diff options
Diffstat (limited to 'drivers/scsi/cxlflash/main.c')
-rw-r--r-- | drivers/scsi/cxlflash/main.c | 81 |
1 files changed, 35 insertions, 46 deletions
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 661bb94e2548..b301655f91cd 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c @@ -823,17 +823,6 @@ static void notify_shutdown(struct cxlflash_cfg *cfg, bool wait) } /** - * cxlflash_shutdown() - shutdown handler - * @pdev: PCI device associated with the host. - */ -static void cxlflash_shutdown(struct pci_dev *pdev) -{ - struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); - - notify_shutdown(cfg, false); -} - -/** * cxlflash_remove() - PCI entry point to tear down host * @pdev: PCI device associated with the host. * @@ -844,6 +833,11 @@ static void cxlflash_remove(struct pci_dev *pdev) struct cxlflash_cfg *cfg = pci_get_drvdata(pdev); ulong lock_flags; + if (!pci_is_enabled(pdev)) { + pr_debug("%s: Device is disabled\n", __func__); + return; + } + /* If a Task Management Function is active, wait for it to complete * before continuing with remove. */ @@ -1046,6 +1040,8 @@ static int wait_port_online(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) do { msleep(delay_us / 1000); status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]); + if (status == U64_MAX) + nretry /= 2; } while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_ONLINE && nretry--); @@ -1077,6 +1073,8 @@ static int wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) do { msleep(delay_us / 1000); status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]); + if (status == U64_MAX) + nretry /= 2; } while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_OFFLINE && nretry--); @@ -1095,42 +1093,25 @@ static int wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry) * online. This toggling action can cause this routine to delay up to a few * seconds. When configured to use the internal LUN feature of the AFU, a * failure to come online is overridden. - * - * Return: - * 0 when the WWPN is successfully written and the port comes back online - * -1 when the port fails to go offline or come back up online */ -static int afu_set_wwpn(struct afu *afu, int port, __be64 __iomem *fc_regs, - u64 wwpn) +static void afu_set_wwpn(struct afu *afu, int port, __be64 __iomem *fc_regs, + u64 wwpn) { - int rc = 0; - set_port_offline(fc_regs); - if (!wait_port_offline(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, FC_PORT_STATUS_RETRY_CNT)) { pr_debug("%s: wait on port %d to go offline timed out\n", __func__, port); - rc = -1; /* but continue on to leave the port back online */ } - if (rc == 0) - writeq_be(wwpn, &fc_regs[FC_PNAME / 8]); - - /* Always return success after programming WWPN */ - rc = 0; + writeq_be(wwpn, &fc_regs[FC_PNAME / 8]); set_port_online(fc_regs); - if (!wait_port_online(fc_regs, FC_PORT_STATUS_RETRY_INTERVAL_US, FC_PORT_STATUS_RETRY_CNT)) { - pr_err("%s: wait on port %d to go online timed out\n", - __func__, port); + pr_debug("%s: wait on port %d to go online timed out\n", + __func__, port); } - - pr_debug("%s: returning rc=%d\n", __func__, rc); - - return rc; } /** @@ -1187,7 +1168,7 @@ static const struct asyc_intr_info ainfo[] = { {SISL_ASTATUS_FC0_LOGI_F, "login failed", 0, CLR_FC_ERROR}, {SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, SCAN_HOST}, {SISL_ASTATUS_FC0_LINK_DN, "link down", 0, 0}, - {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, SCAN_HOST}, + {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, 0}, {SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET}, {SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0}, {SISL_ASTATUS_FC1_CRC_T, "CRC threshold exceeded", 1, LINK_RESET}, @@ -1195,7 +1176,7 @@ static const struct asyc_intr_info ainfo[] = { {SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR}, {SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, SCAN_HOST}, {SISL_ASTATUS_FC1_LINK_DN, "link down", 1, 0}, - {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, SCAN_HOST}, + {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, 0}, {0x0, "", 0, 0} /* terminator */ }; @@ -1631,15 +1612,10 @@ static int init_global(struct cxlflash_cfg *cfg) [FC_CRC_THRESH / 8]); /* Set WWPNs. If already programmed, wwpn[i] is 0 */ - if (wwpn[i] != 0 && - afu_set_wwpn(afu, i, - &afu->afu_map->global.fc_regs[i][0], - wwpn[i])) { - dev_err(dev, "%s: failed to set WWPN on port %d\n", - __func__, i); - rc = -EIO; - goto out; - } + if (wwpn[i] != 0) + afu_set_wwpn(afu, i, + &afu->afu_map->global.fc_regs[i][0], + wwpn[i]); /* Programming WWPN back to back causes additional * offline/online transitions and a PLOGI */ @@ -2048,6 +2024,11 @@ retry: * cxlflash_eh_host_reset_handler() - reset the host adapter * @scp: SCSI command from stack identifying host. * + * Following a reset, the state is evaluated again in case an EEH occurred + * during the reset. In such a scenario, the host reset will either yield + * until the EEH recovery is complete or return success or failure based + * upon the current device state. + * * Return: * SUCCESS as defined in scsi/scsi.h * FAILED as defined in scsi/scsi.h @@ -2080,7 +2061,8 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp) } else cfg->state = STATE_NORMAL; wake_up_all(&cfg->reset_waitq); - break; + ssleep(1); + /* fall through */ case STATE_RESET: wait_event(cfg->reset_waitq, cfg->state != STATE_RESET); if (cfg->state == STATE_NORMAL) @@ -2596,6 +2578,9 @@ out_remove: * @pdev: PCI device struct. * @state: PCI channel state. * + * When an EEH occurs during an active reset, wait until the reset is + * complete and then take action based upon the device state. + * * Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT */ static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev, @@ -2609,6 +2594,10 @@ static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev, switch (state) { case pci_channel_io_frozen: + wait_event(cfg->reset_waitq, cfg->state != STATE_RESET); + if (cfg->state == STATE_FAILTERM) + return PCI_ERS_RESULT_DISCONNECT; + cfg->state = STATE_RESET; scsi_block_requests(cfg->host); drain_ioctls(cfg); @@ -2685,7 +2674,7 @@ static struct pci_driver cxlflash_driver = { .id_table = cxlflash_pci_table, .probe = cxlflash_probe, .remove = cxlflash_remove, - .shutdown = cxlflash_shutdown, + .shutdown = cxlflash_remove, .err_handler = &cxlflash_err_handler, }; |