* more details, a copy of which can be found in the file COPYING *
* included with this package. *
*******************************************************************/
-
+/* See Fibre Channel protocol T11 FC-LS for details */
#include <linux/blkdev.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
struct lpfc_iocbq *);
static void lpfc_cmpl_fabric_iocb(struct lpfc_hba *, struct lpfc_iocbq *,
struct lpfc_iocbq *);
+static void lpfc_fabric_abort_vport(struct lpfc_vport *vport);
+static int lpfc_issue_els_fdisc(struct lpfc_vport *vport,
+ struct lpfc_nodelist *ndlp, uint8_t retry);
+static int lpfc_issue_fabric_iocb(struct lpfc_hba *phba,
+ struct lpfc_iocbq *iocb);
+static void lpfc_register_new_vport(struct lpfc_hba *phba,
+ struct lpfc_vport *vport,
+ struct lpfc_nodelist *ndlp);
static int lpfc_max_els_tries = 3;
return 0;
/* Pending Link Event during Discovery */
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
- "%d (%d):0237 Pending Link Event during "
- "Discovery: State x%x\n",
- phba->brd_no, vport->vpi, phba->pport->port_state);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ "0237 Pending Link Event during "
+ "Discovery: State x%x\n",
+ phba->pport->port_state);
/* CLEAR_LA should re-enable link attention events and
* we should then imediately take a LATT event. The
/* fill in BDEs for command */
/* Allocate buffer for command payload */
- if (((pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL)) == 0) ||
- ((pcmd->virt = lpfc_mbuf_alloc(phba,
- MEM_PRI, &(pcmd->phys))) == 0)) {
- kfree(pcmd);
-
- lpfc_sli_release_iocbq(phba, elsiocb);
- return NULL;
- }
+ pcmd = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
+ if (pcmd)
+ pcmd->virt = lpfc_mbuf_alloc(phba, MEM_PRI, &pcmd->phys);
+ if (!pcmd || !pcmd->virt)
+ goto els_iocb_free_pcmb_exit;
INIT_LIST_HEAD(&pcmd->list);
if (prsp)
prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
&prsp->phys);
- if (prsp == 0 || prsp->virt == 0) {
- kfree(prsp);
- lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
- kfree(pcmd);
- lpfc_sli_release_iocbq(phba, elsiocb);
- return NULL;
- }
+ if (!prsp || !prsp->virt)
+ goto els_iocb_free_prsp_exit;
INIT_LIST_HEAD(&prsp->list);
} else {
prsp = NULL;
if (pbuflist)
pbuflist->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
&pbuflist->phys);
- if (pbuflist == 0 || pbuflist->virt == 0) {
- lpfc_sli_release_iocbq(phba, elsiocb);
- lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
- lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
- kfree(pcmd);
- kfree(prsp);
- kfree(pbuflist);
- return NULL;
- }
+ if (!pbuflist || !pbuflist->virt)
+ goto els_iocb_free_pbuf_exit;
INIT_LIST_HEAD(&pbuflist->list);
bpl->tus.w = le32_to_cpu(bpl->tus.w);
}
- /* Save for completion so we can release these resources */
- if (elscmd != ELS_CMD_LS_RJT)
- elsiocb->context1 = lpfc_nlp_get(ndlp);
+ /* prevent preparing iocb with NULL ndlp reference */
+ elsiocb->context1 = lpfc_nlp_get(ndlp);
+ if (!elsiocb->context1)
+ goto els_iocb_free_pbuf_exit;
elsiocb->context2 = pcmd;
elsiocb->context3 = pbuflist;
elsiocb->retry = retry;
if (prsp) {
list_add(&prsp->list, &pcmd->list);
}
-
if (expectRsp) {
/* Xmit ELS command <elsCmd> to remote NPORT <did> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0116 Xmit ELS command x%x to remote "
- "NPORT x%x I/O tag: x%x, port state: x%x\n",
- phba->brd_no, vport->vpi, elscmd, did,
- elsiocb->iotag, vport->port_state);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0116 Xmit ELS command x%x to remote "
+ "NPORT x%x I/O tag: x%x, port state: x%x\n",
+ elscmd, did, elsiocb->iotag,
+ vport->port_state);
} else {
/* Xmit ELS response <elsCmd> to remote NPORT <did> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0117 Xmit ELS response x%x to remote "
- "NPORT x%x I/O tag: x%x, size: x%x\n",
- phba->brd_no, vport->vpi, elscmd,
- ndlp->nlp_DID, elsiocb->iotag, cmdSize);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0117 Xmit ELS response x%x to remote "
+ "NPORT x%x I/O tag: x%x, size: x%x\n",
+ elscmd, ndlp->nlp_DID, elsiocb->iotag,
+ cmdSize);
}
-
return elsiocb;
-}
+els_iocb_free_pbuf_exit:
+ lpfc_mbuf_free(phba, prsp->virt, prsp->phys);
+ kfree(pbuflist);
+
+els_iocb_free_prsp_exit:
+ lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
+ kfree(prsp);
+
+els_iocb_free_pcmb_exit:
+ kfree(pcmd);
+ lpfc_sli_release_iocbq(phba, elsiocb);
+ return NULL;
+}
static int
lpfc_issue_fabric_reglogin(struct lpfc_vport *vport)
struct lpfc_nodelist *ndlp;
struct serv_parm *sp;
int rc;
+ int err = 0;
sp = &phba->fc_fabparam;
ndlp = lpfc_findnode_did(vport, Fabric_DID);
- if (!ndlp)
+ if (!ndlp) {
+ err = 1;
goto fail;
+ }
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!mbox)
+ if (!mbox) {
+ err = 2;
goto fail;
+ }
vport->port_state = LPFC_FABRIC_CFG_LINK;
lpfc_config_link(phba, mbox);
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->vport = vport;
- rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
- if (rc == MBX_NOT_FINISHED)
+ rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+ if (rc == MBX_NOT_FINISHED) {
+ err = 3;
goto fail_free_mbox;
+ }
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
- if (!mbox)
+ if (!mbox) {
+ err = 4;
goto fail;
+ }
rc = lpfc_reg_login(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox,
0);
- if (rc)
+ if (rc) {
+ err = 5;
goto fail_free_mbox;
+ }
mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
mbox->vport = vport;
mbox->context2 = lpfc_nlp_get(ndlp);
- rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
- if (rc == MBX_NOT_FINISHED)
+ rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+ if (rc == MBX_NOT_FINISHED) {
+ err = 6;
goto fail_issue_reg_login;
+ }
return 0;
fail:
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0249 Cannot issue Register Fabric login\n",
- phba->brd_no, vport->vpi);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0249 Cannot issue Register Fabric login: Err %d\n", err);
return -ENXIO;
}
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
if (sp->cmn.response_multiple_NPort) {
- lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
- "%d:1816 FLOGI NPIV supported, "
- "response data 0x%x\n",
- phba->brd_no,
- sp->cmn.response_multiple_NPort);
+ lpfc_printf_vlog(vport, KERN_WARNING,
+ LOG_ELS | LOG_VPORT,
+ "1816 FLOGI NPIV supported, "
+ "response data 0x%x\n",
+ sp->cmn.response_multiple_NPort);
phba->link_flag |= LS_NPIV_FAB_SUPPORTED;
-
} else {
/* Because we asked f/w for NPIV it still expects us
- to call reg_vnpid atleast for the physcial host */
- lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
- "%d:1817 Fabric does not support NPIV "
- "- configuring single port mode.\n",
- phba->brd_no);
+ to call reg_vnpid atleast for the physcial host */
+ lpfc_printf_vlog(vport, KERN_WARNING,
+ LOG_ELS | LOG_VPORT,
+ "1817 Fabric does not support NPIV "
+ "- configuring single port mode.\n");
phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
}
}
}
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
lpfc_mbx_unreg_vpi(vport);
+ spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
}
}
- ndlp->nlp_sid = irsp->un.ulpWord[4] & Mask_DID;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_REG_LOGIN_ISSUE);
if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED &&
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->vport = vport;
- rc = lpfc_sli_issue_mbox(phba, mbox,
- MBX_NOWAIT | MBX_STOP_IOCB);
+ rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool);
goto fail;
lpfc_nlp_put(ndlp);
}
+ /* If we are pt2pt with another NPort, force NPIV off! */
+ phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED;
+
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_PT2PT;
spin_unlock_irq(shost->host_lock);
/* Check to see if link went down during discovery */
if (lpfc_els_chk_latt(vport)) {
+ /* One additional decrement on node reference count to
+ * trigger the release of the node
+ */
lpfc_nlp_put(ndlp);
goto out;
}
* alpa map would take too long otherwise.
*/
if (phba->alpa_map[0] == 0) {
- phba->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
+ vport->cfg_discovery_threads = LPFC_MAX_DISC_THREADS;
}
/* FLOGI failure */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0100 FLOGI failure Data: x%x x%x "
- "x%x\n",
- phba->brd_no, vport->vpi,
- irsp->ulpStatus, irsp->un.ulpWord[4],
- irsp->ulpTimeout);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0100 FLOGI failure Data: x%x x%x "
+ "x%x\n",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpTimeout);
goto flogifail;
}
sp = prsp->virt + sizeof(uint32_t);
/* FLOGI completes successfully */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0101 FLOGI completes sucessfully "
- "Data: x%x x%x x%x x%x\n",
- phba->brd_no, vport->vpi,
- irsp->un.ulpWord[4], sp->cmn.e_d_tov,
- sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0101 FLOGI completes sucessfully "
+ "Data: x%x x%x x%x x%x\n",
+ irsp->un.ulpWord[4], sp->cmn.e_d_tov,
+ sp->cmn.w2.r_a_tov, sp->cmn.edtovResolution);
if (vport->port_state == LPFC_FLOGI) {
/*
/* Start discovery */
lpfc_disc_start(vport);
+ } else if (((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
+ ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) &&
+ (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) &&
+ (phba->link_state != LPFC_CLEAR_LA)) {
+ /* If FLOGI failed enable link interrupt. */
+ lpfc_issue_clear_la(phba, vport);
}
-
out:
lpfc_els_free_iocb(phba, cmdiocb);
}
/* Abort outstanding I/O on NPort <nlp_DID> */
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
- "%d:0201 Abort outstanding I/O on NPort x%x\n",
- phba->brd_no, Fabric_DID);
+ "0201 Abort outstanding I/O on NPort x%x\n",
+ Fabric_DID);
pring = &phba->sli.ring[LPFC_ELS_RING];
struct lpfc_hba *phba = vport->phba;
struct lpfc_nodelist *ndlp;
+ vport->port_state = LPFC_FLOGI;
+ lpfc_set_disctmo(vport);
+
/* First look for the Fabric ndlp */
ndlp = lpfc_findnode_did(vport, Fabric_DID);
if (!ndlp) {
} else {
lpfc_dequeue_node(vport, ndlp);
}
+
if (lpfc_issue_els_flogi(vport, ndlp, 0)) {
+ /* This decrement of reference count to node shall kick off
+ * the release of the node.
+ */
lpfc_nlp_put(ndlp);
}
return 1;
lpfc_dequeue_node(vport, ndlp);
}
if (lpfc_issue_els_fdisc(vport, ndlp, 0)) {
+ /* decrement node reference count to trigger the release of
+ * the node.
+ */
lpfc_nlp_put(ndlp);
+ return 0;
}
return 1;
}
-static void
+
+void
lpfc_more_plogi(struct lpfc_vport *vport)
{
int sentplogi;
- struct lpfc_hba *phba = vport->phba;
if (vport->num_disc_nodes)
vport->num_disc_nodes--;
/* Continue discovery with <num_disc_nodes> PLOGIs to go */
- lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
- "%d (%d):0232 Continue discovery with %d PLOGIs to go "
- "Data: x%x x%x x%x\n",
- phba->brd_no, vport->vpi, vport->num_disc_nodes,
- vport->fc_plogi_cnt, vport->fc_flag, vport->port_state);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0232 Continue discovery with %d PLOGIs to go "
+ "Data: x%x x%x x%x\n",
+ vport->num_disc_nodes, vport->fc_plogi_cnt,
+ vport->fc_flag, vport->port_state);
/* Check to see if there are more PLOGIs to be sent */
if (vport->fc_flag & FC_NLP_MORE)
/* go thru NPR nodes and issue any remaining ELS PLOGIs */
{
struct lpfc_vport *vport = ndlp->vport;
struct lpfc_nodelist *new_ndlp;
+ struct lpfc_rport_data *rdata;
+ struct fc_rport *rport;
struct serv_parm *sp;
uint8_t name[sizeof(struct lpfc_name)];
uint32_t rc;
lpfc_unreg_rpi(vport, new_ndlp);
new_ndlp->nlp_DID = ndlp->nlp_DID;
new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
+
+ if (ndlp->nlp_flag & NLP_NPR_2B_DISC)
+ new_ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+ ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+
lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state);
/* Move this back to NPR state */
- if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0)
+ if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) {
+ /* The new_ndlp is replacing ndlp totally, so we need
+ * to put ndlp on UNUSED list and try to free it.
+ */
+
+ /* Fix up the rport accordingly */
+ rport = ndlp->rport;
+ if (rport) {
+ rdata = rport->dd_data;
+ if (rdata->pnode == ndlp) {
+ lpfc_nlp_put(ndlp);
+ ndlp->rport = NULL;
+ rdata->pnode = lpfc_nlp_get(new_ndlp);
+ new_ndlp->rport = rport;
+ }
+ new_ndlp->nlp_type = ndlp->nlp_type;
+ }
+
lpfc_drop_node(vport, ndlp);
+ }
else {
lpfc_unreg_rpi(vport, ndlp);
ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
return new_ndlp;
}
+void
+lpfc_end_rscn(struct lpfc_vport *vport)
+{
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+ if (vport->fc_flag & FC_RSCN_MODE) {
+ /*
+ * Check to see if more RSCNs came in while we were
+ * processing this one.
+ */
+ if (vport->fc_rscn_id_cnt ||
+ (vport->fc_flag & FC_RSCN_DISCOVERY) != 0)
+ lpfc_els_handle_rscn(vport);
+ else {
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag &= ~FC_RSCN_MODE;
+ spin_unlock_irq(shost->host_lock);
+ }
+ }
+}
+
static void
lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
if (!ndlp) {
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0136 PLOGI completes to NPort x%x "
- "with no ndlp. Data: x%x x%x x%x\n",
- phba->brd_no, vport->vpi, irsp->un.elsreq64.remoteID,
- irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpIoTag);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0136 PLOGI completes to NPort x%x "
+ "with no ndlp. Data: x%x x%x x%x\n",
+ irsp->un.elsreq64.remoteID,
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpIoTag);
goto out;
}
rc = 0;
/* PLOGI completes to NPort <nlp_DID> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0102 PLOGI completes to NPort x%x "
- "Data: x%x x%x x%x x%x x%x\n",
- phba->brd_no, vport->vpi, ndlp->nlp_DID,
- irsp->ulpStatus, irsp->un.ulpWord[4],
- irsp->ulpTimeout, disc, vport->num_disc_nodes);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0102 PLOGI completes to NPort x%x "
+ "Data: x%x x%x x%x x%x x%x\n",
+ ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpTimeout, disc, vport->num_disc_nodes);
/* Check to see if link went down during discovery */
if (lpfc_els_chk_latt(vport)) {
spin_lock_irq(shost->host_lock);
}
goto out;
}
-
/* PLOGI failed */
- if (ndlp->nlp_DID == NameServer_DID) {
- lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0250 Nameserver login error: "
- "0x%x / 0x%x\n",
- phba->brd_no, vport->vpi,
- irsp->ulpStatus, irsp->un.ulpWord[4]);
- }
-
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
if (lpfc_error_lost_link(irsp)) {
rc = NLP_STE_FREED_NODE;
spin_unlock_irq(shost->host_lock);
lpfc_can_disctmo(vport);
- if (vport->fc_flag & FC_RSCN_MODE) {
- /*
- * Check to see if more RSCNs came in while
- * we were processing this one.
- */
- if ((vport->fc_rscn_id_cnt == 0) &&
- (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
- spin_lock_irq(shost->host_lock);
- vport->fc_flag &= ~FC_RSCN_MODE;
- spin_unlock_irq(shost->host_lock);
- } else {
- lpfc_els_handle_rscn(vport);
- }
- }
+ lpfc_end_rscn(vport);
}
}
struct lpfc_hba *phba = vport->phba;
struct serv_parm *sp;
IOCB_t *icmd;
+ struct lpfc_nodelist *ndlp;
struct lpfc_iocbq *elsiocb;
struct lpfc_sli_ring *pring;
struct lpfc_sli *psli;
psli = &phba->sli;
pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
+ ndlp = lpfc_findnode_did(vport, did);
+ /* If ndlp if not NULL, we will bump the reference count on it */
+
cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
- elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, NULL, did,
+ elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
ELS_CMD_PLOGI);
if (!elsiocb)
return 1;
"PRLI cmpl: status:x%x/x%x did:x%x",
irsp->ulpStatus, irsp->un.ulpWord[4],
ndlp->nlp_DID);
-
/* PRLI completes to NPort <nlp_DID> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0103 PRLI completes to NPort x%x "
- "Data: x%x x%x x%x x%x\n",
- phba->brd_no, vport->vpi, ndlp->nlp_DID,
- irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
- vport->num_disc_nodes);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0103 PRLI completes to NPort x%x "
+ "Data: x%x x%x x%x x%x\n",
+ ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpTimeout, vport->num_disc_nodes);
vport->fc_prli_sent--;
/* Check to see if link went down during discovery */
return 0;
}
-static void
+void
lpfc_more_adisc(struct lpfc_vport *vport)
{
int sentadisc;
- struct lpfc_hba *phba = vport->phba;
if (vport->num_disc_nodes)
vport->num_disc_nodes--;
-
/* Continue discovery with <num_disc_nodes> ADISCs to go */
- lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
- "%d (%d):0210 Continue discovery with %d ADISCs to go "
- "Data: x%x x%x x%x\n",
- phba->brd_no, vport->vpi, vport->num_disc_nodes,
- vport->fc_adisc_cnt, vport->fc_flag, vport->port_state);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0210 Continue discovery with %d ADISCs to go "
+ "Data: x%x x%x x%x\n",
+ vport->num_disc_nodes, vport->fc_adisc_cnt,
+ vport->fc_flag, vport->port_state);
/* Check to see if there are more ADISCs to be sent */
if (vport->fc_flag & FC_NLP_MORE) {
lpfc_set_disctmo(vport);
static void
lpfc_rscn_disc(struct lpfc_vport *vport)
{
- struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-
lpfc_can_disctmo(vport);
/* RSCN discovery */
if (lpfc_els_disc_plogi(vport))
return;
- if (vport->fc_flag & FC_RSCN_MODE) {
- /* Check to see if more RSCNs came in while we were
- * processing this one.
- */
- if ((vport->fc_rscn_id_cnt == 0) &&
- (!(vport->fc_flag & FC_RSCN_DISCOVERY))) {
- spin_lock_irq(shost->host_lock);
- vport->fc_flag &= ~FC_RSCN_MODE;
- spin_unlock_irq(shost->host_lock);
- } else {
- lpfc_els_handle_rscn(vport);
- }
- }
+ lpfc_end_rscn(vport);
}
static void
disc = (ndlp->nlp_flag & NLP_NPR_2B_DISC);
ndlp->nlp_flag &= ~(NLP_ADISC_SND | NLP_NPR_2B_DISC);
spin_unlock_irq(shost->host_lock);
-
/* ADISC completes to NPort <nlp_DID> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0104 ADISC completes to NPort x%x "
- "Data: x%x x%x x%x x%x x%x\n",
- phba->brd_no, vport->vpi, ndlp->nlp_DID,
- irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
- disc, vport->num_disc_nodes);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0104 ADISC completes to NPort x%x "
+ "Data: x%x x%x x%x x%x x%x\n",
+ ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpTimeout, disc, vport->num_disc_nodes);
/* Check to see if link went down during discovery */
if (lpfc_els_chk_latt(vport)) {
spin_lock_irq(shost->host_lock);
"LOGO cmpl: status:x%x/x%x did:x%x",
irsp->ulpStatus, irsp->un.ulpWord[4],
ndlp->nlp_DID);
-
/* LOGO completes to NPort <nlp_DID> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0105 LOGO completes to NPort x%x "
- "Data: x%x x%x x%x x%x\n",
- phba->brd_no, vport->vpi, ndlp->nlp_DID,
- irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpTimeout,
- vport->num_disc_nodes);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0105 LOGO completes to NPort x%x "
+ "Data: x%x x%x x%x x%x\n",
+ ndlp->nlp_DID, irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->ulpTimeout, vport->num_disc_nodes);
/* Check to see if link went down during discovery */
if (lpfc_els_chk_latt(vport))
goto out;
psli = &phba->sli;
pring = &psli->ring[LPFC_ELS_RING];
+ spin_lock_irq(shost->host_lock);
+ if (ndlp->nlp_flag & NLP_LOGO_SND) {
+ spin_unlock_irq(shost->host_lock);
+ return 0;
+ }
+ spin_unlock_irq(shost->host_lock);
+
cmdsize = (2 * sizeof(uint32_t)) + sizeof(struct lpfc_name);
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
ndlp->nlp_DID, ELS_CMD_LOGO);
"ELS cmd cmpl: status:x%x/x%x did:x%x",
irsp->ulpStatus, irsp->un.ulpWord[4],
irsp->un.elsreq64.remoteID);
-
/* ELS cmd tag <ulpIoTag> completes */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0106 ELS cmd tag x%x completes Data: x%x x%x "
- "x%x\n",
- phba->brd_no, vport->vpi,
- irsp->ulpIoTag, irsp->ulpStatus,
- irsp->un.ulpWord[4], irsp->ulpTimeout);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0106 ELS cmd tag x%x completes Data: x%x x%x x%x\n",
+ irsp->ulpIoTag, irsp->ulpStatus,
+ irsp->un.ulpWord[4], irsp->ulpTimeout);
/* Check to see if link went down during discovery */
lpfc_els_chk_latt(vport);
lpfc_els_free_iocb(phba, cmdiocb);
ndlp->nlp_DID, ELS_CMD_SCR);
if (!elsiocb) {
+ /* This will trigger the release of the node just
+ * allocated
+ */
lpfc_nlp_put(ndlp);
return 1;
}
phba->fc_stat.elsXmitSCR++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+ /* The additional lpfc_nlp_put will cause the following
+ * lpfc_els_free_iocb routine to trigger the rlease of
+ * the node.
+ */
lpfc_nlp_put(ndlp);
lpfc_els_free_iocb(phba, elsiocb);
return 1;
}
+ /* This will cause the callback-function lpfc_cmpl_els_cmd to
+ * trigger the release of node.
+ */
lpfc_nlp_put(ndlp);
return 0;
}
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
ndlp->nlp_DID, ELS_CMD_RNID);
if (!elsiocb) {
+ /* This will trigger the release of the node just
+ * allocated
+ */
lpfc_nlp_put(ndlp);
return 1;
}
phba->fc_stat.elsXmitFARPR++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_cmd;
if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
+ /* The additional lpfc_nlp_put will cause the following
+ * lpfc_els_free_iocb routine to trigger the release of
+ * the node.
+ */
lpfc_nlp_put(ndlp);
lpfc_els_free_iocb(phba, elsiocb);
return 1;
}
+ /* This will cause the callback-function lpfc_cmpl_els_cmd to
+ * trigger the release of the node.
+ */
lpfc_nlp_put(ndlp);
return 0;
}
-static void
-lpfc_end_rscn(struct lpfc_vport *vport)
-{
- struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
-
- if (vport->fc_flag & FC_RSCN_MODE) {
- /*
- * Check to see if more RSCNs came in while we were
- * processing this one.
- */
- if (vport->fc_rscn_id_cnt ||
- (vport->fc_flag & FC_RSCN_DISCOVERY) != 0)
- lpfc_els_handle_rscn(vport);
- else {
- spin_lock_irq(shost->host_lock);
- vport->fc_flag &= ~FC_RSCN_MODE;
- spin_unlock_irq(shost->host_lock);
- }
- }
-}
-
void
lpfc_cancel_retry_delay_tmo(struct lpfc_vport *vport, struct lpfc_nodelist *nlp)
{
return;
}
- evtp->evt_arg1 = ndlp;
+ /* We need to hold the node by incrementing the reference
+ * count until the queued work is done
+ */
+ evtp->evt_arg1 = lpfc_nlp_get(ndlp);
evtp->evt = LPFC_EVT_ELS_RETRY;
list_add_tail(&evtp->evt_listp, &phba->work_list);
if (phba->work_wait)
uint32_t *elscmd;
struct ls_rjt stat;
int retry = 0, maxretry = lpfc_max_els_tries, delay = 0;
+ int logerr = 0;
uint32_t cmd = 0;
uint32_t did;
case IOERR_ILLEGAL_COMMAND:
if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) &&
(cmd == ELS_CMD_FDISC)) {
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0124 FDISC failed (3/6) retrying...\n",
- phba->brd_no, vport->vpi);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0124 FDISC failed (3/6) "
+ "retrying...\n");
lpfc_mbx_unreg_vpi(vport);
retry = 1;
- /* Always retry for this case */
- cmdiocb->retry = 0;
+ /* FDISC retry policy */
+ maxretry = 48;
+ if (cmdiocb->retry >= 32)
+ delay = 1000;
}
break;
case IOERR_NO_RESOURCES:
+ logerr = 1; /* HBA out of resources */
retry = 1;
if (cmdiocb->retry > 100)
delay = 100;
case IOSTAT_NPORT_BSY:
case IOSTAT_FABRIC_BSY:
+ logerr = 1; /* Fabric / Remote NPort out of resources */
retry = 1;
break;
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
(cmd == ELS_CMD_FDISC) &&
(stat.un.b.lsRjtRsnCodeExp == LSEXP_OUT_OF_RESOURCE)){
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0125 FDISC Failed (x%x)."
- " Fabric out of resources\n",
- phba->brd_no, vport->vpi, stat.un.lsRjtError);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0125 FDISC Failed (x%x). "
+ "Fabric out of resources\n",
+ stat.un.lsRjtError);
lpfc_vport_set_state(vport,
FC_VPORT_NO_FABRIC_RSCS);
}
delay = 1000;
maxretry = 48;
} else if (cmd == ELS_CMD_FDISC) {
- /* Always retry for this case */
- cmdiocb->retry = 0;
+ /* FDISC retry policy */
+ maxretry = 48;
+ if (cmdiocb->retry >= 32)
+ delay = 1000;
}
retry = 1;
break;
((stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_PNAME) ||
(stat.un.b.lsRjtRsnCodeExp == LSEXP_INVALID_NPORT_ID))
) {
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0123 FDISC Failed (x%x)."
- " Fabric Detected Bad WWN\n",
- phba->brd_no, vport->vpi, stat.un.lsRjtError);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0123 FDISC Failed (x%x). "
+ "Fabric Detected Bad WWN\n",
+ stat.un.lsRjtError);
lpfc_vport_set_state(vport,
FC_VPORT_FABRIC_REJ_WWN);
}
if (did == FDMI_DID)
retry = 1;
+ if ((cmd == ELS_CMD_FLOGI) &&
+ (phba->fc_topology != TOPOLOGY_LOOP)) {
+ /* FLOGI retry policy */
+ retry = 1;
+ maxretry = 48;
+ if (cmdiocb->retry >= 32)
+ delay = 1000;
+ }
+
if ((++cmdiocb->retry) >= maxretry) {
phba->fc_stat.elsRetryExceeded++;
retry = 0;
if (retry) {
/* Retry ELS command <elsCmd> to remote NPORT <did> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0107 Retry ELS command x%x to remote "
- "NPORT x%x Data: x%x x%x\n",
- phba->brd_no, vport->vpi,
- cmd, did, cmdiocb->retry, delay);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0107 Retry ELS command x%x to remote "
+ "NPORT x%x Data: x%x x%x\n",
+ cmd, did, cmdiocb->retry, delay);
if (((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) &&
((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
return 1;
}
}
-
/* No retry ELS command <elsCmd> to remote NPORT <did> */
- lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ if (logerr) {
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0137 No retry ELS command x%x to remote "
+ "NPORT x%x: Out of Resources: Error:x%x/%x\n",
+ cmd, did, irsp->ulpStatus,
+ irsp->un.ulpWord[4]);
+ }
+ else {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
"0108 No retry ELS command x%x to remote "
"NPORT x%x Retried:%d Error:x%x/%x\n",
cmd, did, cmdiocb->retry, irsp->ulpStatus,
irsp->un.ulpWord[4]);
+ }
+ return 0;
+}
+
+static int
+lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
+{
+ struct lpfc_dmabuf *buf_ptr;
+
+ /* Free the response before processing the command. */
+ if (!list_empty(&buf_ptr1->list)) {
+ list_remove_head(&buf_ptr1->list, buf_ptr,
+ struct lpfc_dmabuf,
+ list);
+ lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+ kfree(buf_ptr);
+ }
+ lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
+ kfree(buf_ptr1);
+ return 0;
+}
+
+static int
+lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr)
+{
+ lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+ kfree(buf_ptr);
return 0;
}
lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb)
{
struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
+ struct lpfc_nodelist *ndlp;
- if (elsiocb->context1) {
- lpfc_nlp_put(elsiocb->context1);
+ ndlp = (struct lpfc_nodelist *)elsiocb->context1;
+ if (ndlp) {
+ if (ndlp->nlp_flag & NLP_DEFER_RM) {
+ lpfc_nlp_put(ndlp);
+
+ /* If the ndlp is not being used by another discovery
+ * thread, free it.
+ */
+ if (!lpfc_nlp_not_used(ndlp)) {
+ /* If ndlp is being used by another discovery
+ * thread, just clear NLP_DEFER_RM
+ */
+ ndlp->nlp_flag &= ~NLP_DEFER_RM;
+ }
+ }
+ else
+ lpfc_nlp_put(ndlp);
elsiocb->context1 = NULL;
}
/* context2 = cmd, context2->next = rsp, context3 = bpl */
if (elsiocb->context2) {
- buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
- /* Free the response before processing the command. */
- if (!list_empty(&buf_ptr1->list)) {
- list_remove_head(&buf_ptr1->list, buf_ptr,
- struct lpfc_dmabuf,
- list);
- lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
- kfree(buf_ptr);
+ if (elsiocb->iocb_flag & LPFC_DELAY_MEM_FREE) {
+ /* Firmware could still be in progress of DMAing
+ * payload, so don't free data buffer till after
+ * a hbeat.
+ */
+ elsiocb->iocb_flag &= ~LPFC_DELAY_MEM_FREE;
+ buf_ptr = elsiocb->context2;
+ elsiocb->context2 = NULL;
+ if (buf_ptr) {
+ buf_ptr1 = NULL;
+ spin_lock_irq(&phba->hbalock);
+ if (!list_empty(&buf_ptr->list)) {
+ list_remove_head(&buf_ptr->list,
+ buf_ptr1, struct lpfc_dmabuf,
+ list);
+ INIT_LIST_HEAD(&buf_ptr1->list);
+ list_add_tail(&buf_ptr1->list,
+ &phba->elsbuf);
+ phba->elsbuf_cnt++;
+ }
+ INIT_LIST_HEAD(&buf_ptr->list);
+ list_add_tail(&buf_ptr->list, &phba->elsbuf);
+ phba->elsbuf_cnt++;
+ spin_unlock_irq(&phba->hbalock);
+ }
+ } else {
+ buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
+ lpfc_els_free_data(phba, buf_ptr1);
}
- lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
- kfree(buf_ptr1);
}
if (elsiocb->context3) {
buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3;
- lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
- kfree(buf_ptr);
+ lpfc_els_free_bpl(phba, buf_ptr);
}
lpfc_sli_release_iocbq(phba, elsiocb);
return 0;
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
"ACC LOGO cmpl: status:x%x/x%x did:x%x",
irsp->ulpStatus, irsp->un.ulpWord[4], ndlp->nlp_DID);
-
/* ACC to LOGO completes to NPort <nlp_DID> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0109 ACC to LOGO completes to NPort x%x "
- "Data: x%x x%x x%x\n",
- phba->brd_no, vport->vpi, ndlp->nlp_DID,
- ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
-
- switch (ndlp->nlp_state) {
- case NLP_STE_UNUSED_NODE: /* node is just allocated */
- lpfc_drop_node(vport, ndlp);
- break;
- case NLP_STE_NPR_NODE: /* NPort Recovery mode */
- lpfc_unreg_rpi(vport, ndlp);
- break;
- default:
- break;
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0109 ACC to LOGO completes to NPort x%x "
+ "Data: x%x x%x x%x\n",
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi);
+
+ if (ndlp->nlp_state == NLP_STE_NPR_NODE) {
+ /* NPort Recovery mode or node is just allocated */
+ if (!lpfc_nlp_not_used(ndlp)) {
+ /* If the ndlp is being used by another discovery
+ * thread, just unregister the RPI.
+ */
+ lpfc_unreg_rpi(vport, ndlp);
+ } else {
+ /* Indicate the node has already released, should
+ * not reference to it from within lpfc_els_free_iocb.
+ */
+ cmdiocb->context1 = NULL;
+ }
}
lpfc_els_free_iocb(phba, cmdiocb);
return;
lpfc_mbuf_free(phba, mp->virt, mp->phys);
kfree(mp);
mempool_free(pmb, phba->mbox_mem_pool);
- lpfc_nlp_put(ndlp);
+ if (ndlp) {
+ lpfc_nlp_put(ndlp);
+ /* This is the end of the default RPI cleanup logic for this
+ * ndlp. If no other discovery threads are using this ndlp.
+ * we should free all resources associated with it.
+ */
+ lpfc_nlp_not_used(ndlp);
+ }
return;
}
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
struct lpfc_vport *vport = ndlp ? ndlp->vport : NULL;
struct Scsi_Host *shost = vport ? lpfc_shost_from_vport(vport) : NULL;
- IOCB_t *irsp;
+ IOCB_t *irsp;
+ uint8_t *pcmd;
LPFC_MBOXQ_t *mbox = NULL;
struct lpfc_dmabuf *mp = NULL;
+ uint32_t ls_rjt = 0;
irsp = &rspiocb->iocb;
if (cmdiocb->context_un.mbox)
mbox = cmdiocb->context_un.mbox;
+ /* First determine if this is a LS_RJT cmpl. Note, this callback
+ * function can have cmdiocb->contest1 (ndlp) field set to NULL.
+ */
+ pcmd = (uint8_t *) (((struct lpfc_dmabuf *) cmdiocb->context2)->virt);
+ if (ndlp && (*((uint32_t *) (pcmd)) == ELS_CMD_LS_RJT)) {
+ /* A LS_RJT associated with Default RPI cleanup has its own
+ * seperate code path.
+ */
+ if (!(ndlp->nlp_flag & NLP_RM_DFLT_RPI))
+ ls_rjt = 1;
+ }
+
/* Check to see if link went down during discovery */
if (!ndlp || lpfc_els_chk_latt(vport)) {
if (mbox) {
}
mempool_free(mbox, phba->mbox_mem_pool);
}
+ if (ndlp && (ndlp->nlp_flag & NLP_RM_DFLT_RPI))
+ if (lpfc_nlp_not_used(ndlp)) {
+ ndlp = NULL;
+ /* Indicate the node has already released,
+ * should not reference to it from within
+ * the routine lpfc_els_free_iocb.
+ */
+ cmdiocb->context1 = NULL;
+ }
goto out;
}
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
- "ACC cmpl: status:x%x/x%x did:x%x",
+ "ELS rsp cmpl: status:x%x/x%x did:x%x",
irsp->ulpStatus, irsp->un.ulpWord[4],
- irsp->un.rcvels.remoteID);
-
+ cmdiocb->iocb.un.elsreq64.remoteID);
/* ELS response tag <ulpIoTag> completes */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0110 ELS response tag x%x completes "
- "Data: x%x x%x x%x x%x x%x x%x x%x\n",
- phba->brd_no, vport->vpi,
- cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
- rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
- ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
- ndlp->nlp_rpi);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0110 ELS response tag x%x completes "
+ "Data: x%x x%x x%x x%x x%x x%x x%x\n",
+ cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
+ rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi);
if (mbox) {
if ((rspiocb->iocb.ulpStatus == 0)
&& (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
lpfc_nlp_set_state(vport, ndlp,
NLP_STE_REG_LOGIN_ISSUE);
}
- if (lpfc_sli_issue_mbox(phba, mbox,
- (MBX_NOWAIT | MBX_STOP_IOCB))
+ if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
!= MBX_NOT_FINISHED) {
goto out;
}
- lpfc_nlp_put(ndlp);
- /* NOTE: we should have messages for unsuccessful
- reglogin */
+
+ /* ELS rsp: Cannot issue reg_login for <NPortid> */
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0138 ELS rsp: Cannot issue reg_login for x%x "
+ "Data: x%x x%x x%x\n",
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi);
+
+ if (lpfc_nlp_not_used(ndlp)) {
+ ndlp = NULL;
+ /* Indicate node has already been released,
+ * should not reference to it from within
+ * the routine lpfc_els_free_iocb.
+ */
+ cmdiocb->context1 = NULL;
+ }
} else {
/* Do not drop node for lpfc_els_abort'ed ELS cmds */
if (!lpfc_error_lost_link(irsp) &&
ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
- lpfc_drop_node(vport, ndlp);
- ndlp = NULL;
+ if (lpfc_nlp_not_used(ndlp)) {
+ ndlp = NULL;
+ /* Indicate node has already been
+ * released, should not reference
+ * to it from within the routine
+ * lpfc_els_free_iocb.
+ */
+ cmdiocb->context1 = NULL;
+ }
}
}
mp = (struct lpfc_dmabuf *) mbox->context1;
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
spin_unlock_irq(shost->host_lock);
+
+ /* If the node is not being used by another discovery thread,
+ * and we are sending a reject, we are done with it.
+ * Release driver reference count here and free associated
+ * resources.
+ */
+ if (ls_rjt)
+ if (lpfc_nlp_not_used(ndlp))
+ /* Indicate node has already been released,
+ * should not reference to it from within
+ * the routine lpfc_els_free_iocb.
+ */
+ cmdiocb->context1 = NULL;
}
+
lpfc_els_free_iocb(phba, cmdiocb);
return;
}
int
lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
- LPFC_MBOXQ_t *mbox, uint8_t newnode)
+ LPFC_MBOXQ_t *mbox)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
default:
return 1;
}
-
- if (newnode) {
- lpfc_nlp_put(ndlp);
- elsiocb->context1 = NULL;
- }
-
/* Xmit ELS ACC response tag <ulpIoTag> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
- "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
- phba->brd_no, vport->vpi, elsiocb->iotag,
- elsiocb->iocb.ulpContext, ndlp->nlp_DID,
- ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0128 Xmit ELS ACC response tag x%x, XRI: x%x, "
+ "DID: x%x, nlp_flag: x%x nlp_state: x%x RPI: x%x\n",
+ elsiocb->iotag, elsiocb->iocb.ulpContext,
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi);
if (ndlp->nlp_flag & NLP_LOGO_ACC) {
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_LOGO_ACC;
pcmd += sizeof(uint32_t);
*((uint32_t *) (pcmd)) = rejectError;
- if (mbox) {
+ if (mbox)
elsiocb->context_un.mbox = mbox;
- elsiocb->context1 = lpfc_nlp_get(ndlp);
- }
/* Xmit ELS RJT <err> response tag <ulpIoTag> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0129 Xmit ELS RJT x%x response tag x%x "
- "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
- "rpi x%x\n",
- phba->brd_no, vport->vpi, rejectError, elsiocb->iotag,
- elsiocb->iocb.ulpContext, ndlp->nlp_DID,
- ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0129 Xmit ELS RJT x%x response tag x%x "
+ "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
+ "rpi x%x\n",
+ rejectError, elsiocb->iotag,
+ elsiocb->iocb.ulpContext, ndlp->nlp_DID,
+ ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
"Issue LS_RJT: did:x%x flg:x%x err:x%x",
ndlp->nlp_DID, ndlp->nlp_flag, rejectError);
phba->fc_stat.elsXmitLSRJT++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
+
if (rc == IOCB_ERROR) {
lpfc_els_free_iocb(phba, elsiocb);
return 1;
icmd->ulpContext = oldcmd->ulpContext; /* Xri */
/* Xmit ADISC ACC response tag <ulpIoTag> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0130 Xmit ADISC ACC response iotag x%x xri: "
- "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n",
- phba->brd_no, vport->vpi, elsiocb->iotag,
- elsiocb->iocb.ulpContext, ndlp->nlp_DID,
- ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0130 Xmit ADISC ACC response iotag x%x xri: "
+ "x%x, did x%x, nlp_flag x%x, nlp_state x%x rpi x%x\n",
+ elsiocb->iotag, elsiocb->iocb.ulpContext,
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi);
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
icmd = &elsiocb->iocb;
oldcmd = &oldiocb->iocb;
icmd->ulpContext = oldcmd->ulpContext; /* Xri */
-
/* Xmit PRLI ACC response tag <ulpIoTag> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0131 Xmit PRLI ACC response tag x%x xri x%x, "
- "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
- phba->brd_no, vport->vpi, elsiocb->iotag,
- elsiocb->iocb.ulpContext, ndlp->nlp_DID,
- ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0131 Xmit PRLI ACC response tag x%x xri x%x, "
+ "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
+ elsiocb->iotag, elsiocb->iocb.ulpContext,
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi);
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
*((uint32_t *) (pcmd)) = (ELS_CMD_ACC | (ELS_CMD_PRLI & ~ELS_RSP_MASK));
icmd = &elsiocb->iocb;
oldcmd = &oldiocb->iocb;
icmd->ulpContext = oldcmd->ulpContext; /* Xri */
-
/* Xmit RNID ACC response tag <ulpIoTag> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0132 Xmit RNID ACC response tag x%x "
- "xri x%x\n",
- phba->brd_no, vport->vpi, elsiocb->iotag,
- elsiocb->iocb.ulpContext);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0132 Xmit RNID ACC response tag x%x xri x%x\n",
+ elsiocb->iotag, elsiocb->iocb.ulpContext);
pcmd = (uint8_t *) (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
-
*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
pcmd += sizeof(uint32_t);
sentadisc++;
vport->num_disc_nodes++;
if (vport->num_disc_nodes >=
- vport->phba->cfg_discovery_threads) {
+ vport->cfg_discovery_threads) {
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_NLP_MORE;
spin_unlock_irq(shost->host_lock);
sentplogi++;
vport->num_disc_nodes++;
if (vport->num_disc_nodes >=
- vport->phba->cfg_discovery_threads) {
+ vport->cfg_discovery_threads) {
spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_NLP_MORE;
spin_unlock_irq(shost->host_lock);
}
}
}
- if (sentplogi == 0) {
+ if (sentplogi) {
+ lpfc_set_disctmo(vport);
+ }
+ else {
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_NLP_MORE;
spin_unlock_irq(shost->host_lock);
D_ID rscn_did;
uint32_t *lp;
uint32_t payload_len, i;
- struct lpfc_hba *phba = vport->phba;
ns_did.un.word = did;
break;
default:
/* Unknown Identifier in RSCN node */
- lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
- "%d (%d):0217 Unknown "
- "Identifier in RSCN payload "
- "Data: x%x\n",
- phba->brd_no, vport->vpi,
- rscn_did.un.word);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+ "0217 Unknown Identifier in "
+ "RSCN payload Data: x%x\n",
+ rscn_did.un.word);
case 3: /* Whole Fabric effected */
return did;
}
static int
lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
- struct lpfc_nodelist *ndlp, uint8_t newnode)
+ struct lpfc_nodelist *ndlp)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
payload_len -= sizeof(uint32_t); /* take off word 0 */
-
/* RSCN received */
- lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
- "%d (%d):0214 RSCN received Data: x%x x%x x%x x%x\n",
- phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
- *lp, rscn_cnt);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0214 RSCN received Data: x%x x%x x%x x%x\n",
+ vport->fc_flag, payload_len, *lp, rscn_cnt);
for (i = 0; i < payload_len/sizeof(uint32_t); i++)
fc_host_post_event(shost, fc_get_event_number(),
FCH_EVT_RSCN, lp[i]);
"RCV RSCN ignore: did:x%x/ste:x%x flg:x%x",
ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
- lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
- newnode);
+ lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
return 0;
}
* just ACC and ignore it.
*/
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
- !(phba->cfg_peer_port_login)) {
+ !(vport->cfg_peer_port_login)) {
i = payload_len;
datap = lp;
while (i > 0) {
}
if (rscn_id == hba_id) {
/* ALL NPortIDs in RSCN are on HBA */
- lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
- "%d (%d):0214 Ignore RSCN Data: x%x x%x x%x x%x\n",
- phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
- *lp, rscn_cnt);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0214 Ignore RSCN "
+ "Data: x%x x%x x%x x%x\n",
+ vport->fc_flag, payload_len,
+ *lp, rscn_cnt);
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
"RCV RSCN vport: did:x%x/ste:x%x flg:x%x",
ndlp->nlp_DID, vport->port_state,
ndlp->nlp_flag);
lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
- ndlp, NULL, newnode);
+ ndlp, NULL);
return 0;
}
}
"RCV RSCN defer: did:x%x/ste:x%x flg:x%x",
ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
+ spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_RSCN_DEFERRED;
if ((rscn_cnt < FC_MAX_HOLD_RSCN) &&
!(vport->fc_flag & FC_RSCN_DISCOVERY)) {
- spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_RSCN_MODE;
spin_unlock_irq(shost->host_lock);
if (rscn_cnt) {
}
/* Deferred RSCN */
- lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
- "%d (%d):0235 Deferred RSCN "
- "Data: x%x x%x x%x\n",
- phba->brd_no, vport->vpi,
- vport->fc_rscn_id_cnt, vport->fc_flag,
- vport->port_state);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0235 Deferred RSCN "
+ "Data: x%x x%x x%x\n",
+ vport->fc_rscn_id_cnt, vport->fc_flag,
+ vport->port_state);
} else {
- spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_RSCN_DISCOVERY;
spin_unlock_irq(shost->host_lock);
/* ReDiscovery RSCN */
- lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
- "%d (%d):0234 ReDiscovery RSCN "
- "Data: x%x x%x x%x\n",
- phba->brd_no, vport->vpi,
- vport->fc_rscn_id_cnt, vport->fc_flag,
- vport->port_state);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0234 ReDiscovery RSCN "
+ "Data: x%x x%x x%x\n",
+ vport->fc_rscn_id_cnt, vport->fc_flag,
+ vport->port_state);
}
/* Send back ACC */
- lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
- newnode);
+ lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
/* send RECOVERY event for ALL nodes that match RSCN payload */
lpfc_rscn_recovery_check(vport);
+ spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_RSCN_DEFERRED;
+ spin_unlock_irq(shost->host_lock);
return 0;
}
lpfc_set_disctmo(vport);
/* Send back ACC */
- lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, newnode);
+ lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
/* send RECOVERY event for ALL nodes that match RSCN payload */
lpfc_rscn_recovery_check(vport);
lpfc_set_disctmo(vport);
/* RSCN processed */
- lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
- "%d (%d):0215 RSCN processed Data: x%x x%x x%x x%x\n",
- phba->brd_no, vport->vpi,
- vport->fc_flag, 0, vport->fc_rscn_id_cnt,
- vport->port_state);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0215 RSCN processed Data: x%x x%x x%x x%x\n",
+ vport->fc_flag, 0, vport->fc_rscn_id_cnt,
+ vport->port_state);
/* To process RSCN, first compare RSCN data with NameServer */
vport->fc_ns_retry = 0;
+ vport->num_disc_nodes = 0;
+
ndlp = lpfc_findnode_did(vport, NameServer_DID);
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
/* Good ndlp, issue CT Request to NameServer */
static int
lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
- struct lpfc_nodelist *ndlp, uint8_t newnode)
+ struct lpfc_nodelist *ndlp)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
/* An FLOGI ELS command <elsCmd> was received from DID <did> in
Loop Mode */
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0113 An FLOGI ELS command x%x was "
- "received from DID x%x in Loop Mode\n",
- phba->brd_no, vport->vpi, cmd, did);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0113 An FLOGI ELS command x%x was "
+ "received from DID x%x in Loop Mode\n",
+ cmd, did);
return 1;
}
mbox->mb.un.varInitLnk.lipsr_AL_PA = 0;
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->vport = vport;
- rc = lpfc_sli_issue_mbox
- (phba, mbox, (MBX_NOWAIT | MBX_STOP_IOCB));
+ rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
lpfc_set_loopback_flag(phba);
if (rc == MBX_NOT_FINISHED) {
mempool_free(mbox, phba->mbox_mem_pool);
}
/* Send back ACC */
- lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL, newnode);
+ lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
return 0;
}
elsiocb = lpfc_prep_els_iocb(phba->pport, 0, cmdsize,
lpfc_max_els_tries, ndlp,
ndlp->nlp_DID, ELS_CMD_ACC);
+
+ /* Decrement the ndlp reference count from previous mbox command */
lpfc_nlp_put(ndlp);
+
if (!elsiocb)
return;
status |= 0x4;
rps_rsp->rsvd1 = 0;
- rps_rsp->portStatus = be16_to_cpu(status);
- rps_rsp->linkFailureCnt = be32_to_cpu(mb->un.varRdLnk.linkFailureCnt);
- rps_rsp->lossSyncCnt = be32_to_cpu(mb->un.varRdLnk.lossSyncCnt);
- rps_rsp->lossSignalCnt = be32_to_cpu(mb->un.varRdLnk.lossSignalCnt);
- rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt);
- rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord);
- rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt);
-
+ rps_rsp->portStatus = cpu_to_be16(status);
+ rps_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt);
+ rps_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt);
+ rps_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt);
+ rps_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt);
+ rps_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord);
+ rps_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt);
/* Xmit ELS RPS ACC response tag <ulpIoTag> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0118 Xmit ELS RPS ACC response tag x%x "
- "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
- "rpi x%x\n",
- phba->brd_no, ndlp->vport->vpi, elsiocb->iotag,
- elsiocb->iocb.ulpContext, ndlp->nlp_DID,
- ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
-
+ lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS,
+ "0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
+ "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
+ elsiocb->iotag, elsiocb->iocb.ulpContext,
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi);
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
phba->fc_stat.elsXmitACC++;
if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR)
mbox->context2 = lpfc_nlp_get(ndlp);
mbox->vport = vport;
mbox->mbox_cmpl = lpfc_els_rsp_rps_acc;
- if (lpfc_sli_issue_mbox (phba, mbox,
- (MBX_NOWAIT | MBX_STOP_IOCB)) != MBX_NOT_FINISHED)
+ if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
+ != MBX_NOT_FINISHED)
/* Mbox completion will send ELS Response */
return 0;
-
+ /* Decrement reference count used for the failed mbox
+ * command.
+ */
lpfc_nlp_put(ndlp);
mempool_free(mbox, phba->mbox_mem_pool);
}
rpl_rsp.port_num_blk.portID = be32_to_cpu(vport->fc_myDID);
memcpy(&rpl_rsp.port_num_blk.portName, &vport->fc_portname,
sizeof(struct lpfc_name));
-
memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t));
-
-
/* Xmit ELS RPL ACC response tag <ulpIoTag> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0120 Xmit ELS RPL ACC response tag x%x "
- "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
- "rpi x%x\n",
- phba->brd_no, vport->vpi, elsiocb->iotag,
- elsiocb->iocb.ulpContext, ndlp->nlp_DID,
- ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0120 Xmit ELS RPL ACC response tag x%x "
+ "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
+ "rpi x%x\n",
+ elsiocb->iotag, elsiocb->iocb.ulpContext,
+ ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+ ndlp->nlp_rpi);
elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
-
phba->fc_stat.elsXmitACC++;
if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
lpfc_els_free_iocb(phba, elsiocb);
lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
struct lpfc_nodelist *ndlp)
{
- struct lpfc_hba *phba = vport->phba;
struct lpfc_dmabuf *pcmd;
uint32_t *lp;
IOCB_t *icmd;
cmd = *lp++;
fp = (FARP *) lp;
-
/* FARP-REQ received from DID <did> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0601 FARP-REQ received from DID x%x\n",
- phba->brd_no, vport->vpi, did);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0601 FARP-REQ received from DID x%x\n", did);
/* We will only support match on WWPN or WWNN */
if (fp->Mflags & ~(FARP_MATCH_NODE | FARP_MATCH_PORT)) {
return 0;
uint32_t *lp;
IOCB_t *icmd;
uint32_t cmd, did;
- struct lpfc_hba *phba = vport->phba;
icmd = &cmdiocb->iocb;
did = icmd->un.elsreq64.remoteID;
cmd = *lp++;
/* FARP-RSP received from DID <did> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0600 FARP-RSP received from DID x%x\n",
- phba->brd_no, vport->vpi, did);
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0600 FARP-RSP received from DID x%x\n", did);
/* ACCEPT the Farp resp request */
- lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
+ lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
return 0;
}
struct lpfc_hba *phba = vport->phba;
/* FAN received */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0265 FAN received\n",
- phba->brd_no, vport->vpi);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0265 FAN received\n");
icmd = &cmdiocb->iocb;
did = icmd->un.elsreq64.remoteID;
pcmd = (struct lpfc_dmabuf *)cmdiocb->context2;
* other NLP_FABRIC logins
*/
lpfc_drop_node(vport, ndlp);
+
} else if (!(ndlp->nlp_flag & NLP_NPR_ADISC)) {
/* Fail outstanding I/O now since this
* device is marked for PLOGI
}
}
- vport->port_state = LPFC_FLOGI;
- lpfc_set_disctmo(vport);
lpfc_initial_flogi(vport);
return 0;
}
if (ndlp)
remote_ID = ndlp->nlp_DID;
}
-
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0127 ELS timeout Data: x%x x%x x%x "
- "x%x\n",
- phba->brd_no, vport->vpi, els_command,
- remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
-
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0127 ELS timeout Data: x%x x%x x%x "
+ "x%x\n", els_command,
+ remote_ID, cmd->ulpCommand, cmd->ulpIoTag);
lpfc_sli_issue_abort_iotag(phba, pring, piocb);
}
spin_unlock_irq(&phba->hbalock);
lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
struct lpfc_vport *vport, struct lpfc_iocbq *elsiocb)
{
+ struct Scsi_Host *shost;
struct lpfc_nodelist *ndlp;
struct ls_rjt stat;
uint32_t *payload;
goto dropit;
lpfc_nlp_init(vport, ndlp, did);
+ lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
newnode = 1;
if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
ndlp->nlp_type |= NLP_FABRIC;
}
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
+ }
+ else {
+ if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
+ /* This is simular to the new node path */
+ lpfc_nlp_get(ndlp);
+ lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+ newnode = 1;
+ }
}
phba->fc_stat.elsRcvFrame++;
cmd &= ELS_CMD_MASK;
}
/* ELS command <elsCmd> received from NPORT <did> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0112 ELS command x%x received from NPORT x%x "
- "Data: x%x\n", phba->brd_no, vport->vpi, cmd, did,
- vport->port_state);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0112 ELS command x%x received from NPORT x%x "
+ "Data: x%x\n", cmd, did, vport->port_state);
switch (cmd) {
case ELS_CMD_PLOGI:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
rjt_err = LSRJT_UNABLE_TPC;
break;
}
+
+ shost = lpfc_shost_from_vport(vport);
+ spin_lock_irq(shost->host_lock);
+ ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
+ spin_unlock_irq(shost->host_lock);
+
lpfc_disc_state_machine(vport, ndlp, elsiocb,
NLP_EVT_RCV_PLOGI);
did, vport->port_state, ndlp->nlp_flag);
phba->fc_stat.elsRcvFLOGI++;
- lpfc_els_rcv_flogi(vport, elsiocb, ndlp, newnode);
+ lpfc_els_rcv_flogi(vport, elsiocb, ndlp);
if (newnode)
- lpfc_drop_node(vport, ndlp);
+ lpfc_nlp_put(ndlp);
break;
case ELS_CMD_LOGO:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
break;
case ELS_CMD_RSCN:
phba->fc_stat.elsRcvRSCN++;
- lpfc_els_rcv_rscn(vport, elsiocb, ndlp, newnode);
+ lpfc_els_rcv_rscn(vport, elsiocb, ndlp);
if (newnode)
- lpfc_drop_node(vport, ndlp);
+ lpfc_nlp_put(ndlp);
break;
case ELS_CMD_ADISC:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
phba->fc_stat.elsRcvLIRR++;
lpfc_els_rcv_lirr(vport, elsiocb, ndlp);
if (newnode)
- lpfc_drop_node(vport, ndlp);
+ lpfc_nlp_put(ndlp);
break;
case ELS_CMD_RPS:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
phba->fc_stat.elsRcvRPS++;
lpfc_els_rcv_rps(vport, elsiocb, ndlp);
if (newnode)
- lpfc_drop_node(vport, ndlp);
+ lpfc_nlp_put(ndlp);
break;
case ELS_CMD_RPL:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
phba->fc_stat.elsRcvRPL++;
lpfc_els_rcv_rpl(vport, elsiocb, ndlp);
if (newnode)
- lpfc_drop_node(vport, ndlp);
+ lpfc_nlp_put(ndlp);
break;
case ELS_CMD_RNID:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
phba->fc_stat.elsRcvRNID++;
lpfc_els_rcv_rnid(vport, elsiocb, ndlp);
if (newnode)
- lpfc_drop_node(vport, ndlp);
+ lpfc_nlp_put(ndlp);
break;
default:
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
rjt_err = LSRJT_INVALID_CMD;
/* Unknown ELS command <elsCmd> received from NPORT <did> */
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0115 Unknown ELS command x%x "
- "received from NPORT x%x\n",
- phba->brd_no, vport->vpi, cmd, did);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0115 Unknown ELS command x%x "
+ "received from NPORT x%x\n", cmd, did);
if (newnode)
- lpfc_drop_node(vport, ndlp);
+ lpfc_nlp_put(ndlp);
break;
}
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp,
NULL);
- if (newnode)
- lpfc_drop_node(vport, ndlp);
}
return;
dropit:
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0111 Dropping received ELS cmd "
+ if (vport && !(vport->load_flag & FC_UNLOADING))
+ lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+ "(%d):0111 Dropping received ELS cmd "
"Data: x%x x%x x%x\n",
- phba->brd_no, vport ? vport->vpi : 0xffff,
- icmd->ulpStatus, icmd->un.ulpWord[4],
- icmd->ulpTimeout);
+ vport->vpi, icmd->ulpStatus,
+ icmd->un.ulpWord[4], icmd->ulpTimeout);
phba->fc_stat.elsRcvDrop++;
}
return;
}
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0251 NameServer login: no memory\n",
- phba->brd_no, vport->vpi);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0251 NameServer login: no memory\n");
return;
}
lpfc_nlp_init(vport, ndlp, NameServer_DID);
if (lpfc_issue_els_plogi(vport, ndlp->nlp_DID, 0)) {
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0252 Cannot issue NameServer login\n",
- phba->brd_no, vport->vpi);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0252 Cannot issue NameServer login\n");
return;
}
- if (phba->cfg_fdmi_on) {
+ if (vport->cfg_fdmi_on) {
ndlp_fdmi = mempool_alloc(phba->nlp_mem_pool,
GFP_KERNEL);
if (ndlp_fdmi) {
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
MAILBOX_t *mb = &pmb->mb;
+ spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
- lpfc_nlp_put(ndlp);
+ spin_unlock_irq(shost->host_lock);
if (mb->mbxStatus) {
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
- "%d (%d):0915 Register VPI failed: 0x%x\n",
- phba->brd_no, vport->vpi, mb->mbxStatus);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
+ "0915 Register VPI failed: 0x%x\n",
+ mb->mbxStatus);
switch (mb->mbxStatus) {
case 0x11: /* unsupported feature */
default:
/* Try to recover from this error */
lpfc_mbx_unreg_vpi(vport);
+ spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
lpfc_initial_fdisc(vport);
break;
}
else
lpfc_do_scr_ns_plogi(phba, vport);
}
+
+ /* Now, we decrement the ndlp reference count held for this
+ * callback function
+ */
+ lpfc_nlp_put(ndlp);
+
mempool_free(pmb, phba->mbox_mem_pool);
return;
}
-void
+static void
lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
struct lpfc_nodelist *ndlp)
{
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
LPFC_MBOXQ_t *mbox;
mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
mbox->vport = vport;
mbox->context2 = lpfc_nlp_get(ndlp);
mbox->mbox_cmpl = lpfc_cmpl_reg_new_vport;
- if (lpfc_sli_issue_mbox(phba, mbox,
- MBX_NOWAIT | MBX_STOP_IOCB)
+ if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
== MBX_NOT_FINISHED) {
+ /* mailbox command not success, decrement ndlp
+ * reference count for this command
+ */
+ lpfc_nlp_put(ndlp);
mempool_free(mbox, phba->mbox_mem_pool);
- vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
- lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
- "%d (%d):0253 Register VPI: Cannot send mbox\n",
- phba->brd_no, vport->vpi);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
+ "0253 Register VPI: Can't send mbox\n");
+ goto mbox_err_exit;
}
} else {
- lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-
- lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
- "%d (%d):0254 Register VPI: no memory\n",
- phba->brd_no, vport->vpi);
-
- vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
- lpfc_nlp_put(ndlp);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
+ "0254 Register VPI: no memory\n");
+ goto mbox_err_exit;
}
+ return;
+
+mbox_err_exit:
+ lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
+ return;
}
static void
IOCB_t *irsp = &rspiocb->iocb;
struct lpfc_iocbq *piocb;
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0123 FDISC completes. x%x/x%x prevDID: x%x\n",
- phba->brd_no, vport->vpi,
- irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID);
-
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+ "0123 FDISC completes. x%x/x%x prevDID: x%x\n",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ vport->fc_prevDID);
/* Since all FDISCs are being single threaded, we
* must reset the discovery timer for ALL vports
* waiting to send FDISC when one completes.
/* Check for retry */
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
goto out;
-
/* FDISC failed */
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0124 FDISC failed. (%d/%d)\n",
- phba->brd_no, vport->vpi,
- irsp->ulpStatus, irsp->un.ulpWord[4]);
-
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0124 FDISC failed. (%d/%d)\n",
+ irsp->ulpStatus, irsp->un.ulpWord[4]);
if (vport->fc_vport->vport_state == FC_VPORT_INITIALIZING)
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
lpfc_unreg_rpi(vport, np);
}
lpfc_mbx_unreg_vpi(vport);
+ spin_lock_irq(shost->host_lock);
vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+ spin_unlock_irq(shost->host_lock);
}
if (vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)
else
lpfc_do_scr_ns_plogi(phba, vport);
- lpfc_nlp_put(ndlp); /* Free Fabric ndlp for vports */
+ /* Unconditionaly kick off releasing fabric node for vports */
+ lpfc_nlp_put(ndlp);
}
out:
lpfc_els_free_iocb(phba, cmdiocb);
}
-int
+static int
lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
uint8_t retry)
{
ELS_CMD_FDISC);
if (!elsiocb) {
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0255 Issue FDISC: no IOCB\n",
- phba->brd_no, vport->vpi);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0255 Issue FDISC: no IOCB\n");
return 1;
}
if (rc == IOCB_ERROR) {
lpfc_els_free_iocb(phba, elsiocb);
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-
- lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
- "%d (%d):0256 Issue FDISC: Cannot send IOCB\n",
- phba->brd_no, vport->vpi);
-
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0256 Issue FDISC: Cannot send IOCB\n");
return 1;
}
lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING);
}
}
-int
+static int
lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
{
unsigned long iflags;
}
-void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
+static void lpfc_fabric_abort_vport(struct lpfc_vport *vport)
{
LIST_HEAD(completions);
struct lpfc_hba *phba = vport->phba;
}
+#if 0
void lpfc_fabric_abort_flogi(struct lpfc_hba *phba)
{
LIST_HEAD(completions);
(piocb->iocb_cmpl) (phba, piocb, piocb);
}
}
+#endif /* 0 */