Commit 7f04839e authored by James Smart's avatar James Smart Committed by Martin K. Petersen

scsi: lpfc: Fix initial FLOGI failure due to BBSCN not supported

Initial FLOGIs are failing with the following message:

 lpfc 0000:13:00.1: 1:(0):0820 FLOGI Failed (x300). BBCredit Not Supported

In a prior patch, the READ_SPARAM command was re-ordered to post after
CONFIG_LINK as the driver is expected to update the driver's copy of the
service parameters for the FLOGI payload. If the bb-credit recovery feature
is enabled, this is fine. But on adapters were bb-credit recovery isn't
enabled, it would cause the FLOGI to fail.

Fix by restoring the original command order (READ_SPARAM before
CONFIG_LINK), and after issuing CONFIG_LINK, detect bb-credit recovery
support and reissuing READ_SPARAM to obtain the updated service parameters
(effectively adding in the fix command order).

[mkp: corrected SHA]

Link: https://lore.kernel.org/r/20200911200147.110826-1-james.smart@broadcom.com
Fixes: 835214f5 ("scsi: lpfc: Fix broken Credit Recovery after driver load")
CC: <stable@vger.kernel.org> # v5.7+
Co-developed-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarJames Smart <james.smart@broadcom.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 244359c9
...@@ -71,6 +71,7 @@ static void lpfc_disc_timeout_handler(struct lpfc_vport *); ...@@ -71,6 +71,7 @@ static void lpfc_disc_timeout_handler(struct lpfc_vport *);
static void lpfc_disc_flush_list(struct lpfc_vport *vport); static void lpfc_disc_flush_list(struct lpfc_vport *vport);
static void lpfc_unregister_fcfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *); static void lpfc_unregister_fcfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
static int lpfc_fcf_inuse(struct lpfc_hba *); static int lpfc_fcf_inuse(struct lpfc_hba *);
static void lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
void void
lpfc_terminate_rport_io(struct fc_rport *rport) lpfc_terminate_rport_io(struct fc_rport *rport)
...@@ -1138,11 +1139,13 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -1138,11 +1139,13 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
return; return;
} }
void void
lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
{ {
struct lpfc_vport *vport = pmb->vport; struct lpfc_vport *vport = pmb->vport;
LPFC_MBOXQ_t *sparam_mb;
struct lpfc_dmabuf *sparam_mp;
int rc;
if (pmb->u.mb.mbxStatus) if (pmb->u.mb.mbxStatus)
goto out; goto out;
...@@ -1167,12 +1170,42 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -1167,12 +1170,42 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
} }
/* Start discovery by sending a FLOGI. port_state is identically /* Start discovery by sending a FLOGI. port_state is identically
* LPFC_FLOGI while waiting for FLOGI cmpl. Check if sending * LPFC_FLOGI while waiting for FLOGI cmpl.
* the FLOGI is being deferred till after MBX_READ_SPARAM completes.
*/ */
if (vport->port_state != LPFC_FLOGI) { if (vport->port_state != LPFC_FLOGI) {
if (!(phba->hba_flag & HBA_DEFER_FLOGI)) /* Issue MBX_READ_SPARAM to update CSPs before FLOGI if
* bb-credit recovery is in place.
*/
if (phba->bbcredit_support && phba->cfg_enable_bbcr &&
!(phba->link_flag & LS_LOOPBACK_MODE)) {
sparam_mb = mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL);
if (!sparam_mb)
goto sparam_out;
rc = lpfc_read_sparam(phba, sparam_mb, 0);
if (rc) {
mempool_free(sparam_mb, phba->mbox_mem_pool);
goto sparam_out;
}
sparam_mb->vport = vport;
sparam_mb->mbox_cmpl = lpfc_mbx_cmpl_read_sparam;
rc = lpfc_sli_issue_mbox(phba, sparam_mb, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
sparam_mp = (struct lpfc_dmabuf *)
sparam_mb->ctx_buf;
lpfc_mbuf_free(phba, sparam_mp->virt,
sparam_mp->phys);
kfree(sparam_mp);
sparam_mb->ctx_buf = NULL;
mempool_free(sparam_mb, phba->mbox_mem_pool);
goto sparam_out;
}
phba->hba_flag |= HBA_DEFER_FLOGI;
} else {
lpfc_initial_flogi(vport); lpfc_initial_flogi(vport);
}
} else { } else {
if (vport->fc_flag & FC_PT2PT) if (vport->fc_flag & FC_PT2PT)
lpfc_disc_start(vport); lpfc_disc_start(vport);
...@@ -1184,6 +1217,7 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb) ...@@ -1184,6 +1217,7 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
"0306 CONFIG_LINK mbxStatus error x%x " "0306 CONFIG_LINK mbxStatus error x%x "
"HBA state x%x\n", "HBA state x%x\n",
pmb->u.mb.mbxStatus, vport->port_state); pmb->u.mb.mbxStatus, vport->port_state);
sparam_out:
mempool_free(pmb, phba->mbox_mem_pool); mempool_free(pmb, phba->mbox_mem_pool);
lpfc_linkdown(phba); lpfc_linkdown(phba);
...@@ -3239,21 +3273,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) ...@@ -3239,21 +3273,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
lpfc_linkup(phba); lpfc_linkup(phba);
sparam_mbox = NULL; 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); sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
if (!sparam_mbox) if (!sparam_mbox)
goto out; goto out;
...@@ -3274,7 +3293,20 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) ...@@ -3274,7 +3293,20 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
goto out; goto out;
} }
if (phba->hba_flag & HBA_FCOE_MODE) { 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 {
vport->port_state = LPFC_VPORT_UNKNOWN; vport->port_state = LPFC_VPORT_UNKNOWN;
/* /*
* Add the driver's default FCF record at FCF index 0 now. This * Add the driver's default FCF record at FCF index 0 now. This
...@@ -3331,10 +3363,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la) ...@@ -3331,10 +3363,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
} }
/* Reset FCF roundrobin bmask for new discovery */ /* Reset FCF roundrobin bmask for new discovery */
lpfc_sli4_clear_fcf_rr_bmask(phba); 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 */ /* Prepare for LINK up registrations */
......
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