summaryrefslogtreecommitdiff
path: root/drivers/scsi/lpfc/lpfc_nportdisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_nportdisc.c')
-rw-r--r--drivers/scsi/lpfc/lpfc_nportdisc.c282
1 files changed, 102 insertions, 180 deletions
diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c
index 135d8e8a42ba..bb4e65a32ecc 100644
--- a/drivers/scsi/lpfc/lpfc_nportdisc.c
+++ b/drivers/scsi/lpfc/lpfc_nportdisc.c
@@ -1,7 +1,7 @@
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2017-2020 Broadcom. All Rights Reserved. The term *
+ * Copyright (C) 2017-2021 Broadcom. All Rights Reserved. The term *
* “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. *
* Copyright (C) 2004-2016 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
@@ -279,106 +279,43 @@ lpfc_els_abort(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
}
-/* lpfc_defer_pt2pt_acc - Complete SLI3 pt2pt processing on link up
+/* lpfc_defer_plogi_acc - Issue PLOGI ACC after reg_login completes
* @phba: pointer to lpfc hba data structure.
- * @link_mbox: pointer to CONFIG_LINK mailbox object
+ * @login_mbox: pointer to REG_RPI mailbox object
*
- * This routine is only called if we are SLI3, direct connect pt2pt
- * mode and the remote NPort issues the PLOGI after link up.
+ * The ACC for a rcv'ed PLOGI is deferred until AFTER the REG_RPI completes
*/
static void
-lpfc_defer_pt2pt_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *link_mbox)
+lpfc_defer_plogi_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *login_mbox)
{
- LPFC_MBOXQ_t *login_mbox;
- MAILBOX_t *mb = &link_mbox->u.mb;
struct lpfc_iocbq *save_iocb;
struct lpfc_nodelist *ndlp;
+ MAILBOX_t *mb = &login_mbox->u.mb;
+
int rc;
- ndlp = link_mbox->ctx_ndlp;
- login_mbox = link_mbox->context3;
+ ndlp = login_mbox->ctx_ndlp;
save_iocb = login_mbox->context3;
- link_mbox->context3 = NULL;
- login_mbox->context3 = NULL;
- /* Check for CONFIG_LINK error */
- if (mb->mbxStatus) {
- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "4575 CONFIG_LINK fails pt2pt discovery: %x\n",
- mb->mbxStatus);
- mempool_free(login_mbox, phba->mbox_mem_pool);
- mempool_free(link_mbox, phba->mbox_mem_pool);
- kfree(save_iocb);
- return;
- }
-
- /* Now that CONFIG_LINK completed, and our SID is configured,
- * we can now proceed with sending the PLOGI ACC.
- */
- rc = lpfc_els_rsp_acc(link_mbox->vport, ELS_CMD_PLOGI,
- save_iocb, ndlp, login_mbox);
- if (rc) {
- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "4576 PLOGI ACC fails pt2pt discovery: %x\n",
- rc);
- mempool_free(login_mbox, phba->mbox_mem_pool);
+ if (mb->mbxStatus == MBX_SUCCESS) {
+ /* Now that REG_RPI completed successfully,
+ * we can now proceed with sending the PLOGI ACC.
+ */
+ rc = lpfc_els_rsp_acc(login_mbox->vport, ELS_CMD_PLOGI,
+ save_iocb, ndlp, NULL);
+ if (rc) {
+ lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
+ "4576 PLOGI ACC fails pt2pt discovery: "
+ "DID %x Data: %x\n", ndlp->nlp_DID, rc);
+ }
}
- mempool_free(link_mbox, phba->mbox_mem_pool);
+ /* Now process the REG_RPI cmpl */
+ lpfc_mbx_cmpl_reg_login(phba, login_mbox);
+ ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
kfree(save_iocb);
}
-/**
- * lpfc_defer_tgt_acc - Progress SLI4 target rcv PLOGI handler
- * @phba: Pointer to HBA context object.
- * @pmb: Pointer to mailbox object.
- *
- * This function provides the unreg rpi mailbox completion handler for a tgt.
- * The routine frees the memory resources associated with the completed
- * mailbox command and transmits the ELS ACC.
- *
- * This routine is only called if we are SLI4, acting in target
- * mode and the remote NPort issues the PLOGI after link up.
- **/
-static void
-lpfc_defer_acc_rsp(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
-{
- struct lpfc_vport *vport = pmb->vport;
- struct lpfc_nodelist *ndlp = pmb->ctx_ndlp;
- LPFC_MBOXQ_t *mbox = pmb->context3;
- struct lpfc_iocbq *piocb = NULL;
- int rc;
-
- if (mbox) {
- pmb->context3 = NULL;
- piocb = mbox->context3;
- mbox->context3 = NULL;
- }
-
- /*
- * Complete the unreg rpi mbx request, and update flags.
- * This will also restart any deferred events.
- */
- lpfc_sli4_unreg_rpi_cmpl_clr(phba, pmb);
-
- if (!piocb) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
- "4578 PLOGI ACC fail\n");
- if (mbox)
- mempool_free(mbox, phba->mbox_mem_pool);
- return;
- }
-
- rc = lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, piocb, ndlp, mbox);
- if (rc) {
- lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
- "4579 PLOGI ACC fail %x\n", rc);
- if (mbox)
- mempool_free(mbox, phba->mbox_mem_pool);
- }
- kfree(piocb);
-}
-
static int
lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct lpfc_iocbq *cmdiocb)
@@ -395,8 +332,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
struct lpfc_iocbq *save_iocb;
struct ls_rjt stat;
uint32_t vid, flag;
- u16 rpi;
- int rc, defer_acc;
+ int rc;
memset(&stat, 0, sizeof (struct ls_rjt));
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
@@ -404,7 +340,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
if (wwn_to_u64(sp->portName.u.wwn) == 0) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
- "0140 PLOGI Reject: invalid nname\n");
+ "0140 PLOGI Reject: invalid pname\n");
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_PNAME;
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
@@ -413,7 +349,7 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
}
if (wwn_to_u64(sp->nodeName.u.wwn) == 0) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_TRACE_EVENT,
- "0141 PLOGI Reject: invalid pname\n");
+ "0141 PLOGI Reject: invalid nname\n");
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_NNAME;
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
@@ -445,7 +381,6 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
else
ndlp->nlp_fcp_info |= CLASS3;
- defer_acc = 0;
ndlp->nlp_class_sup = 0;
if (sp->cls1.classValid)
ndlp->nlp_class_sup |= FC_COS_CLASS1;
@@ -523,6 +458,16 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
/* rcv'ed PLOGI decides what our NPortId will be */
vport->fc_myDID = icmd->un.rcvels.parmRo;
+ /* If there is an outstanding FLOGI, abort it now.
+ * The remote NPort is not going to ACC our FLOGI
+ * if its already issuing a PLOGI for pt2pt mode.
+ * This indicates our FLOGI was dropped; however, we
+ * must have ACCed the remote NPorts FLOGI to us
+ * to make it here.
+ */
+ if (phba->hba_flag & HBA_FLOGI_OUTSTANDING)
+ lpfc_els_abort_flogi(phba);
+
ed_tov = be32_to_cpu(sp->cmn.e_d_tov);
if (sp->cmn.edtovResolution) {
/* E_D_TOV ticks are in nanoseconds */
@@ -539,27 +484,26 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
- /* Issue config_link / reg_vfi to account for updated TOV's */
-
+ /* Issue CONFIG_LINK for SLI3 or REG_VFI for SLI4,
+ * to account for updated TOV's / parameters
+ */
if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_issue_reg_vfi(vport);
else {
- defer_acc = 1;
link_mbox = mempool_alloc(phba->mbox_mem_pool,
GFP_KERNEL);
if (!link_mbox)
goto out;
lpfc_config_link(phba, link_mbox);
- link_mbox->mbox_cmpl = lpfc_defer_pt2pt_acc;
+ link_mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
link_mbox->vport = vport;
link_mbox->ctx_ndlp = ndlp;
- save_iocb = kzalloc(sizeof(*save_iocb), GFP_KERNEL);
- if (!save_iocb)
+ rc = lpfc_sli_issue_mbox(phba, link_mbox, MBX_NOWAIT);
+ if (rc == MBX_NOT_FINISHED) {
+ mempool_free(link_mbox, phba->mbox_mem_pool);
goto out;
- /* Save info from cmd IOCB used in rsp */
- memcpy((uint8_t *)save_iocb, (uint8_t *)cmdiocb,
- sizeof(struct lpfc_iocbq));
+ }
}
lpfc_can_disctmo(vport);
@@ -578,59 +522,28 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
if (!login_mbox)
goto out;
- /* Registering an existing RPI behaves differently for SLI3 vs SLI4 */
- if (phba->nvmet_support && !defer_acc) {
- link_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!link_mbox)
- goto out;
-
- /* As unique identifiers such as iotag would be overwritten
- * with those from the cmdiocb, allocate separate temporary
- * storage for the copy.
- */
- save_iocb = kzalloc(sizeof(*save_iocb), GFP_KERNEL);
- if (!save_iocb)
- goto out;
-
- /* Unreg RPI is required for SLI4. */
- rpi = phba->sli4_hba.rpi_ids[ndlp->nlp_rpi];
- lpfc_unreg_login(phba, vport->vpi, rpi, link_mbox);
- link_mbox->vport = vport;
- link_mbox->ctx_ndlp = lpfc_nlp_get(ndlp);
- if (!link_mbox->ctx_ndlp)
- goto out;
-
- link_mbox->mbox_cmpl = lpfc_defer_acc_rsp;
-
- if (((ndlp->nlp_DID & Fabric_DID_MASK) != Fabric_DID_MASK) &&
- (!(vport->fc_flag & FC_OFFLINE_MODE)))
- ndlp->nlp_flag |= NLP_UNREG_INP;
+ save_iocb = kzalloc(sizeof(*save_iocb), GFP_KERNEL);
+ if (!save_iocb)
+ goto out;
- /* Save info from cmd IOCB used in rsp */
- memcpy(save_iocb, cmdiocb, sizeof(*save_iocb));
+ /* Save info from cmd IOCB to be used in rsp after all mbox completes */
+ memcpy((uint8_t *)save_iocb, (uint8_t *)cmdiocb,
+ sizeof(struct lpfc_iocbq));
- /* Delay sending ACC till unreg RPI completes. */
- defer_acc = 1;
- } else if (phba->sli_rev == LPFC_SLI_REV4)
+ /* Registering an existing RPI behaves differently for SLI3 vs SLI4 */
+ if (phba->sli_rev == LPFC_SLI_REV4)
lpfc_unreg_rpi(vport, ndlp);
+ /* Issue REG_LOGIN first, before ACCing the PLOGI, thus we will
+ * always be deferring the ACC.
+ */
rc = lpfc_reg_rpi(phba, vport->vpi, icmd->un.rcvels.remoteID,
(uint8_t *)sp, login_mbox, ndlp->nlp_rpi);
if (rc)
goto out;
- /* ACC PLOGI rsp command needs to execute first,
- * queue this login_mbox command to be processed later.
- */
login_mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
- /*
- * login_mbox->ctx_ndlp = lpfc_nlp_get(ndlp) deferred until mailbox
- * command issued in lpfc_cmpl_els_acc().
- */
login_mbox->vport = vport;
- spin_lock_irq(&ndlp->lock);
- ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
- spin_unlock_irq(&ndlp->lock);
/*
* If there is an outstanding PLOGI issued, abort it before
@@ -660,7 +573,8 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
* to register, then unregister the RPI.
*/
spin_lock_irq(&ndlp->lock);
- ndlp->nlp_flag |= NLP_RM_DFLT_RPI;
+ ndlp->nlp_flag |= (NLP_RM_DFLT_RPI | NLP_ACC_REGLOGIN |
+ NLP_RCV_PLOGI);
spin_unlock_irq(&ndlp->lock);
stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
@@ -670,42 +584,39 @@ lpfc_rcv_plogi(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
mempool_free(login_mbox, phba->mbox_mem_pool);
return 1;
}
- if (defer_acc) {
- /* So the order here should be:
- * SLI3 pt2pt
- * Issue CONFIG_LINK mbox
- * CONFIG_LINK cmpl
- * SLI4 tgt
- * Issue UNREG RPI mbx
- * UNREG RPI cmpl
- * Issue PLOGI ACC
- * PLOGI ACC cmpl
- * Issue REG_LOGIN mbox
- */
- /* Save the REG_LOGIN mbox for and rcv IOCB copy later */
- link_mbox->context3 = login_mbox;
- login_mbox->context3 = save_iocb;
+ /* So the order here should be:
+ * SLI3 pt2pt
+ * Issue CONFIG_LINK mbox
+ * CONFIG_LINK cmpl
+ * SLI4 pt2pt
+ * Issue REG_VFI mbox
+ * REG_VFI cmpl
+ * SLI4
+ * Issue UNREG RPI mbx
+ * UNREG RPI cmpl
+ * Issue REG_RPI mbox
+ * REG RPI cmpl
+ * Issue PLOGI ACC
+ * PLOGI ACC cmpl
+ */
+ login_mbox->mbox_cmpl = lpfc_defer_plogi_acc;
+ login_mbox->ctx_ndlp = lpfc_nlp_get(ndlp);
+ login_mbox->context3 = save_iocb; /* For PLOGI ACC */
+
+ spin_lock_irq(&ndlp->lock);
+ ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
+ spin_unlock_irq(&ndlp->lock);
- /* Start the ball rolling by issuing CONFIG_LINK here */
- rc = lpfc_sli_issue_mbox(phba, link_mbox, MBX_NOWAIT);
- if (rc == MBX_NOT_FINISHED)
- goto out;
- return 1;
- }
+ /* Start the ball rolling by issuing REG_LOGIN here */
+ rc = lpfc_sli_issue_mbox(phba, login_mbox, MBX_NOWAIT);
+ if (rc == MBX_NOT_FINISHED)
+ goto out;
+ lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE);
- rc = lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, login_mbox);
- if (rc)
- mempool_free(login_mbox, phba->mbox_mem_pool);
return 1;
out:
- if (defer_acc)
- lpfc_printf_log(phba, KERN_ERR, LOG_TRACE_EVENT,
- "4577 discovery failure: %p %p %p\n",
- save_iocb, link_mbox, login_mbox);
kfree(save_iocb);
- if (link_mbox)
- mempool_free(link_mbox, phba->mbox_mem_pool);
if (login_mbox)
mempool_free(login_mbox, phba->mbox_mem_pool);
@@ -913,9 +824,14 @@ lpfc_rcv_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
}
} else if ((!(ndlp->nlp_type & NLP_FABRIC) &&
((ndlp->nlp_type & NLP_FCP_TARGET) ||
- !(ndlp->nlp_type & NLP_FCP_INITIATOR))) ||
+ (ndlp->nlp_type & NLP_NVME_TARGET) ||
+ (vport->fc_flag & FC_PT2PT))) ||
(ndlp->nlp_state == NLP_STE_ADISC_ISSUE)) {
- /* Only try to re-login if this is NOT a Fabric Node */
+ /* Only try to re-login if this is NOT a Fabric Node
+ * AND the remote NPORT is a FCP/NVME Target or we
+ * are in pt2pt mode. NLP_STE_ADISC_ISSUE is a special
+ * case for LOGO as a response to ADISC behavior.
+ */
mod_timer(&ndlp->nlp_delayfunc,
jiffies + msecs_to_jiffies(1000 * 1));
spin_lock_irq(&ndlp->lock);
@@ -1985,8 +1901,6 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_vport *vport,
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
lpfc_issue_els_logo(vport, ndlp, 0);
- ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
return ndlp->nlp_state;
}
@@ -2570,6 +2484,16 @@ lpfc_rcv_prlo_unmap_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
}
static uint32_t
+lpfc_device_rm_unmap_node(struct lpfc_vport *vport,
+ struct lpfc_nodelist *ndlp,
+ void *arg,
+ uint32_t evt)
+{
+ lpfc_drop_node(vport, ndlp);
+ return NLP_STE_FREED_NODE;
+}
+
+static uint32_t
lpfc_device_recov_unmap_node(struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp,
void *arg,
@@ -2633,12 +2557,10 @@ static uint32_t
lpfc_rcv_prlo_mapped_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
{
- struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *cmdiocb = (struct lpfc_iocbq *) arg;
/* flush the target */
- lpfc_sli_abort_iocb(vport, &phba->sli.sli3_ring[LPFC_FCP_RING],
- ndlp->nlp_sid, 0, LPFC_CTX_TGT);
+ lpfc_sli_abort_iocb(vport, ndlp->nlp_sid, 0, LPFC_CTX_TGT);
/* Treat like rcv logo */
lpfc_rcv_logo(vport, ndlp, cmdiocb, ELS_CMD_PRLO);
@@ -3062,7 +2984,7 @@ static uint32_t (*lpfc_disc_action[NLP_STE_MAX_STATE * NLP_EVT_MAX_EVENT])
lpfc_disc_illegal, /* CMPL_LOGO */
lpfc_disc_illegal, /* CMPL_ADISC */
lpfc_disc_illegal, /* CMPL_REG_LOGIN */
- lpfc_disc_illegal, /* DEVICE_RM */
+ lpfc_device_rm_unmap_node, /* DEVICE_RM */
lpfc_device_recov_unmap_node, /* DEVICE_RECOVERY */
lpfc_rcv_plogi_mapped_node, /* RCV_PLOGI MAPPED_NODE */