diff options
-rw-r--r-- | drivers/scsi/cxlflash/superpipe.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/drivers/scsi/cxlflash/superpipe.c b/drivers/scsi/cxlflash/superpipe.c index d8a5cb3cd2bd..ce1507023132 100644 --- a/drivers/scsi/cxlflash/superpipe.c +++ b/drivers/scsi/cxlflash/superpipe.c | |||
@@ -1615,6 +1615,13 @@ err1: | |||
1615 | * place at the same time and the failure was due to CXL services being | 1615 | * place at the same time and the failure was due to CXL services being |
1616 | * unable to keep up. | 1616 | * unable to keep up. |
1617 | * | 1617 | * |
1618 | * As this routine is called on ioctl context, it holds the ioctl r/w | ||
1619 | * semaphore that is used to drain ioctls in recovery scenarios. The | ||
1620 | * implementation to achieve the pacing described above (a local mutex) | ||
1621 | * requires that the ioctl r/w semaphore be dropped and reacquired to | ||
1622 | * avoid a 3-way deadlock when multiple process recoveries operate in | ||
1623 | * parallel. | ||
1624 | * | ||
1618 | * Because a user can detect an error condition before the kernel, it is | 1625 | * Because a user can detect an error condition before the kernel, it is |
1619 | * quite possible for this routine to act as the kernel's EEH detection | 1626 | * quite possible for this routine to act as the kernel's EEH detection |
1620 | * source (MMIO read of mbox_r). Because of this, there is a window of | 1627 | * source (MMIO read of mbox_r). Because of this, there is a window of |
@@ -1642,9 +1649,17 @@ static int cxlflash_afu_recover(struct scsi_device *sdev, | |||
1642 | int rc = 0; | 1649 | int rc = 0; |
1643 | 1650 | ||
1644 | atomic_inc(&cfg->recovery_threads); | 1651 | atomic_inc(&cfg->recovery_threads); |
1652 | up_read(&cfg->ioctl_rwsem); | ||
1645 | rc = mutex_lock_interruptible(mutex); | 1653 | rc = mutex_lock_interruptible(mutex); |
1654 | down_read(&cfg->ioctl_rwsem); | ||
1646 | if (rc) | 1655 | if (rc) |
1647 | goto out; | 1656 | goto out; |
1657 | rc = check_state(cfg); | ||
1658 | if (rc) { | ||
1659 | dev_err(dev, "%s: Failed state! rc=%d\n", __func__, rc); | ||
1660 | rc = -ENODEV; | ||
1661 | goto out; | ||
1662 | } | ||
1648 | 1663 | ||
1649 | dev_dbg(dev, "%s: reason 0x%016llX rctxid=%016llX\n", | 1664 | dev_dbg(dev, "%s: reason 0x%016llX rctxid=%016llX\n", |
1650 | __func__, recover->reason, rctxid); | 1665 | __func__, recover->reason, rctxid); |