diff options
author | James Smart <james.smart@emulex.com> | 2014-09-03 12:57:08 -0400 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2014-09-16 12:10:09 -0400 |
commit | 2f6fa2c911167e7a3fda130689a36f55b39ed86d (patch) | |
tree | e5adad6b8e32a0c54fb0fb31e50449df18ce33d0 /drivers/scsi/lpfc/lpfc_init.c | |
parent | c62321978f542e82960264f175c9e33d7279bec5 (diff) |
lpfc: fix IP Reset processing - wait for RDY before proceeding
Fix IP Reset processing - wait for RDY before proceeding
Signed-off-by: James Smart <james.smart@emulex.com>
Signed-off-by: Dick Kennedy <dick.kennedy@emulex.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 109 |
1 files changed, 47 insertions, 62 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 7f54916c4f62..33a24fc0afec 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -7903,7 +7903,8 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) | |||
7903 | LPFC_MBOXQ_t *mboxq; | 7903 | LPFC_MBOXQ_t *mboxq; |
7904 | uint32_t rc = 0, if_type; | 7904 | uint32_t rc = 0, if_type; |
7905 | uint32_t shdr_status, shdr_add_status; | 7905 | uint32_t shdr_status, shdr_add_status; |
7906 | uint32_t rdy_chk, num_resets = 0, reset_again = 0; | 7906 | uint32_t rdy_chk; |
7907 | uint32_t port_reset = 0; | ||
7907 | union lpfc_sli4_cfg_shdr *shdr; | 7908 | union lpfc_sli4_cfg_shdr *shdr; |
7908 | struct lpfc_register reg_data; | 7909 | struct lpfc_register reg_data; |
7909 | uint16_t devid; | 7910 | uint16_t devid; |
@@ -7943,9 +7944,42 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) | |||
7943 | } | 7944 | } |
7944 | break; | 7945 | break; |
7945 | case LPFC_SLI_INTF_IF_TYPE_2: | 7946 | case LPFC_SLI_INTF_IF_TYPE_2: |
7946 | for (num_resets = 0; | 7947 | wait: |
7947 | num_resets < MAX_IF_TYPE_2_RESETS; | 7948 | /* |
7948 | num_resets++) { | 7949 | * Poll the Port Status Register and wait for RDY for |
7950 | * up to 30 seconds. If the port doesn't respond, treat | ||
7951 | * it as an error. | ||
7952 | */ | ||
7953 | for (rdy_chk = 0; rdy_chk < 3000; rdy_chk++) { | ||
7954 | if (lpfc_readl(phba->sli4_hba.u.if_type2. | ||
7955 | STATUSregaddr, ®_data.word0)) { | ||
7956 | rc = -ENODEV; | ||
7957 | goto out; | ||
7958 | } | ||
7959 | if (bf_get(lpfc_sliport_status_rdy, ®_data)) | ||
7960 | break; | ||
7961 | msleep(20); | ||
7962 | } | ||
7963 | |||
7964 | if (!bf_get(lpfc_sliport_status_rdy, ®_data)) { | ||
7965 | phba->work_status[0] = readl( | ||
7966 | phba->sli4_hba.u.if_type2.ERR1regaddr); | ||
7967 | phba->work_status[1] = readl( | ||
7968 | phba->sli4_hba.u.if_type2.ERR2regaddr); | ||
7969 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
7970 | "2890 Port not ready, port status reg " | ||
7971 | "0x%x error 1=0x%x, error 2=0x%x\n", | ||
7972 | reg_data.word0, | ||
7973 | phba->work_status[0], | ||
7974 | phba->work_status[1]); | ||
7975 | rc = -ENODEV; | ||
7976 | goto out; | ||
7977 | } | ||
7978 | |||
7979 | if (!port_reset) { | ||
7980 | /* | ||
7981 | * Reset the port now | ||
7982 | */ | ||
7949 | reg_data.word0 = 0; | 7983 | reg_data.word0 = 0; |
7950 | bf_set(lpfc_sliport_ctrl_end, ®_data, | 7984 | bf_set(lpfc_sliport_ctrl_end, ®_data, |
7951 | LPFC_SLIPORT_LITTLE_ENDIAN); | 7985 | LPFC_SLIPORT_LITTLE_ENDIAN); |
@@ -7956,64 +7990,16 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) | |||
7956 | /* flush */ | 7990 | /* flush */ |
7957 | pci_read_config_word(phba->pcidev, | 7991 | pci_read_config_word(phba->pcidev, |
7958 | PCI_DEVICE_ID, &devid); | 7992 | PCI_DEVICE_ID, &devid); |
7959 | /* | ||
7960 | * Poll the Port Status Register and wait for RDY for | ||
7961 | * up to 10 seconds. If the port doesn't respond, treat | ||
7962 | * it as an error. If the port responds with RN, start | ||
7963 | * the loop again. | ||
7964 | */ | ||
7965 | for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) { | ||
7966 | msleep(10); | ||
7967 | if (lpfc_readl(phba->sli4_hba.u.if_type2. | ||
7968 | STATUSregaddr, ®_data.word0)) { | ||
7969 | rc = -ENODEV; | ||
7970 | goto out; | ||
7971 | } | ||
7972 | if (bf_get(lpfc_sliport_status_rn, ®_data)) | ||
7973 | reset_again++; | ||
7974 | if (bf_get(lpfc_sliport_status_rdy, ®_data)) | ||
7975 | break; | ||
7976 | } | ||
7977 | |||
7978 | /* | ||
7979 | * If the port responds to the init request with | ||
7980 | * reset needed, delay for a bit and restart the loop. | ||
7981 | */ | ||
7982 | if (reset_again && (rdy_chk < 1000)) { | ||
7983 | msleep(10); | ||
7984 | reset_again = 0; | ||
7985 | continue; | ||
7986 | } | ||
7987 | 7993 | ||
7988 | /* Detect any port errors. */ | 7994 | port_reset = 1; |
7989 | if ((bf_get(lpfc_sliport_status_err, ®_data)) || | 7995 | msleep(20); |
7990 | (rdy_chk >= 1000)) { | 7996 | goto wait; |
7991 | phba->work_status[0] = readl( | 7997 | } else if (bf_get(lpfc_sliport_status_rn, ®_data)) { |
7992 | phba->sli4_hba.u.if_type2.ERR1regaddr); | 7998 | rc = -ENODEV; |
7993 | phba->work_status[1] = readl( | 7999 | goto out; |
7994 | phba->sli4_hba.u.if_type2.ERR2regaddr); | ||
7995 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
7996 | "2890 Port error detected during port " | ||
7997 | "reset(%d): wait_tmo:%d ms, " | ||
7998 | "port status reg 0x%x, " | ||
7999 | "error 1=0x%x, error 2=0x%x\n", | ||
8000 | num_resets, rdy_chk*10, | ||
8001 | reg_data.word0, | ||
8002 | phba->work_status[0], | ||
8003 | phba->work_status[1]); | ||
8004 | rc = -ENODEV; | ||
8005 | } | ||
8006 | |||
8007 | /* | ||
8008 | * Terminate the outer loop provided the Port indicated | ||
8009 | * ready within 10 seconds. | ||
8010 | */ | ||
8011 | if (rdy_chk < 1000) | ||
8012 | break; | ||
8013 | } | 8000 | } |
8014 | /* delay driver action following IF_TYPE_2 function reset */ | ||
8015 | msleep(100); | ||
8016 | break; | 8001 | break; |
8002 | |||
8017 | case LPFC_SLI_INTF_IF_TYPE_1: | 8003 | case LPFC_SLI_INTF_IF_TYPE_1: |
8018 | default: | 8004 | default: |
8019 | break; | 8005 | break; |
@@ -8021,11 +8007,10 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) | |||
8021 | 8007 | ||
8022 | out: | 8008 | out: |
8023 | /* Catch the not-ready port failure after a port reset. */ | 8009 | /* Catch the not-ready port failure after a port reset. */ |
8024 | if (num_resets >= MAX_IF_TYPE_2_RESETS) { | 8010 | if (rc) { |
8025 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 8011 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
8026 | "3317 HBA not functional: IP Reset Failed " | 8012 | "3317 HBA not functional: IP Reset Failed " |
8027 | "after (%d) retries, try: " | 8013 | "try: echo fw_reset > board_mode\n"); |
8028 | "echo fw_reset > board_mode\n", num_resets); | ||
8029 | rc = -ENODEV; | 8014 | rc = -ENODEV; |
8030 | } | 8015 | } |
8031 | 8016 | ||