Skip to content

Commit d496b9a

Browse files
jsmart-ghmartinkpetersen
authored andcommitted
scsi: lpfc: Fix odd recovery in duplicate FLOGIs in point-to-point
Testing a point-to-point topology and a case of re-FLOGI without intervening link bouncing, showed an odd interaction with firmware and a resulting scenario where the driver no longer probed after accepting the new FLOGI. Work around the firmware issue by issuing a link bounce if a FLOGI is received after the link is already up and FLOGI's accepted. While debugging the issue, realized that some debug traces should be clarified to help in the future. 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 b114d90 commit d496b9a

File tree

3 files changed

+64
-12
lines changed

3 files changed

+64
-12
lines changed

drivers/scsi/lpfc/lpfc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ struct lpfc_vport {
490490
struct nvme_fc_local_port *localport;
491491
uint8_t nvmei_support; /* driver supports NVME Initiator */
492492
uint32_t last_fcp_wqidx;
493+
uint32_t rcv_flogi_cnt; /* How many unsol FLOGIs ACK'd. */
493494
};
494495

495496
struct hbq_s {

drivers/scsi/lpfc/lpfc_els.c

Lines changed: 54 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,9 +1057,9 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
10571057
goto flogifail;
10581058

10591059
lpfc_printf_vlog(vport, KERN_WARNING, LOG_ELS,
1060-
"0150 FLOGI failure Status:x%x/x%x TMO:x%x\n",
1060+
"0150 FLOGI failure Status:x%x/x%x xri x%x TMO:x%x\n",
10611061
irsp->ulpStatus, irsp->un.ulpWord[4],
1062-
irsp->ulpTimeout);
1062+
cmdiocb->sli4_xritag, irsp->ulpTimeout);
10631063

10641064
/* FLOGI failed, so there is no fabric */
10651065
spin_lock_irq(shost->host_lock);
@@ -1113,7 +1113,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
11131113
/* FLOGI completes successfully */
11141114
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
11151115
"0101 FLOGI completes successfully, I/O tag:x%x, "
1116-
"Data: x%x x%x x%x x%x x%x x%x\n", cmdiocb->iotag,
1116+
"xri x%x Data: x%x x%x x%x x%x x%x %x\n",
1117+
cmdiocb->iotag, cmdiocb->sli4_xritag,
11171118
irsp->un.ulpWord[4], sp->cmn.e_d_tov,
11181119
sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution,
11191120
vport->port_state, vport->fc_flag);
@@ -4347,14 +4348,6 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
43474348
default:
43484349
return 1;
43494350
}
4350-
/* Xmit ELS ACC response tag <ulpIoTag> */
4351-
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
4352-
"0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
4353-
"DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x "
4354-
"fc_flag x%x\n",
4355-
elsiocb->iotag, elsiocb->iocb.ulpContext,
4356-
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
4357-
ndlp->nlp_rpi, vport->fc_flag);
43584351
if (ndlp->nlp_flag & NLP_LOGO_ACC) {
43594352
spin_lock_irq(shost->host_lock);
43604353
if (!(ndlp->nlp_flag & NLP_RPI_REGISTERED ||
@@ -4523,6 +4516,15 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
45234516
lpfc_els_free_iocb(phba, elsiocb);
45244517
return 1;
45254518
}
4519+
4520+
/* Xmit ELS ACC response tag <ulpIoTag> */
4521+
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
4522+
"0128 Xmit ELS ACC response Status: x%x, IoTag: x%x, "
4523+
"XRI: x%x, DID: x%x, nlp_flag: x%x nlp_state: x%x "
4524+
"RPI: x%x, fc_flag x%x\n",
4525+
rc, elsiocb->iotag, elsiocb->sli4_xritag,
4526+
ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
4527+
ndlp->nlp_rpi, vport->fc_flag);
45264528
return 0;
45274529
}
45284530

@@ -6533,6 +6535,11 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
65336535
port_state = vport->port_state;
65346536
vport->fc_flag |= FC_PT2PT;
65356537
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
6538+
6539+
/* Acking an unsol FLOGI. Count 1 for link bounce
6540+
* work-around.
6541+
*/
6542+
vport->rcv_flogi_cnt++;
65366543
spin_unlock_irq(shost->host_lock);
65376544
lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
65386545
"3311 Rcv Flogi PS x%x new PS x%x "
@@ -7930,8 +7937,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
79307937
struct ls_rjt stat;
79317938
uint32_t *payload;
79327939
uint32_t cmd, did, newnode;
7933-
uint8_t rjt_exp, rjt_err = 0;
7940+
uint8_t rjt_exp, rjt_err = 0, init_link = 0;
79347941
IOCB_t *icmd = &elsiocb->iocb;
7942+
LPFC_MBOXQ_t *mbox;
79357943

79367944
if (!vport || !(elsiocb->context2))
79377945
goto dropit;
@@ -8080,6 +8088,19 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
80808088
did, vport->port_state, ndlp->nlp_flag);
80818089

80828090
phba->fc_stat.elsRcvFLOGI++;
8091+
8092+
/* If the driver believes fabric discovery is done and is ready,
8093+
* bounce the link. There is some descrepancy.
8094+
*/
8095+
if (vport->port_state >= LPFC_LOCAL_CFG_LINK &&
8096+
vport->fc_flag & FC_PT2PT &&
8097+
vport->rcv_flogi_cnt >= 1) {
8098+
rjt_err = LSRJT_LOGICAL_BSY;
8099+
rjt_exp = LSEXP_NOTHING_MORE;
8100+
init_link++;
8101+
goto lsrjt;
8102+
}
8103+
80838104
lpfc_els_rcv_flogi(vport, elsiocb, ndlp);
80848105
if (newnode)
80858106
lpfc_nlp_put(ndlp);
@@ -8308,6 +8329,27 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
83088329

83098330
lpfc_nlp_put(elsiocb->context1);
83108331
elsiocb->context1 = NULL;
8332+
8333+
/* Special case. Driver received an unsolicited command that
8334+
* unsupportable given the driver's current state. Reset the
8335+
* link and start over.
8336+
*/
8337+
if (init_link) {
8338+
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
8339+
if (!mbox)
8340+
return;
8341+
lpfc_linkdown(phba);
8342+
lpfc_init_link(phba, mbox,
8343+
phba->cfg_topology,
8344+
phba->cfg_link_speed);
8345+
mbox->u.mb.un.varInitLnk.lipsr_AL_PA = 0;
8346+
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
8347+
mbox->vport = vport;
8348+
if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) ==
8349+
MBX_NOT_FINISHED)
8350+
mempool_free(mbox, phba->mbox_mem_pool);
8351+
}
8352+
83118353
return;
83128354

83138355
dropit:

drivers/scsi/lpfc/lpfc_hbadisc.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,7 @@ lpfc_linkdown(struct lpfc_hba *phba)
947947
}
948948
spin_lock_irq(shost->host_lock);
949949
phba->pport->fc_flag &= ~(FC_PT2PT | FC_PT2PT_PLOGI);
950+
phba->pport->rcv_flogi_cnt = 0;
950951
spin_unlock_irq(shost->host_lock);
951952
}
952953
return 0;
@@ -1018,6 +1019,7 @@ lpfc_linkup(struct lpfc_hba *phba)
10181019
{
10191020
struct lpfc_vport **vports;
10201021
int i;
1022+
struct Scsi_Host *shost = lpfc_shost_from_vport(phba->pport);
10211023

10221024
phba->link_state = LPFC_LINK_UP;
10231025

@@ -1031,6 +1033,13 @@ lpfc_linkup(struct lpfc_hba *phba)
10311033
lpfc_linkup_port(vports[i]);
10321034
lpfc_destroy_vport_work_array(phba, vports);
10331035

1036+
/* Clear the pport flogi counter in case the link down was
1037+
* absorbed without an ACQE. No lock here - in worker thread
1038+
* and discovery is synchronized.
1039+
*/
1040+
spin_lock_irq(shost->host_lock);
1041+
phba->pport->rcv_flogi_cnt = 0;
1042+
spin_unlock_irq(shost->host_lock);
10341043
return 0;
10351044
}
10361045

0 commit comments

Comments
 (0)