@@ -934,10 +934,15 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
934934 /* Check to see if link went down during discovery */
935935 if (lpfc_els_chk_latt (vport )) {
936936 /* One additional decrement on node reference count to
937- * trigger the release of the node
937+ * trigger the release of the node. Make sure the ndlp
938+ * is marked NLP_DROPPED.
938939 */
939- if (!(ndlp -> fc4_xpt_flags & SCSI_XPT_REGD ))
940+ if (!test_bit (NLP_IN_DEV_LOSS , & ndlp -> nlp_flag ) &&
941+ !test_bit (NLP_DROPPED , & ndlp -> nlp_flag ) &&
942+ !(ndlp -> fc4_xpt_flags & SCSI_XPT_REGD )) {
943+ set_bit (NLP_DROPPED , & ndlp -> nlp_flag );
940944 lpfc_nlp_put (ndlp );
945+ }
941946 goto out ;
942947 }
943948
@@ -995,9 +1000,10 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
9951000 IOERR_LOOP_OPEN_FAILURE )))
9961001 lpfc_vlog_msg (vport , KERN_WARNING , LOG_ELS ,
9971002 "2858 FLOGI Status:x%x/x%x TMO"
998- ":x%x Data x%lx x%x\n" ,
1003+ ":x%x Data x%lx x%x x%lx x%x \n" ,
9991004 ulp_status , ulp_word4 , tmo ,
1000- phba -> hba_flag , phba -> fcf .fcf_flag );
1005+ phba -> hba_flag , phba -> fcf .fcf_flag ,
1006+ ndlp -> nlp_flag , ndlp -> fc4_xpt_flags );
10011007
10021008 /* Check for retry */
10031009 if (lpfc_els_retry (phba , cmdiocb , rspiocb )) {
@@ -1015,14 +1021,17 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
10151021 * reference to trigger node release.
10161022 */
10171023 if (!test_bit (NLP_IN_DEV_LOSS , & ndlp -> nlp_flag ) &&
1018- !(ndlp -> fc4_xpt_flags & SCSI_XPT_REGD ))
1024+ !test_bit (NLP_DROPPED , & ndlp -> nlp_flag ) &&
1025+ !(ndlp -> fc4_xpt_flags & SCSI_XPT_REGD )) {
1026+ set_bit (NLP_DROPPED , & ndlp -> nlp_flag );
10191027 lpfc_nlp_put (ndlp );
1028+ }
10201029
10211030 lpfc_printf_vlog (vport , KERN_WARNING , LOG_ELS ,
10221031 "0150 FLOGI Status:x%x/x%x "
1023- "xri x%x TMO:x%x refcnt %d\n" ,
1032+ "xri x%x iotag x%x TMO:x%x refcnt %d\n" ,
10241033 ulp_status , ulp_word4 , cmdiocb -> sli4_xritag ,
1025- tmo , kref_read (& ndlp -> kref ));
1034+ cmdiocb -> iotag , tmo , kref_read (& ndlp -> kref ));
10261035
10271036 /* If this is not a loop open failure, bail out */
10281037 if (!(ulp_status == IOSTAT_LOCAL_REJECT &&
@@ -1279,6 +1288,19 @@ lpfc_issue_els_flogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
12791288 uint32_t tmo , did ;
12801289 int rc ;
12811290
1291+ /* It's possible for lpfc to reissue a FLOGI on an ndlp that is marked
1292+ * NLP_DROPPED. This happens when the FLOGI completed with the XB bit
1293+ * set causing lpfc to reference the ndlp until the XRI_ABORTED CQE is
1294+ * issued. The time window for the XRI_ABORTED CQE can be as much as
1295+ * 2*2*RA_TOV allowing for ndlp reuse of this type when the link is
1296+ * cycling quickly. When true, restore the initial reference and remove
1297+ * the NLP_DROPPED flag as lpfc is retrying.
1298+ */
1299+ if (test_and_clear_bit (NLP_DROPPED , & ndlp -> nlp_flag )) {
1300+ if (!lpfc_nlp_get (ndlp ))
1301+ return 1 ;
1302+ }
1303+
12821304 cmdsize = (sizeof (uint32_t ) + sizeof (struct serv_parm ));
12831305 elsiocb = lpfc_prep_els_iocb (vport , 1 , cmdsize , retry , ndlp ,
12841306 ndlp -> nlp_DID , ELS_CMD_FLOGI );
0 commit comments