Commit 0f154226 authored by James Smart's avatar James Smart Committed by Martin K. Petersen

scsi: lpfc: Fix device recovery errors after PLOGI failures

When target-side fault injections are made, the driver isn't reconnecting
to the remote port. The driver is logging "2753" error messages which
state:

"PLOGI failure DID:1B2400 Status:x3/xf0240008"

The failures status is indicating a Illegal field error, which points to
the Temporary RPI field being used for the ELS. This error typically means
the driver used an RPI that was already registered (shouldn't be registered
if using it in this context).

Study has found that if the driver were in discovery attempts and
encountered an error, it wouldn't flag the temporary rpi in error.  Yet the
rpi was released for reallocation in these error paths and another ELS
could allocate the rpi. In the failure situation a retry was done on an ELS
that had encountered an error, and as the rpi wasn't marked in error, the
ELS reused the rpi it originally allocated. But that rpi had been allocated
by a different ELS issued after the original error and before the retry
attempt. The different ELS had succeeded and the RPI was registered.

Fix by marking the rpi state for the node to be in error, aka as needing
reallocation, upon an error in the els processing.  Error state marking is
always done prior to release back to the internal rpi free list, which the
driver wasn't doing in cases prior.

Also enhanced some of the logging to help in the next case of problem
troubleshooting.

Link: https://lore.kernel.org/r/20190922035906.10977-7-jsmart2021@gmail.comSigned-off-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 97acd001
...@@ -4046,7 +4046,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -4046,7 +4046,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
ndlp->nlp_flag |= NLP_RPI_REGISTERED; ndlp->nlp_flag |= NLP_RPI_REGISTERED;
ndlp->nlp_type |= NLP_FABRIC; ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY,
"0003 rpi:%x DID:%x flg:%x %d map%x x%px\n", "0003 rpi:%x DID:%x flg:%x %d map%x x%px\n",
ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
kref_read(&ndlp->kref), kref_read(&ndlp->kref),
...@@ -4575,8 +4575,10 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ...@@ -4575,8 +4575,10 @@ lpfc_enable_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
return ndlp; return ndlp;
free_rpi: free_rpi:
if (phba->sli_rev == LPFC_SLI_REV4) if (phba->sli_rev == LPFC_SLI_REV4) {
lpfc_sli4_free_rpi(vport->phba, rpi); lpfc_sli4_free_rpi(vport->phba, rpi);
ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
}
return NULL; return NULL;
} }
...@@ -4835,6 +4837,7 @@ lpfc_nlp_logo_unreg(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -4835,6 +4837,7 @@ lpfc_nlp_logo_unreg(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
if (ndlp->nlp_flag & NLP_RELEASE_RPI) { if (ndlp->nlp_flag & NLP_RELEASE_RPI) {
lpfc_sli4_free_rpi(vport->phba, ndlp->nlp_rpi); lpfc_sli4_free_rpi(vport->phba, ndlp->nlp_rpi);
ndlp->nlp_flag &= ~NLP_RELEASE_RPI; ndlp->nlp_flag &= ~NLP_RELEASE_RPI;
ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
} }
ndlp->nlp_flag &= ~NLP_UNREG_INP; ndlp->nlp_flag &= ~NLP_UNREG_INP;
} }
...@@ -4898,7 +4901,8 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -4898,7 +4901,8 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
if (ndlp->nlp_flag & NLP_RPI_REGISTERED || if (ndlp->nlp_flag & NLP_RPI_REGISTERED ||
ndlp->nlp_flag & NLP_REG_LOGIN_SEND) { ndlp->nlp_flag & NLP_REG_LOGIN_SEND) {
if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND) if (ndlp->nlp_flag & NLP_REG_LOGIN_SEND)
lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, lpfc_printf_vlog(vport, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"3366 RPI x%x needs to be " "3366 RPI x%x needs to be "
"unregistered nlp_flag x%x " "unregistered nlp_flag x%x "
"did x%x\n", "did x%x\n",
...@@ -4909,7 +4913,8 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -4909,7 +4913,8 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
* no need to queue up another one. * no need to queue up another one.
*/ */
if (ndlp->nlp_flag & NLP_UNREG_INP) { if (ndlp->nlp_flag & NLP_UNREG_INP) {
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, lpfc_printf_vlog(vport, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"1436 unreg_rpi SKIP UNREG x%x on " "1436 unreg_rpi SKIP UNREG x%x on "
"NPort x%x deferred x%x flg x%x " "NPort x%x deferred x%x flg x%x "
"Data: x%px\n", "Data: x%px\n",
...@@ -4939,7 +4944,8 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -4939,7 +4944,8 @@ lpfc_unreg_rpi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
(!(vport->fc_flag & FC_OFFLINE_MODE))) (!(vport->fc_flag & FC_OFFLINE_MODE)))
ndlp->nlp_flag |= NLP_UNREG_INP; ndlp->nlp_flag |= NLP_UNREG_INP;
lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY, lpfc_printf_vlog(vport, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"1433 unreg_rpi UNREG x%x on " "1433 unreg_rpi UNREG x%x on "
"NPort x%x deferred flg x%x " "NPort x%x deferred flg x%x "
"Data:x%px\n", "Data:x%px\n",
...@@ -5195,8 +5201,10 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -5195,8 +5201,10 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
/* For this case we need to cleanup the default rpi /* For this case we need to cleanup the default rpi
* allocated by the firmware. * allocated by the firmware.
*/ */
lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, lpfc_printf_vlog(vport, KERN_INFO,
"0005 rpi:%x DID:%x flg:%x %d map:%x x%px\n", LOG_NODE | LOG_DISCOVERY,
"0005 Cleanup Default rpi:x%x DID:x%x flg:x%x "
"ref %d map:x%x ndlp x%px\n",
ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
kref_read(&ndlp->kref), kref_read(&ndlp->kref),
ndlp->nlp_usg_map, ndlp); ndlp->nlp_usg_map, ndlp);
...@@ -5233,8 +5241,9 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp) ...@@ -5233,8 +5241,9 @@ lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
*/ */
lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE, lpfc_printf_vlog(vport, KERN_WARNING, LOG_NODE,
"0940 removed node x%px DID x%x " "0940 removed node x%px DID x%x "
" rport not null x%px\n", "rpi %d rport not null x%px\n",
ndlp, ndlp->nlp_DID, ndlp->rport); ndlp, ndlp->nlp_DID, ndlp->nlp_rpi,
ndlp->rport);
rport = ndlp->rport; rport = ndlp->rport;
rdata = rport->dd_data; rdata = rport->dd_data;
rdata->pnode = NULL; rdata->pnode = NULL;
...@@ -6026,7 +6035,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -6026,7 +6035,7 @@ lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
ndlp->nlp_flag |= NLP_RPI_REGISTERED; ndlp->nlp_flag |= NLP_RPI_REGISTERED;
ndlp->nlp_type |= NLP_FABRIC; ndlp->nlp_type |= NLP_FABRIC;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE); lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNMAPPED_NODE);
lpfc_printf_vlog(vport, KERN_INFO, LOG_SLI, lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY,
"0004 rpi:%x DID:%x flg:%x %d map:%x x%px\n", "0004 rpi:%x DID:%x flg:%x %d map:%x x%px\n",
ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_flag,
kref_read(&ndlp->kref), kref_read(&ndlp->kref),
...@@ -6215,12 +6224,12 @@ lpfc_nlp_init(struct lpfc_vport *vport, uint32_t did) ...@@ -6215,12 +6224,12 @@ lpfc_nlp_init(struct lpfc_vport *vport, uint32_t did)
INIT_LIST_HEAD(&ndlp->nlp_listp); INIT_LIST_HEAD(&ndlp->nlp_listp);
if (vport->phba->sli_rev == LPFC_SLI_REV4) { if (vport->phba->sli_rev == LPFC_SLI_REV4) {
ndlp->nlp_rpi = rpi; ndlp->nlp_rpi = rpi;
lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE, lpfc_printf_vlog(vport, KERN_INFO, LOG_NODE | LOG_DISCOVERY,
"0007 rpi:%x DID:%x flg:%x refcnt:%d " "0007 Init New ndlp x%px, rpi:x%x DID:%x "
"map:%x x%px\n", ndlp->nlp_rpi, ndlp->nlp_DID, "flg:x%x refcnt:%d map:x%x\n",
ndlp->nlp_flag, ndlp, ndlp->nlp_rpi, ndlp->nlp_DID,
kref_read(&ndlp->kref), ndlp->nlp_flag, kref_read(&ndlp->kref),
ndlp->nlp_usg_map, ndlp); ndlp->nlp_usg_map);
ndlp->active_rrqs_xri_bitmap = ndlp->active_rrqs_xri_bitmap =
mempool_alloc(vport->phba->active_rrq_pool, mempool_alloc(vport->phba->active_rrq_pool,
...@@ -6449,7 +6458,8 @@ lpfc_fcf_inuse(struct lpfc_hba *phba) ...@@ -6449,7 +6458,8 @@ lpfc_fcf_inuse(struct lpfc_hba *phba)
goto out; goto out;
} else if (ndlp->nlp_flag & NLP_RPI_REGISTERED) { } else if (ndlp->nlp_flag & NLP_RPI_REGISTERED) {
ret = 1; ret = 1;
lpfc_printf_log(phba, KERN_INFO, LOG_ELS, lpfc_printf_log(phba, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"2624 RPI %x DID %x flag %x " "2624 RPI %x DID %x flag %x "
"still logged in\n", "still logged in\n",
ndlp->nlp_rpi, ndlp->nlp_DID, ndlp->nlp_rpi, ndlp->nlp_DID,
......
...@@ -3053,11 +3053,12 @@ lpfc_sli4_node_prep(struct lpfc_hba *phba) ...@@ -3053,11 +3053,12 @@ lpfc_sli4_node_prep(struct lpfc_hba *phba)
continue; continue;
} }
ndlp->nlp_rpi = rpi; ndlp->nlp_rpi = rpi;
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_NODE, lpfc_printf_vlog(ndlp->vport, KERN_INFO,
"0009 rpi:%x DID:%x " LOG_NODE | LOG_DISCOVERY,
"flg:%x map:%x x%px\n", ndlp->nlp_rpi, "0009 Assign RPI x%x to ndlp x%px "
ndlp->nlp_DID, ndlp->nlp_flag, "DID:x%06x flg:x%x map:x%x\n",
ndlp->nlp_usg_map, ndlp); ndlp->nlp_rpi, ndlp, ndlp->nlp_DID,
ndlp->nlp_flag, ndlp->nlp_usg_map);
} }
} }
lpfc_destroy_vport_work_array(phba, vports); lpfc_destroy_vport_work_array(phba, vports);
...@@ -3453,10 +3454,15 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) ...@@ -3453,10 +3454,15 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
list_for_each_entry_safe(ndlp, next_ndlp, list_for_each_entry_safe(ndlp, next_ndlp,
&vports[i]->fc_nodes, &vports[i]->fc_nodes,
nlp_listp) { nlp_listp) {
if (!NLP_CHK_NODE_ACT(ndlp)) if ((!NLP_CHK_NODE_ACT(ndlp)) ||
continue; ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) /* Driver must assume RPI is invalid for
* any unused or inactive node.
*/
ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
continue; continue;
}
if (ndlp->nlp_type & NLP_FABRIC) { if (ndlp->nlp_type & NLP_FABRIC) {
lpfc_disc_state_machine(vports[i], ndlp, lpfc_disc_state_machine(vports[i], ndlp,
NULL, NLP_EVT_DEVICE_RECOVERY); NULL, NLP_EVT_DEVICE_RECOVERY);
...@@ -3472,16 +3478,16 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action) ...@@ -3472,16 +3478,16 @@ lpfc_offline_prep(struct lpfc_hba *phba, int mbx_action)
* comes back online. * comes back online.
*/ */
if (phba->sli_rev == LPFC_SLI_REV4) { if (phba->sli_rev == LPFC_SLI_REV4) {
lpfc_printf_vlog(ndlp->vport, lpfc_printf_vlog(ndlp->vport, KERN_INFO,
KERN_INFO, LOG_NODE, LOG_NODE | LOG_DISCOVERY,
"0011 lpfc_offline: " "0011 Free RPI x%x on "
"ndlp:x%px did %x " "ndlp:x%px did x%x "
"usgmap:x%x rpi:%x\n", "usgmap:x%x\n",
ndlp, ndlp->nlp_DID, ndlp->nlp_rpi, ndlp,
ndlp->nlp_usg_map, ndlp->nlp_DID,
ndlp->nlp_rpi); ndlp->nlp_usg_map);
lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi); lpfc_sli4_free_rpi(phba, ndlp->nlp_rpi);
ndlp->nlp_rpi = LPFC_RPI_ALLOC_ERROR;
} }
lpfc_unreg_rpi(vports[i], ndlp); lpfc_unreg_rpi(vports[i], ndlp);
} }
......
...@@ -18131,8 +18131,9 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba) ...@@ -18131,8 +18131,9 @@ lpfc_sli4_alloc_rpi(struct lpfc_hba *phba)
phba->sli4_hba.max_cfg_param.rpi_used++; phba->sli4_hba.max_cfg_param.rpi_used++;
phba->sli4_hba.rpi_count++; phba->sli4_hba.rpi_count++;
} }
lpfc_printf_log(phba, KERN_INFO, LOG_SLI, lpfc_printf_log(phba, KERN_INFO,
"0001 rpi:%x max:%x lim:%x\n", LOG_NODE | LOG_DISCOVERY,
"0001 Allocated rpi:x%x max:x%x lim:x%x\n",
(int) rpi, max_rpi, rpi_limit); (int) rpi, max_rpi, rpi_limit);
/* /*
...@@ -18192,7 +18193,8 @@ __lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi) ...@@ -18192,7 +18193,8 @@ __lpfc_sli4_free_rpi(struct lpfc_hba *phba, int rpi)
phba->sli4_hba.rpi_count--; phba->sli4_hba.rpi_count--;
phba->sli4_hba.max_cfg_param.rpi_used--; phba->sli4_hba.max_cfg_param.rpi_used--;
} else { } else {
lpfc_printf_log(phba, KERN_INFO, LOG_SLI, lpfc_printf_log(phba, KERN_INFO,
LOG_NODE | LOG_DISCOVERY,
"2016 rpi %x not inuse\n", "2016 rpi %x not inuse\n",
rpi); rpi);
} }
......
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