aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew R. Ochs <mrochs@linux.vnet.ibm.com>2016-09-02 16:39:30 -0400
committerMartin K. Petersen <martin.petersen@oracle.com>2016-09-14 12:45:06 -0400
commit1d3324c382b1a617eb567e3650dcb51f22dfec9a (patch)
tree9a7fb64a89a7cbdd5e3f6c74df0d8be1af9cb10f
parentbabf985d1e1b0677cb264acd01319d2b9c8f4327 (diff)
scsi: cxlflash: Fix to avoid EEH and host reset collisions
The EEH reset handler is ignorant to the current state of the driver when processing a frozen event and initiating a device reset. This can be an issue if an EEH event occurs while a user or stack initiated reset is executing. More specifically, if an EEH occurs while the SCSI host reset handler is active, the reset initiated by the EEH thread will likely collide with the host reset thread. This can leave the device in an inconsistent state, or worse, cause a system crash. As a remedy, the EEH handler is updated to evaluate the device state and take appropriate action (proceed, wait, or disconnect host). The host reset handler is also updated to handle situations where an EEH occurred during a host reset. In such situations, the host reset handler will delay reporting back a success to give the EEH reset an opportunity to complete. Signed-off-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com> Acked-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/cxlflash/main.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 4c2559adf723..4ef523505364 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -2042,6 +2042,11 @@ retry:
2042 * cxlflash_eh_host_reset_handler() - reset the host adapter 2042 * cxlflash_eh_host_reset_handler() - reset the host adapter
2043 * @scp: SCSI command from stack identifying host. 2043 * @scp: SCSI command from stack identifying host.
2044 * 2044 *
2045 * Following a reset, the state is evaluated again in case an EEH occurred
2046 * during the reset. In such a scenario, the host reset will either yield
2047 * until the EEH recovery is complete or return success or failure based
2048 * upon the current device state.
2049 *
2045 * Return: 2050 * Return:
2046 * SUCCESS as defined in scsi/scsi.h 2051 * SUCCESS as defined in scsi/scsi.h
2047 * FAILED as defined in scsi/scsi.h 2052 * FAILED as defined in scsi/scsi.h
@@ -2074,7 +2079,8 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp)
2074 } else 2079 } else
2075 cfg->state = STATE_NORMAL; 2080 cfg->state = STATE_NORMAL;
2076 wake_up_all(&cfg->reset_waitq); 2081 wake_up_all(&cfg->reset_waitq);
2077 break; 2082 ssleep(1);
2083 /* fall through */
2078 case STATE_RESET: 2084 case STATE_RESET:
2079 wait_event(cfg->reset_waitq, cfg->state != STATE_RESET); 2085 wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
2080 if (cfg->state == STATE_NORMAL) 2086 if (cfg->state == STATE_NORMAL)
@@ -2590,6 +2596,9 @@ out_remove:
2590 * @pdev: PCI device struct. 2596 * @pdev: PCI device struct.
2591 * @state: PCI channel state. 2597 * @state: PCI channel state.
2592 * 2598 *
2599 * When an EEH occurs during an active reset, wait until the reset is
2600 * complete and then take action based upon the device state.
2601 *
2593 * Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT 2602 * Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
2594 */ 2603 */
2595static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev, 2604static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev,
@@ -2603,6 +2612,10 @@ static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev,
2603 2612
2604 switch (state) { 2613 switch (state) {
2605 case pci_channel_io_frozen: 2614 case pci_channel_io_frozen:
2615 wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
2616 if (cfg->state == STATE_FAILTERM)
2617 return PCI_ERS_RESULT_DISCONNECT;
2618
2606 cfg->state = STATE_RESET; 2619 cfg->state = STATE_RESET;
2607 scsi_block_requests(cfg->host); 2620 scsi_block_requests(cfg->host);
2608 drain_ioctls(cfg); 2621 drain_ioctls(cfg);