scsi: lpfc: Fix broken Credit Recovery after driver load
authorJames Smart <jsmart2021@gmail.com>
Tue, 28 Jan 2020 00:23:03 +0000 (16:23 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 11 Feb 2020 03:46:55 +0000 (22:46 -0500)
When driver is set to enable bb credit recovery, the switch displayed the
setting as inactive.  If the link bounces, it switches to Active.

During link up processing, the driver currently does a MBX_READ_SPARAM
followed by a MBX_CONFIG_LINK. These mbox commands are queued to be
executed, one at a time and the completion is processed by the worker
thread.  Since the MBX_READ_SPARAM is done BEFORE the MBX_CONFIG_LINK, the
BB_SC_N bit is never set the the returned values. BB Credit recovery status
only gets set after the driver requests the feature in CONFIG_LINK, which
is done after the link up. Thus the ordering of READ_SPARAM needs to follow
the CONFIG_LINK.

Fix by reordering so that READ_SPARAM is done after CONFIG_LINK.  Added a
HBA_DEFER_FLOGI flag so that any FLOGI handling waits until after the
READ_SPARAM is done so that the proper BB credit value is set in the FLOGI
payload.

Fixes: 6bfb16208298 ("scsi: lpfc: Fix configuration of BB credit recovery in service parameters")
Cc: <stable@vger.kernel.org> # v5.4+
Link: https://lore.kernel.org/r/20200128002312.16346-4-jsmart2021@gmail.com
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>
drivers/scsi/lpfc/lpfc.h
drivers/scsi/lpfc/lpfc_hbadisc.c

index 04d73e2be373e3376f1e0427eb1671ea47d6c150..3f2cb17c4574c69e1eaa176bceac65b0a934b887 100644 (file)
@@ -749,6 +749,7 @@ struct lpfc_hba {
                                         * capability
                                         */
 #define HBA_FLOGI_ISSUED       0x100000 /* FLOGI was issued */
+#define HBA_DEFER_FLOGI                0x800000 /* Defer FLOGI till read_sparm cmpl */
 
        uint32_t fcp_ring_in_use; /* When polling test if intr-hndlr active*/
        struct lpfc_dmabuf slim2p;
index dcc8999c6a683ba50fa542b9a6df2a61ca2804cb..6a2bdae0e52a25ff98adf9381f8cc9e6891d15cd 100644 (file)
@@ -1163,13 +1163,16 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        }
 
        /* Start discovery by sending a FLOGI. port_state is identically
-        * LPFC_FLOGI while waiting for FLOGI cmpl
+        * LPFC_FLOGI while waiting for FLOGI cmpl. Check if sending
+        * the FLOGI is being deferred till after MBX_READ_SPARAM completes.
         */
-       if (vport->port_state != LPFC_FLOGI)
-               lpfc_initial_flogi(vport);
-       else if (vport->fc_flag & FC_PT2PT)
-               lpfc_disc_start(vport);
-
+       if (vport->port_state != LPFC_FLOGI) {
+               if (!(phba->hba_flag & HBA_DEFER_FLOGI))
+                       lpfc_initial_flogi(vport);
+       } else {
+               if (vport->fc_flag & FC_PT2PT)
+                       lpfc_disc_start(vport);
+       }
        return;
 
 out:
@@ -3094,6 +3097,14 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
        mempool_free(pmb, phba->mbox_mem_pool);
+
+       /* Check if sending the FLOGI is being deferred to after we get
+        * up to date CSPs from MBX_READ_SPARAM.
+        */
+       if (phba->hba_flag & HBA_DEFER_FLOGI) {
+               lpfc_initial_flogi(vport);
+               phba->hba_flag &= ~HBA_DEFER_FLOGI;
+       }
        return;
 
 out:
@@ -3224,6 +3235,23 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
        }
 
        lpfc_linkup(phba);
+       sparam_mbox = NULL;
+
+       if (!(phba->hba_flag & HBA_FCOE_MODE)) {
+               cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+               if (!cfglink_mbox)
+                       goto out;
+               vport->port_state = LPFC_LOCAL_CFG_LINK;
+               lpfc_config_link(phba, cfglink_mbox);
+               cfglink_mbox->vport = vport;
+               cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
+               rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT);
+               if (rc == MBX_NOT_FINISHED) {
+                       mempool_free(cfglink_mbox, phba->mbox_mem_pool);
+                       goto out;
+               }
+       }
+
        sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (!sparam_mbox)
                goto out;
@@ -3244,20 +3272,7 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
                goto out;
        }
 
-       if (!(phba->hba_flag & HBA_FCOE_MODE)) {
-               cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-               if (!cfglink_mbox)
-                       goto out;
-               vport->port_state = LPFC_LOCAL_CFG_LINK;
-               lpfc_config_link(phba, cfglink_mbox);
-               cfglink_mbox->vport = vport;
-               cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
-               rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT);
-               if (rc == MBX_NOT_FINISHED) {
-                       mempool_free(cfglink_mbox, phba->mbox_mem_pool);
-                       goto out;
-               }
-       } else {
+       if (phba->hba_flag & HBA_FCOE_MODE) {
                vport->port_state = LPFC_VPORT_UNKNOWN;
                /*
                 * Add the driver's default FCF record at FCF index 0 now. This
@@ -3314,6 +3329,10 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
                }
                /* Reset FCF roundrobin bmask for new discovery */
                lpfc_sli4_clear_fcf_rr_bmask(phba);
+       } else {
+               if (phba->bbcredit_support && phba->cfg_enable_bbcr &&
+                   !(phba->link_flag & LS_LOOPBACK_MODE))
+                       phba->hba_flag |= HBA_DEFER_FLOGI;
        }
 
        /* Prepare for LINK up registrations */