Commit 2f6fa2c9 authored by James Smart's avatar James Smart Committed by Christoph Hellwig

lpfc: fix IP Reset processing - wait for RDY before proceeding

Fix IP Reset processing - wait for RDY before proceeding
Signed-off-by: default avatarJames Smart <james.smart@emulex.com>
Signed-off-by: default avatarDick Kennedy <dick.kennedy@emulex.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent c6232197
...@@ -7903,7 +7903,8 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) ...@@ -7903,7 +7903,8 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
LPFC_MBOXQ_t *mboxq; LPFC_MBOXQ_t *mboxq;
uint32_t rc = 0, if_type; uint32_t rc = 0, if_type;
uint32_t shdr_status, shdr_add_status; uint32_t shdr_status, shdr_add_status;
uint32_t rdy_chk, num_resets = 0, reset_again = 0; uint32_t rdy_chk;
uint32_t port_reset = 0;
union lpfc_sli4_cfg_shdr *shdr; union lpfc_sli4_cfg_shdr *shdr;
struct lpfc_register reg_data; struct lpfc_register reg_data;
uint16_t devid; uint16_t devid;
...@@ -7943,77 +7944,62 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) ...@@ -7943,77 +7944,62 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
} }
break; break;
case LPFC_SLI_INTF_IF_TYPE_2: case LPFC_SLI_INTF_IF_TYPE_2:
for (num_resets = 0; wait:
num_resets < MAX_IF_TYPE_2_RESETS;
num_resets++) {
reg_data.word0 = 0;
bf_set(lpfc_sliport_ctrl_end, &reg_data,
LPFC_SLIPORT_LITTLE_ENDIAN);
bf_set(lpfc_sliport_ctrl_ip, &reg_data,
LPFC_SLIPORT_INIT_PORT);
writel(reg_data.word0, phba->sli4_hba.u.if_type2.
CTRLregaddr);
/* flush */
pci_read_config_word(phba->pcidev,
PCI_DEVICE_ID, &devid);
/* /*
* Poll the Port Status Register and wait for RDY for * Poll the Port Status Register and wait for RDY for
* up to 10 seconds. If the port doesn't respond, treat * up to 30 seconds. If the port doesn't respond, treat
* it as an error. If the port responds with RN, start * it as an error.
* the loop again.
*/ */
for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) { for (rdy_chk = 0; rdy_chk < 3000; rdy_chk++) {
msleep(10);
if (lpfc_readl(phba->sli4_hba.u.if_type2. if (lpfc_readl(phba->sli4_hba.u.if_type2.
STATUSregaddr, &reg_data.word0)) { STATUSregaddr, &reg_data.word0)) {
rc = -ENODEV; rc = -ENODEV;
goto out; goto out;
} }
if (bf_get(lpfc_sliport_status_rn, &reg_data))
reset_again++;
if (bf_get(lpfc_sliport_status_rdy, &reg_data)) if (bf_get(lpfc_sliport_status_rdy, &reg_data))
break; break;
msleep(20);
} }
/* if (!bf_get(lpfc_sliport_status_rdy, &reg_data)) {
* If the port responds to the init request with
* reset needed, delay for a bit and restart the loop.
*/
if (reset_again && (rdy_chk < 1000)) {
msleep(10);
reset_again = 0;
continue;
}
/* Detect any port errors. */
if ((bf_get(lpfc_sliport_status_err, &reg_data)) ||
(rdy_chk >= 1000)) {
phba->work_status[0] = readl( phba->work_status[0] = readl(
phba->sli4_hba.u.if_type2.ERR1regaddr); phba->sli4_hba.u.if_type2.ERR1regaddr);
phba->work_status[1] = readl( phba->work_status[1] = readl(
phba->sli4_hba.u.if_type2.ERR2regaddr); phba->sli4_hba.u.if_type2.ERR2regaddr);
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2890 Port error detected during port " "2890 Port not ready, port status reg "
"reset(%d): wait_tmo:%d ms, " "0x%x error 1=0x%x, error 2=0x%x\n",
"port status reg 0x%x, "
"error 1=0x%x, error 2=0x%x\n",
num_resets, rdy_chk*10,
reg_data.word0, reg_data.word0,
phba->work_status[0], phba->work_status[0],
phba->work_status[1]); phba->work_status[1]);
rc = -ENODEV; rc = -ENODEV;
goto out;
} }
if (!port_reset) {
/* /*
* Terminate the outer loop provided the Port indicated * Reset the port now
* ready within 10 seconds.
*/ */
if (rdy_chk < 1000) reg_data.word0 = 0;
break; bf_set(lpfc_sliport_ctrl_end, &reg_data,
LPFC_SLIPORT_LITTLE_ENDIAN);
bf_set(lpfc_sliport_ctrl_ip, &reg_data,
LPFC_SLIPORT_INIT_PORT);
writel(reg_data.word0, phba->sli4_hba.u.if_type2.
CTRLregaddr);
/* flush */
pci_read_config_word(phba->pcidev,
PCI_DEVICE_ID, &devid);
port_reset = 1;
msleep(20);
goto wait;
} else if (bf_get(lpfc_sliport_status_rn, &reg_data)) {
rc = -ENODEV;
goto out;
} }
/* delay driver action following IF_TYPE_2 function reset */
msleep(100);
break; break;
case LPFC_SLI_INTF_IF_TYPE_1: case LPFC_SLI_INTF_IF_TYPE_1:
default: default:
break; break;
...@@ -8021,11 +8007,10 @@ lpfc_pci_function_reset(struct lpfc_hba *phba) ...@@ -8021,11 +8007,10 @@ lpfc_pci_function_reset(struct lpfc_hba *phba)
out: out:
/* Catch the not-ready port failure after a port reset. */ /* Catch the not-ready port failure after a port reset. */
if (num_resets >= MAX_IF_TYPE_2_RESETS) { if (rc) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT, lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3317 HBA not functional: IP Reset Failed " "3317 HBA not functional: IP Reset Failed "
"after (%d) retries, try: " "try: echo fw_reset > board_mode\n");
"echo fw_reset > board_mode\n", num_resets);
rc = -ENODEV; rc = -ENODEV;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment