From 6f469b67ff8a3ec2698ef1041229e111065013ce Mon Sep 17 00:00:00 2001 From: Cyril Bur Date: Fri, 3 Nov 2017 13:41:46 +1100 Subject: 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 Acked-by: Boris Brezillon Signed-off-by: Michael Ellerman --- drivers/mtd/devices/powernv_flash.c | 57 +++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 22 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/devices/powernv_flash.c b/drivers/mtd/devices/powernv_flash.c index 3343d4f5c4f3..26f9feaa5d17 100644 --- a/drivers/mtd/devices/powernv_flash.c +++ b/drivers/mtd/devices/powernv_flash.c @@ -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; -- cgit v1.2.3