Commit 287aba25 authored by James Smart's avatar James Smart Committed by Martin K. Petersen

scsi: lpfc: ls_rjt erroneus FLOGIs

In some link initialization sequences, the fw generates an erroneous FLOGI
payload to the driver without an intervening link bounce.  The driver, when
it sees a 2nd FLOGI without an intervening link bounce, automatically
performs a link bounce. In this, the link bounce causes the situate to
repeat and in a nasty loop of link bounces.

Resolve the issue by validating the FLOGI payload. The erroneous FLOGI will
contain VVL signatures that are not normal. When the driver sees these, it
will simply reject the flogi rather than bouncing the link.  The reject is
consumed within the firmware.
Signed-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 92ea83a8
...@@ -8042,8 +8042,10 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -8042,8 +8042,10 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct ls_rjt stat; struct ls_rjt stat;
uint32_t *payload; uint32_t *payload;
uint32_t cmd, did, newnode; uint32_t cmd, did, newnode;
uint32_t vid, flag;
uint8_t rjt_exp, rjt_err = 0, init_link = 0; uint8_t rjt_exp, rjt_err = 0, init_link = 0;
IOCB_t *icmd = &elsiocb->iocb; IOCB_t *icmd = &elsiocb->iocb;
struct serv_parm *sp;
LPFC_MBOXQ_t *mbox; LPFC_MBOXQ_t *mbox;
if (!vport || !(elsiocb->context2)) if (!vport || !(elsiocb->context2))
...@@ -8193,6 +8195,22 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -8193,6 +8195,22 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
did, vport->port_state, ndlp->nlp_flag); did, vport->port_state, ndlp->nlp_flag);
phba->fc_stat.elsRcvFLOGI++; phba->fc_stat.elsRcvFLOGI++;
sp = (struct serv_parm *)
((uint8_t *)payload + sizeof(uint32_t));
/* Check to see if this is firmware generated */
if (sp->cmn.valid_vendor_ver_level) {
vid = be32_to_cpu(sp->un.vv.vid);
flag = be32_to_cpu(sp->un.vv.flags);
if (vid == LPFC_VV_BRCD_ID) {
/* Drop this FLOGI */
lpfc_printf_vlog(
vport, KERN_INFO, LOG_ELS,
"3316 Dropping rcv FLOGI: "
"flag x%x\n", flag);
goto lsrjt;
}
}
/* If the driver believes fabric discovery is done and is ready, /* If the driver believes fabric discovery is done and is ready,
* bounce the link. There is some descrepancy. * bounce the link. There is some descrepancy.
...@@ -8440,6 +8458,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring, ...@@ -8440,6 +8458,8 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
* link and start over. * link and start over.
*/ */
if (init_link) { if (init_link) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
"3318 Resetting Link, multiple rcv FLOGIs\n");
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!mbox) if (!mbox)
return; return;
......
...@@ -525,6 +525,7 @@ struct serv_parm { /* Structure is in Big Endian format */ ...@@ -525,6 +525,7 @@ struct serv_parm { /* Structure is in Big Endian format */
struct { struct {
uint32_t vid; uint32_t vid;
#define LPFC_VV_EMLX_ID 0x454d4c58 /* EMLX */ #define LPFC_VV_EMLX_ID 0x454d4c58 /* EMLX */
#define LPFC_VV_BRCD_ID 0x42524344 /* BRCD */
uint32_t flags; uint32_t flags;
#define LPFC_VV_SUPPRESS_RSP 1 #define LPFC_VV_SUPPRESS_RSP 1
} vv; } vv;
......
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