mtd: powernv_flash: Use opal_async_wait_response_interruptible()
The OPAL calls performed in this driver shouldn't be using opal_async_wait_response() as this performs a wait_event() which, on long running OPAL calls could result in hung task warnings. wait_event() prevents timely signal delivery which is also undesirable. This patch also attempts to quieten down the use of dev_err() when errors haven't actually occurred and also to return better information up the stack rather than always -EIO. Signed-off-by: Cyril Bur <cyrilbur@gmail.com> Acked-by: Boris Brezillon <boris.brezillon@free-electrons.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
parent
77adbd2207
commit
6f469b67ff
|
@ -89,33 +89,46 @@ static int powernv_flash_async_op(struct mtd_info *mtd, enum flash_op op,
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
if (rc == OPAL_SUCCESS)
|
||||
goto out_success;
|
||||
if (rc == OPAL_ASYNC_COMPLETION) {
|
||||
rc = opal_async_wait_response_interruptible(token, &msg);
|
||||
if (rc) {
|
||||
/*
|
||||
* If we return the mtd core will free the
|
||||
* buffer we've just passed to OPAL but OPAL
|
||||
* will continue to read or write from that
|
||||
* memory.
|
||||
* It may be tempting to ultimately return 0
|
||||
* if we're doing a read or a write since we
|
||||
* are going to end up waiting until OPAL is
|
||||
* done. However, because the MTD core sends
|
||||
* us the userspace request in chunks, we need
|
||||
* it to know we've been interrupted.
|
||||
*/
|
||||
rc = -EINTR;
|
||||
if (opal_async_wait_response(token, &msg))
|
||||
dev_err(dev, "opal_async_wait_response() failed\n");
|
||||
goto out;
|
||||
}
|
||||
rc = opal_get_async_rc(msg);
|
||||
}
|
||||
|
||||
if (rc != OPAL_ASYNC_COMPLETION) {
|
||||
/*
|
||||
* OPAL does mutual exclusion on the flash, it will return
|
||||
* OPAL_BUSY.
|
||||
* During firmware updates by the service processor OPAL may
|
||||
* be (temporarily) prevented from accessing the flash, in
|
||||
* this case OPAL will also return OPAL_BUSY.
|
||||
* Both cases aren't errors exactly but the flash could have
|
||||
* changed, userspace should be informed.
|
||||
*/
|
||||
if (rc != OPAL_SUCCESS && rc != OPAL_BUSY)
|
||||
dev_err(dev, "opal_flash_async_op(op=%d) failed (rc %d)\n",
|
||||
op, rc);
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = opal_async_wait_response(token, &msg);
|
||||
if (rc) {
|
||||
dev_err(dev, "opal async wait failed (rc %d)\n", rc);
|
||||
rc = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = opal_get_async_rc(msg);
|
||||
out_success:
|
||||
if (rc == OPAL_SUCCESS) {
|
||||
rc = 0;
|
||||
if (retlen)
|
||||
*retlen = len;
|
||||
} else {
|
||||
rc = -EIO;
|
||||
}
|
||||
if (rc == OPAL_SUCCESS && retlen)
|
||||
*retlen = len;
|
||||
|
||||
rc = opal_error_code(rc);
|
||||
out:
|
||||
opal_async_release_token(token);
|
||||
return rc;
|
||||
|
|
Loading…
Reference in New Issue