Commit 6f469b67 authored by Cyril Bur's avatar Cyril Bur Committed by Michael Ellerman

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: default avatarCyril Bur <cyrilbur@gmail.com>
Acked-by: default avatarBoris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 77adbd22
...@@ -89,33 +89,46 @@ static int powernv_flash_async_op(struct mtd_info *mtd, enum flash_op op, ...@@ -89,33 +89,46 @@ static int powernv_flash_async_op(struct mtd_info *mtd, enum flash_op op,
return -EIO; return -EIO;
} }
if (rc == OPAL_SUCCESS) if (rc == OPAL_ASYNC_COMPLETION) {
goto out_success; rc = opal_async_wait_response_interruptible(token, &msg);
if (rc != OPAL_ASYNC_COMPLETION) {
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) { if (rc) {
dev_err(dev, "opal async wait failed (rc %d)\n", rc); /*
rc = -EIO; * 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; goto out;
} }
rc = opal_get_async_rc(msg); rc = opal_get_async_rc(msg);
out_success:
if (rc == OPAL_SUCCESS) {
rc = 0;
if (retlen)
*retlen = len;
} else {
rc = -EIO;
} }
/*
* 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);
if (rc == OPAL_SUCCESS && retlen)
*retlen = len;
rc = opal_error_code(rc);
out: out:
opal_async_release_token(token); opal_async_release_token(token);
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment