Skip to content

Commit 30e196c

Browse files
jsmart-ghmartinkpetersen
authored andcommitted
scsi: lpfc: Fix LOGO/PLOGI handling when triggerd by ABTS Timeout event
After a LOGO in response to an ABTS timeout, a PLOGI wasn't issued to re-establish the login. An nlp_type check in the LOGO completion handler failed to restart discovery for NVME targets. Revised the nlp_type check for NVME as well as SCSI. While reviewing the LOGO handling a few other issues were seen and were addressed: - Better lock synchronization around ndlp data types - When the ABTS times out, unregister the RPI before sending the LOGO so that all local exchange contexts are cleared and nothing received while awaiting LOGO/PLOGI handling will be accepted. - LOGO handling optimized to: Wait only R_A_TOV for a response. It doesn't need to be retried on timeout. If there wasn't a response, a PLOGI will be sent, thus an implicit logout applies as well when the other port sees it. If there is a response, any kind of response is considered "good" and the XRI quarantined for a exchange qualifier window. - PLOGI is issued as soon a LOGO state is resolved. Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Reviewed-by: Hannes Reinecke <hare@suse.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 3952e91 commit 30e196c

File tree

2 files changed

+26
-28
lines changed

2 files changed

+26
-28
lines changed

drivers/scsi/lpfc/lpfc_els.c

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
242242
icmd->ulpCommand = CMD_ELS_REQUEST64_CR;
243243
if (elscmd == ELS_CMD_FLOGI)
244244
icmd->ulpTimeout = FF_DEF_RATOV * 2;
245+
else if (elscmd == ELS_CMD_LOGO)
246+
icmd->ulpTimeout = phba->fc_ratov;
245247
else
246248
icmd->ulpTimeout = phba->fc_ratov * 2;
247249
} else {
@@ -2682,16 +2684,15 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
26822684
goto out;
26832685
}
26842686

2687+
/* The LOGO will not be retried on failure. A LOGO was
2688+
* issued to the remote rport and a ACC or RJT or no Answer are
2689+
* all acceptable. Note the failure and move forward with
2690+
* discovery. The PLOGI will retry.
2691+
*/
26852692
if (irsp->ulpStatus) {
2686-
/* Check for retry */
2687-
if (lpfc_els_retry(phba, cmdiocb, rspiocb)) {
2688-
/* ELS command is being retried */
2689-
skip_recovery = 1;
2690-
goto out;
2691-
}
26922693
/* LOGO failed */
26932694
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
2694-
"2756 LOGO failure DID:%06X Status:x%x/x%x\n",
2695+
"2756 LOGO failure, No Retry DID:%06X Status:x%x/x%x\n",
26952696
ndlp->nlp_DID, irsp->ulpStatus,
26962697
irsp->un.ulpWord[4]);
26972698
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
@@ -2737,7 +2738,8 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
27372738
* For any other port type, the rpi is unregistered as an implicit
27382739
* LOGO.
27392740
*/
2740-
if ((ndlp->nlp_type & NLP_FCP_TARGET) && (skip_recovery == 0)) {
2741+
if (ndlp->nlp_type & (NLP_FCP_TARGET | NLP_NVME_TARGET) &&
2742+
skip_recovery == 0) {
27412743
lpfc_cancel_retry_delay_tmo(vport, ndlp);
27422744
spin_lock_irqsave(shost->host_lock, flags);
27432745
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
@@ -2770,6 +2772,8 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
27702772
* will be stored into the context1 field of the IOCB for the completion
27712773
* callback function to the LOGO ELS command.
27722774
*
2775+
* Callers of this routine are expected to unregister the RPI first
2776+
*
27732777
* Return code
27742778
* 0 - successfully issued logo
27752779
* 1 - failed to issue logo
@@ -2811,37 +2815,25 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
28112815
"Issue LOGO: did:x%x",
28122816
ndlp->nlp_DID, 0, 0);
28132817

2814-
/*
2815-
* If we are issuing a LOGO, we may try to recover the remote NPort
2816-
* by issuing a PLOGI later. Even though we issue ELS cmds by the
2817-
* VPI, if we have a valid RPI, and that RPI gets unreg'ed while
2818-
* that ELS command is in-flight, the HBA returns a IOERR_INVALID_RPI
2819-
* for that ELS cmd. To avoid this situation, lets get rid of the
2820-
* RPI right now, before any ELS cmds are sent.
2821-
*/
2822-
spin_lock_irq(shost->host_lock);
2823-
ndlp->nlp_flag |= NLP_ISSUE_LOGO;
2824-
spin_unlock_irq(shost->host_lock);
2825-
if (lpfc_unreg_rpi(vport, ndlp)) {
2826-
lpfc_els_free_iocb(phba, elsiocb);
2827-
return 0;
2828-
}
2829-
28302818
phba->fc_stat.elsXmitLOGO++;
28312819
elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
28322820
spin_lock_irq(shost->host_lock);
28332821
ndlp->nlp_flag |= NLP_LOGO_SND;
28342822
ndlp->nlp_flag &= ~NLP_ISSUE_LOGO;
28352823
spin_unlock_irq(shost->host_lock);
28362824
rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, elsiocb, 0);
2837-
28382825
if (rc == IOCB_ERROR) {
28392826
spin_lock_irq(shost->host_lock);
28402827
ndlp->nlp_flag &= ~NLP_LOGO_SND;
28412828
spin_unlock_irq(shost->host_lock);
28422829
lpfc_els_free_iocb(phba, elsiocb);
28432830
return 1;
28442831
}
2832+
2833+
spin_lock_irq(shost->host_lock);
2834+
ndlp->nlp_prev_state = ndlp->nlp_state;
2835+
spin_unlock_irq(shost->host_lock);
2836+
lpfc_nlp_set_state(vport, ndlp, NLP_STE_LOGO_ISSUE);
28452837
return 0;
28462838
}
28472839

@@ -9505,7 +9497,8 @@ lpfc_sli_abts_recover_port(struct lpfc_vport *vport,
95059497
"rport in state 0x%x\n", ndlp->nlp_state);
95069498
return;
95079499
}
9508-
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
9500+
lpfc_printf_log(phba, KERN_ERR,
9501+
LOG_ELS | LOG_FCP_ERROR | LOG_NVME_IOERR,
95099502
"3094 Start rport recovery on shost id 0x%x "
95109503
"fc_id 0x%06x vpi 0x%x rpi 0x%x state 0x%x "
95119504
"flags 0x%x\n",
@@ -9518,8 +9511,8 @@ lpfc_sli_abts_recover_port(struct lpfc_vport *vport,
95189511
*/
95199512
spin_lock_irqsave(shost->host_lock, flags);
95209513
ndlp->nlp_fcp_info &= ~NLP_FCP_2_DEVICE;
9514+
ndlp->nlp_flag |= NLP_ISSUE_LOGO;
95219515
spin_unlock_irqrestore(shost->host_lock, flags);
9522-
lpfc_issue_els_logo(vport, ndlp, 0);
9523-
lpfc_nlp_set_state(vport, ndlp, NLP_STE_LOGO_ISSUE);
9516+
lpfc_unreg_rpi(vport, ndlp);
95249517
}
95259518

drivers/scsi/lpfc/lpfc_nportdisc.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,9 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
836836
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
837837

838838
if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED)) {
839+
spin_lock_irq(shost->host_lock);
839840
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
841+
spin_unlock_irq(shost->host_lock);
840842
return 0;
841843
}
842844

@@ -851,7 +853,10 @@ lpfc_disc_set_adisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
851853
return 1;
852854
}
853855
}
856+
857+
spin_lock_irq(shost->host_lock);
854858
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
859+
spin_unlock_irq(shost->host_lock);
855860
lpfc_unreg_rpi(vport, ndlp);
856861
return 0;
857862
}

0 commit comments

Comments
 (0)