From 0a27ae514740b4d64b586043d6b837ad5d0c40f8 Mon Sep 17 00:00:00 2001 From: "Matthew R. Ochs" Date: Wed, 21 Oct 2015 15:11:52 -0500 Subject: cxlflash: Fix to avoid CXL services during EEH During an EEH freeze event, certain CXL services should not be called until after the hardware reset has taken place. Doing so can result in unnecessary failures and possibly cause other ill effects by triggering hardware accesses. This translates to a requirement to quiesce all threads that may potentially use CXL runtime service during this window. In particular, multiple ioctls make use of the CXL services when acting on contexts on behalf of the user. Thus, it is essential to 'drain' running ioctls _before_ proceeding with handling the EEH freeze event. Create the ability to drain ioctls by wrapping the ioctl handler call in a read semaphore and then implementing a small routine that obtains the write semaphore, effectively creating a wait point for all currently executing ioctls. Signed-off-by: Matthew R. Ochs Signed-off-by: Manoj N. Kumar Reviewed-by: Brian King Reviewed-by: Daniel Axtens Reviewed-by: Tomas Henzl Signed-off-by: James Bottomley --- drivers/scsi/cxlflash/main.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'drivers/scsi/cxlflash/main.c') diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 3e3ccf16e7c2..6e85c77a19ed 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -2311,6 +2311,7 @@ static int cxlflash_probe(struct pci_dev *pdev, cfg->lr_port = -1; mutex_init(&cfg->ctx_tbl_list_mutex); mutex_init(&cfg->ctx_recovery_mutex); + init_rwsem(&cfg->ioctl_rwsem); INIT_LIST_HEAD(&cfg->ctx_err_recovery); INIT_LIST_HEAD(&cfg->lluns); @@ -2364,6 +2365,19 @@ out_remove: goto out; } +/** + * drain_ioctls() - wait until all currently executing ioctls have completed + * @cfg: Internal structure associated with the host. + * + * Obtain write access to read/write semaphore that wraps ioctl + * handling to 'drain' ioctls currently executing. + */ +static void drain_ioctls(struct cxlflash_cfg *cfg) +{ + down_write(&cfg->ioctl_rwsem); + up_write(&cfg->ioctl_rwsem); +} + /** * cxlflash_pci_error_detected() - called when a PCI error is detected * @pdev: PCI device struct. @@ -2383,16 +2397,14 @@ static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev, switch (state) { case pci_channel_io_frozen: cfg->state = STATE_LIMBO; - - /* Turn off legacy I/O */ scsi_block_requests(cfg->host); + drain_ioctls(cfg); rc = cxlflash_mark_contexts_error(cfg); if (unlikely(rc)) dev_err(dev, "%s: Failed to mark user contexts!(%d)\n", __func__, rc); term_mc(cfg, UNDO_START); stop_afu(cfg); - return PCI_ERS_RESULT_NEED_RESET; case pci_channel_io_perm_failure: cfg->state = STATE_FAILTERM; -- cgit v1.2.3