summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Smart <jsmart2021@gmail.com>2018-11-29 16:09:35 -0800
committerMartin K. Petersen <martin.petersen@oracle.com>2018-12-07 22:35:32 -0500
commit287aba2592870fa5b76134b28173b77f1f7a4492 (patch)
tree23ce42e20e958b3f0d705d254b8970bd969f1cd3
parent92ea83a878c68f709a172dd0125582b311d4d0d0 (diff)
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: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c20
-rw-r--r--drivers/scsi/lpfc/lpfc_hw.h1
2 files changed, 21 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index e4cf648c951b..48610bcd6962 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -8042,8 +8042,10 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct ls_rjt stat;
uint32_t *payload;
uint32_t cmd, did, newnode;
+ uint32_t vid, flag;
uint8_t rjt_exp, rjt_err = 0, init_link = 0;
IOCB_t *icmd = &elsiocb->iocb;
+ struct serv_parm *sp;
LPFC_MBOXQ_t *mbox;
if (!vport || !(elsiocb->context2))
@@ -8193,6 +8195,22 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
did, vport->port_state, ndlp->nlp_flag);
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,
* bounce the link. There is some descrepancy.
@@ -8440,6 +8458,8 @@ lsrjt:
* link and start over.
*/
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);
if (!mbox)
return;
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index ec1227018913..eb49c720e042 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -525,6 +525,7 @@ struct serv_parm { /* Structure is in Big Endian format */
struct {
uint32_t vid;
#define LPFC_VV_EMLX_ID 0x454d4c58 /* EMLX */
+#define LPFC_VV_BRCD_ID 0x42524344 /* BRCD */
uint32_t flags;
#define LPFC_VV_SUPPRESS_RSP 1
} vv;