aboutsummaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMatthew R. Ochs2017-08-25 17:18:03 -0500
committerMartin K. Petersen2017-08-25 18:23:34 -0400
commit1a9e394154e34728f58c1f697b993aaaf89a4db2 (patch)
treeb2df6f5402857384d239733478641e32d0333642 /drivers/scsi
parent48a17ad5931c3832eec68411620bc3527021c193 (diff)
scsi: cxlflash: Avoid double mutex unlock
The AFU recovery routine uses an interruptible mutex to control the flow of in-flight recoveries. Upon receiving an interruptible signal the code branches to a common exit path which wrongly assumes the mutex is held. Add a local variable to track when the mutex should be unlocked. Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/cxlflash/superpipe.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c
index 08da593cb2f6..ed46e8df2e42 100644
--- a/drivers/scsi/cxlflash/superpipe.c
+++ b/drivers/scsi/cxlflash/superpipe.c
@@ -1651,6 +1651,7 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
u64 ctxid = DECODE_CTXID(recover->context_id),
rctxid = recover->context_id;
long reg;
+ bool locked = true;
int lretry = 20; /* up to 2 seconds */
int new_adap_fd = -1;
int rc = 0;
@@ -1659,8 +1660,11 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
up_read(&cfg->ioctl_rwsem);
rc = mutex_lock_interruptible(mutex);
down_read(&cfg->ioctl_rwsem);
- if (rc)
+ if (rc) {
+ locked = false;
goto out;
+ }
+
rc = check_state(cfg);
if (rc) {
dev_err(dev, "%s: Failed state rc=%d\n", __func__, rc);
@@ -1694,8 +1698,10 @@ retry_recover:
mutex_unlock(mutex);
msleep(100);
rc = mutex_lock_interruptible(mutex);
- if (rc)
+ if (rc) {
+ locked = false;
goto out;
+ }
goto retry_recover;
}
@@ -1739,7 +1745,8 @@ retry_recover:
out:
if (likely(ctxi))
put_context(ctxi);
- mutex_unlock(mutex);
+ if (locked)
+ mutex_unlock(mutex);
atomic_dec_if_positive(&cfg->recovery_threads);
return rc;
}