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:
Cyril Bur 2017-11-03 13:41:46 +11:00 committed by Michael Ellerman
parent 77adbd2207
commit 6f469b67ff
1 changed files with 35 additions and 22 deletions

View File

@ -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;