/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2007 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2008 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
* 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>
#include "lpfc_logmsg.h"
#include "lpfc_crtn.h"
#include "lpfc_vport.h"
+#include "lpfc_debugfs.h"
static int lpfc_els_retry(struct lpfc_hba *, struct lpfc_iocbq *,
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;
-static int
+int
lpfc_els_chk_latt(struct lpfc_vport *vport)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
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
if (elsiocb == NULL)
return NULL;
+
icmd = &elsiocb->iocb;
/* 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 {
+ } else
prsp = NULL;
- }
/* Allocate buffer for Buffer ptr list */
pbuflist = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
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 || !NLP_CHK_NODE_ACT(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;
+ /* increment the reference count on ndlp to hold reference
+ * for the callback routine.
+ */
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_issue_reg_login:
+ /* decrement the reference count on ndlp just incremented
+ * for the failed mbox command.
+ */
lpfc_nlp_put(ndlp);
mp = (struct lpfc_dmabuf *) mbox->context1;
lpfc_mbuf_free(phba, mp->virt, mp->phys);
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);
- phba->vpi_cnt = 1;
+ 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;
}
}
*/
list_for_each_entry_safe(np, next_np,
&vport->fc_nodes, nlp_listp) {
+ if (!NLP_CHK_NODE_ACT(ndlp))
+ continue;
if ((np->nlp_state != NLP_STE_NPR_NODE) ||
!(np->nlp_flag & NLP_NPR_ADISC))
continue;
}
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 &&
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
- phba->vpi_cnt = 1;
spin_unlock_irq(shost->host_lock);
phba->fc_edtov = FF_DEF_EDTOV;
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;
}
+ /* Decrement ndlp reference count indicating that ndlp can be
+ * safely released when other references to it are done.
+ */
lpfc_nlp_put(ndlp);
ndlp = lpfc_findnode_did(vport, PT2PT_RemoteID);
ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
if (!ndlp)
goto fail;
-
lpfc_nlp_init(vport, ndlp, PT2PT_RemoteID);
+ } else if (!NLP_CHK_NODE_ACT(ndlp)) {
+ ndlp = lpfc_enable_node(vport, ndlp,
+ NLP_STE_UNUSED_NODE);
+ if(!ndlp)
+ goto fail;
}
memcpy(&ndlp->nlp_portname, &sp->portName,
sizeof(struct lpfc_name));
memcpy(&ndlp->nlp_nodename, &sp->nodeName,
sizeof(struct lpfc_name));
+ /* Set state will put ndlp onto node list if not already done */
lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
- } else {
- /* This side will wait for the PLOGI */
+ } else
+ /* This side will wait for the PLOGI, decrement ndlp reference
+ * count indicating that ndlp can be released when other
+ * references to it are done.
+ */
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;
/* 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;
}
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "FLOGI cmpl: status:x%x/x%x state:x%x",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ vport->port_state);
+
if (irsp->ulpStatus) {
/* Check for retry */
if (lpfc_els_retry(phba, cmdiocb, rspiocb))
/* FLOGI failed, so there is no fabric */
spin_lock_irq(shost->host_lock);
vport->fc_flag &= ~(FC_FABRIC | FC_PUBLIC_LOOP);
- phba->vpi_cnt = 1;
spin_unlock_irq(shost->host_lock);
/* If private loop, then allow max outstanding els to be
* 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) {
/*
flogifail:
lpfc_nlp_put(ndlp);
- phba->vpi_cnt = 1;
- if (irsp->ulpStatus != IOSTAT_LOCAL_REJECT ||
- (irsp->un.ulpWord[4] != IOERR_SLI_ABORTED &&
- irsp->un.ulpWord[4] != IOERR_SLI_DOWN)) {
+ if (!lpfc_error_lost_link(irsp)) {
/* FLOGI failed, so just use loop map to make discovery list */
lpfc_disc_list_loopmap(vport);
/* 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);
}
icmd->ulpCt_l = 0;
}
+ if (phba->fc_topology != TOPOLOGY_LOOP) {
+ icmd->un.elsreq64.myID = 0;
+ icmd->un.elsreq64.fl = 1;
+ }
+
tmo = phba->fc_ratov;
phba->fc_ratov = LPFC_DISC_FLOGI_TMO;
lpfc_set_disctmo(vport);
phba->fc_stat.elsXmitFLOGI++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_flogi;
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue FLOGI: opt:x%x",
+ phba->sli3_options, 0, 0);
+
rc = lpfc_issue_fabric_iocb(phba, elsiocb);
if (rc == IOCB_ERROR) {
lpfc_els_free_iocb(phba, elsiocb);
/* 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) {
if (!ndlp)
return 0;
lpfc_nlp_init(vport, ndlp, Fabric_DID);
- } else {
- lpfc_dequeue_node(vport, ndlp);
+ /* Put ndlp onto node list */
+ lpfc_enqueue_node(vport, ndlp);
+ } else if (!NLP_CHK_NODE_ACT(ndlp)) {
+ /* re-setup ndlp without removing from node list */
+ ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
+ if (!ndlp)
+ return 0;
}
- if (lpfc_issue_els_flogi(vport, ndlp, 0)) {
+
+ 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;
}
if (!ndlp)
return 0;
lpfc_nlp_init(vport, ndlp, Fabric_DID);
- } else {
- lpfc_dequeue_node(vport, ndlp);
+ /* Put ndlp onto node list */
+ lpfc_enqueue_node(vport, ndlp);
+ } else if (!NLP_CHK_NODE_ACT(ndlp)) {
+ /* re-setup ndlp without removing from node list */
+ ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
+ if (!ndlp)
+ return 0;
}
+
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;
*/
new_ndlp = lpfc_findnode_wwpn(vport, &sp->portName);
- if (new_ndlp == ndlp)
+ if (new_ndlp == ndlp && NLP_CHK_NODE_ACT(new_ndlp))
return ndlp;
if (!new_ndlp) {
new_ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_ATOMIC);
if (!new_ndlp)
return ndlp;
-
lpfc_nlp_init(vport, new_ndlp, ndlp->nlp_DID);
+ } else if (!NLP_CHK_NODE_ACT(new_ndlp)) {
+ new_ndlp = lpfc_enable_node(vport, new_ndlp,
+ NLP_STE_UNUSED_NODE);
+ if (!new_ndlp)
+ return ndlp;
}
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;
+
+ /* Set state will put new_ndlp on to node list if not already done */
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)
cmdiocb->context_un.rsp_iocb = rspiocb;
irsp = &rspiocb->iocb;
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "PLOGI cmpl: status:x%x/x%x did:x%x",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ irsp->un.elsreq64.remoteID);
+
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);
+ if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
+ 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 ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
- ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
- (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
- (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
+ if (lpfc_error_lost_link(irsp))
rc = NLP_STE_FREED_NODE;
- } else {
+ else
rc = lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_PLOGI);
- }
} else {
/* Good status, call state machine */
prsp = list_entry(((struct lpfc_dmabuf *)
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 && !NLP_CHK_NODE_ACT(ndlp))
+ ndlp = NULL;
+
+ /* If ndlp is 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;
if (sp->cmn.fcphHigh < FC_PH3)
sp->cmn.fcphHigh = FC_PH3;
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue PLOGI: did:x%x",
+ did, 0, 0);
+
phba->fc_stat.elsXmitPLOGI++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_plogi;
ret = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
ndlp->nlp_flag &= ~NLP_PRLI_SND;
spin_unlock_irq(shost->host_lock);
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "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 */
}
/* PRLI failed */
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
- if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
- ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
- (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
- (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
+ if (lpfc_error_lost_link(irsp))
goto out;
- } else {
+ else
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_PRLI);
- }
- } else {
+ } else
/* Good status, call state machine */
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_PRLI);
- }
-
out:
lpfc_els_free_iocb(phba, cmdiocb);
return;
npr->prliType = PRLI_FCP_TYPE;
npr->initiatorFunc = 1;
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue PRLI: did:x%x",
+ ndlp->nlp_DID, 0, 0);
+
phba->fc_stat.elsXmitPRLI++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_prli;
spin_lock_irq(shost->host_lock);
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 */
/* go thru NPR nodes and issue ELS PLOGIs */
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
irsp = &(rspiocb->iocb);
ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "ADISC cmpl: status:x%x/x%x did:x%x",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ ndlp->nlp_DID);
+
/* Since ndlp can be freed in the disc state machine, note if this node
* is being used during discovery.
*/
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);
}
/* ADISC failed */
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
- if ((irsp->ulpStatus != IOSTAT_LOCAL_REJECT) ||
- ((irsp->un.ulpWord[4] != IOERR_SLI_ABORTED) &&
- (irsp->un.ulpWord[4] != IOERR_LINK_DOWN) &&
- (irsp->un.ulpWord[4] != IOERR_SLI_DOWN))) {
+ if (!lpfc_error_lost_link(irsp))
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
- NLP_EVT_CMPL_ADISC);
- }
- } else {
+ NLP_EVT_CMPL_ADISC);
+ } else
/* Good status, call state machine */
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_ADISC);
- }
if (disc && vport->num_disc_nodes) {
/* Check to see if there are more ADISCs to be sent */
memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
ap->DID = be32_to_cpu(vport->fc_myDID);
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue ADISC: did:x%x",
+ ndlp->nlp_DID, 0, 0);
+
phba->fc_stat.elsXmitADISC++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_adisc;
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_LOGO_SND;
spin_unlock_irq(shost->host_lock);
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "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;
goto out;
/* LOGO failed */
/* Do not call DSM for lpfc_els_abort'ed ELS cmds */
- if ((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
- ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
- (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
- (irsp->un.ulpWord[4] == IOERR_SLI_DOWN))) {
+ if (lpfc_error_lost_link(irsp))
goto out;
- } else {
+ else
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_LOGO);
- }
- } else {
+ } else
/* Good status, call state machine.
* This will unregister the rpi if needed.
*/
lpfc_disc_state_machine(vport, ndlp, cmdiocb,
NLP_EVT_CMPL_LOGO);
- }
-
out:
lpfc_els_free_iocb(phba, cmdiocb);
return;
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);
pcmd += sizeof(uint32_t);
memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue LOGO: did:x%x",
+ ndlp->nlp_DID, 0, 0);
+
phba->fc_stat.elsXmitLOGO++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_logo;
spin_lock_irq(shost->host_lock);
irsp = &rspiocb->iocb;
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "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);
psli = &phba->sli;
pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
cmdsize = (sizeof(uint32_t) + sizeof(SCR));
- ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
- if (!ndlp)
- return 1;
- lpfc_nlp_init(vport, ndlp, nportid);
+ ndlp = lpfc_findnode_did(vport, nportid);
+ if (!ndlp) {
+ ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+ if (!ndlp)
+ return 1;
+ lpfc_nlp_init(vport, ndlp, nportid);
+ lpfc_enqueue_node(vport, ndlp);
+ } else if (!NLP_CHK_NODE_ACT(ndlp)) {
+ ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
+ if (!ndlp)
+ return 1;
+ }
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp,
ndlp->nlp_DID, ELS_CMD_SCR);
if (!elsiocb) {
+ /* This will trigger the release of the node just
+ * allocated
+ */
lpfc_nlp_put(ndlp);
return 1;
}
memset(pcmd, 0, sizeof(SCR));
((SCR *) pcmd)->Function = SCR_FUNC_FULL;
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue SCR: did:x%x",
+ ndlp->nlp_DID, 0, 0);
+
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;
}
psli = &phba->sli;
pring = &psli->ring[LPFC_ELS_RING]; /* ELS ring */
cmdsize = (sizeof(uint32_t) + sizeof(FARP));
- ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
- if (!ndlp)
- return 1;
- lpfc_nlp_init(vport, ndlp, nportid);
+ ndlp = lpfc_findnode_did(vport, nportid);
+ if (!ndlp) {
+ ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+ if (!ndlp)
+ return 1;
+ lpfc_nlp_init(vport, ndlp, nportid);
+ lpfc_enqueue_node(vport, ndlp);
+ } else if (!NLP_CHK_NODE_ACT(ndlp)) {
+ ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
+ if (!ndlp)
+ return 1;
+ }
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;
}
memcpy(&fp->RportName, &vport->fc_portname, sizeof(struct lpfc_name));
memcpy(&fp->RnodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
ondlp = lpfc_findnode_did(vport, nportid);
- if (ondlp) {
+ if (ondlp && NLP_CHK_NODE_ACT(ondlp)) {
memcpy(&fp->OportName, &ondlp->nlp_portname,
sizeof(struct lpfc_name));
memcpy(&fp->OnodeName, &ondlp->nlp_nodename,
sizeof(struct lpfc_name));
}
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue FARPR: did:x%x",
+ ndlp->nlp_DID, 0, 0);
+
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)
{
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+ struct lpfc_work_evt *evtp;
spin_lock_irq(shost->host_lock);
nlp->nlp_flag &= ~NLP_DELAY_TMO;
del_timer_sync(&nlp->nlp_delayfunc);
nlp->nlp_last_elscmd = 0;
- if (!list_empty(&nlp->els_retry_evt.evt_listp))
+ if (!list_empty(&nlp->els_retry_evt.evt_listp)) {
list_del_init(&nlp->els_retry_evt.evt_listp);
+ /* Decrement nlp reference count held for the delayed retry */
+ evtp = &nlp->els_retry_evt;
+ lpfc_nlp_put((struct lpfc_nodelist *)evtp->evt_arg1);
+ }
if (nlp->nlp_flag & NLP_NPR_2B_DISC) {
spin_lock_irq(shost->host_lock);
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;
cmd = *elscmd++;
}
- if (ndlp)
+ if (ndlp && NLP_CHK_NODE_ACT(ndlp))
did = ndlp->nlp_DID;
else {
/* We should only hit this case for retrying PLOGI */
did = irsp->un.elsreq64.remoteID;
ndlp = lpfc_findnode_did(vport, did);
- if (!ndlp && (cmd != ELS_CMD_PLOGI))
+ if ((!ndlp || !NLP_CHK_NODE_ACT(ndlp))
+ && (cmd != ELS_CMD_PLOGI))
return 1;
}
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Retry ELS: wd7:x%x wd4:x%x did:x%x",
+ *(((uint32_t *) irsp) + 7), irsp->un.ulpWord[4], ndlp->nlp_DID);
+
switch (irsp->ulpStatus) {
case IOSTAT_FCP_RSP_ERROR:
case IOSTAT_REMOTE_STOP:
retry = 1;
break;
- case IOERR_SEQUENCE_TIMEOUT:
+ case IOERR_ILLEGAL_COMMAND:
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0124 Retry illegal cmd x%x "
+ "retry:x%x delay:x%x\n",
+ cmd, cmdiocb->retry, delay);
retry = 1;
+ /* All command's retry policy */
+ maxretry = 8;
+ if (cmdiocb->retry > 2)
+ delay = 1000;
break;
- 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_mbx_unreg_vpi(vport);
- retry = 1;
- /* Always retry for this case */
- cmdiocb->retry = 0;
- }
+ case IOERR_NO_RESOURCES:
+ logerr = 1; /* HBA out of resources */
+ retry = 1;
+ if (cmdiocb->retry > 100)
+ delay = 100;
+ maxretry = 250;
break;
- case IOERR_NO_RESOURCES:
+ case IOERR_ILLEGAL_FRAME:
delay = 100;
retry = 1;
break;
+ case IOERR_SEQUENCE_TIMEOUT:
case IOERR_INVALID_RPI:
retry = 1;
break;
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);
}
break;
case LSRJT_LOGICAL_BSY:
- if (cmd == ELS_CMD_PLOGI) {
+ if ((cmd == ELS_CMD_PLOGI) ||
+ (cmd == ELS_CMD_PRLI)) {
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;
case LSRJT_LOGICAL_ERR:
+ /* There are some cases where switches return this
+ * error when they are not ready and should be returning
+ * Logical Busy. We should delay every time.
+ */
+ if (cmd == ELS_CMD_FDISC &&
+ stat.un.b.lsRjtRsnCodeExp == LSEXP_PORT_LOGIN_REQ) {
+ maxretry = 3;
+ delay = 1000;
+ retry = 1;
+ break;
+ }
case LSRJT_PROTOCOL_ERR:
if ((phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) &&
(cmd == ELS_CMD_FDISC) &&
((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) &&
+ !lpfc_error_lost_link(irsp)) {
+ /* 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) ||
+ ((irsp->un.ulpWord[4] & 0xff) != IOERR_NO_RESOURCES))) {
+ /* Don't reset timer for no resources */
- if ((cmd == ELS_CMD_PLOGI) || (cmd == ELS_CMD_ADISC)) {
/* If discovery / RSCN timer is running, reset it */
if (timer_pending(&vport->fc_disctmo) ||
(vport->fc_flag & FC_RSCN_MODE))
spin_unlock_irq(shost->host_lock);
ndlp->nlp_prev_state = ndlp->nlp_state;
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+ if (cmd == ELS_CMD_PRLI)
+ lpfc_nlp_set_state(vport, ndlp,
+ NLP_STE_REG_LOGIN_ISSUE);
+ else
+ lpfc_nlp_set_state(vport, ndlp,
+ NLP_STE_NPR_NODE);
ndlp->nlp_last_elscmd = cmd;
return 1;
return 1;
}
}
-
/* No retry ELS command <elsCmd> to remote NPORT <did> */
- lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
- "%d (%d):0108 No retry ELS command x%x to remote "
- "NPORT x%x Data: x%x\n",
- phba->brd_no, vport->vpi,
- cmd, did, cmdiocb->retry);
+ 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;
{
struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) cmdiocb->context1;
struct lpfc_vport *vport = cmdiocb->vport;
+ IOCB_t *irsp;
+ irsp = &rspiocb->iocb;
+ 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;
}
+void
+lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
+{
+ struct lpfc_dmabuf *mp = (struct lpfc_dmabuf *) (pmb->context1);
+ struct lpfc_nodelist *ndlp = (struct lpfc_nodelist *) pmb->context2;
+
+ pmb->context1 = NULL;
+ lpfc_mbuf_free(phba, mp->virt, mp->phys);
+ kfree(mp);
+ mempool_free(pmb, phba->mbox_mem_pool);
+ 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;
+}
+
static void
-lpfc_cmpl_els_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
+lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
struct lpfc_iocbq *rspiocb)
{
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,
+ "ELS rsp cmpl: status:x%x/x%x did:x%x",
+ irsp->ulpStatus, irsp->un.ulpWord[4],
+ 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_unreg_rpi(vport, ndlp);
- mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
+ /* Increment reference count to ndlp to hold the
+ * reference to ndlp for the callback function.
+ */
mbox->context2 = lpfc_nlp_get(ndlp);
mbox->vport = vport;
- ndlp->nlp_prev_state = ndlp->nlp_state;
- lpfc_nlp_set_state(vport, ndlp,
+ if (ndlp->nlp_flag & NLP_RM_DFLT_RPI) {
+ mbox->mbox_flag |= LPFC_MBX_IMED_UNREG;
+ mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
+ }
+ else {
+ mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
+ ndlp->nlp_prev_state = ndlp->nlp_state;
+ lpfc_nlp_set_state(vport, ndlp,
NLP_STE_REG_LOGIN_ISSUE);
- 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)
goto out;
+ else
+ /* Decrement the ndlp reference count we
+ * set for this failed mailbox command.
+ */
+ lpfc_nlp_put(ndlp);
+
+ /* 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;
}
- lpfc_nlp_put(ndlp);
- /* NOTE: we should have messages for unsuccessful
- reglogin */
} else {
- /* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */
- if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
- ((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
- (irsp->un.ulpWord[4] == IOERR_LINK_DOWN) ||
- (irsp->un.ulpWord[4] == IOERR_SLI_DOWN)))) {
- if (ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
- lpfc_drop_node(vport, ndlp);
+ /* Do not drop node for lpfc_els_abort'ed ELS cmds */
+ if (!lpfc_error_lost_link(irsp) &&
+ ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
+ 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;
}
}
}
out:
if (ndlp) {
spin_lock_irq(shost->host_lock);
- ndlp->nlp_flag &= ~NLP_ACC_REGLOGIN;
+ 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;
pcmd = (((struct lpfc_dmabuf *) elsiocb->context2)->virt);
*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
pcmd += sizeof(uint32_t);
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+ "Issue ACC: did:x%x flg:x%x",
+ ndlp->nlp_DID, ndlp->nlp_flag, 0);
break;
case ELS_CMD_PLOGI:
cmdsize = (sizeof(struct serv_parm) + sizeof(uint32_t));
*((uint32_t *) (pcmd)) = ELS_CMD_ACC;
pcmd += sizeof(uint32_t);
memcpy(pcmd, &vport->fc_sparam, sizeof(struct serv_parm));
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+ "Issue ACC PLOGI: did:x%x flg:x%x",
+ ndlp->nlp_DID, ndlp->nlp_flag, 0);
break;
case ELS_CMD_PRLO:
cmdsize = sizeof(uint32_t) + sizeof(PRLO);
*((uint32_t *) (pcmd)) = ELS_CMD_PRLO_ACC;
els_pkt_ptr = (ELS_PKT *) pcmd;
els_pkt_ptr->un.prlo.acceptRspCode = PRLO_REQ_EXECUTED;
+
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+ "Issue ACC PRLO: did:x%x flg:x%x",
+ ndlp->nlp_DID, ndlp->nlp_flag, 0);
break;
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;
spin_unlock_irq(shost->host_lock);
elsiocb->iocb_cmpl = lpfc_cmpl_els_logo_acc;
} else {
- elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
}
phba->fc_stat.elsXmitACC++;
int
lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
- struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp)
+ struct lpfc_iocbq *oldiocb, struct lpfc_nodelist *ndlp,
+ LPFC_MBOXQ_t *mbox)
{
struct lpfc_hba *phba = vport->phba;
IOCB_t *icmd;
pcmd += sizeof(uint32_t);
*((uint32_t *) (pcmd)) = rejectError;
+ if (mbox)
+ elsiocb->context_un.mbox = mbox;
+
/* 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_acc;
+ 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;
memcpy(&ap->nodeName, &vport->fc_nodename, sizeof(struct lpfc_name));
ap->DID = be32_to_cpu(vport->fc_myDID);
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+ "Issue ACC ADISC: did:x%x flg:x%x",
+ ndlp->nlp_DID, ndlp->nlp_flag, 0);
+
phba->fc_stat.elsXmitACC++;
- elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+ 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);
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));
npr->prliType = PRLI_FCP_TYPE;
npr->initiatorFunc = 1;
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+ "Issue ACC PRLI: did:x%x flg:x%x",
+ ndlp->nlp_DID, ndlp->nlp_flag, 0);
+
phba->fc_stat.elsXmitACC++;
- elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
if (rc == IOCB_ERROR) {
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);
break;
}
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
+ "Issue ACC RNID: did:x%x flg:x%x",
+ ndlp->nlp_DID, ndlp->nlp_flag, 0);
+
phba->fc_stat.elsXmitACC++;
- elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+ elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
lpfc_nlp_put(ndlp);
elsiocb->context1 = NULL; /* Don't need ndlp for cmpl,
* it could be freed */
/* go thru NPR nodes and issue any remaining ELS ADISCs */
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+ if (!NLP_CHK_NODE_ACT(ndlp))
+ continue;
if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
(ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
(ndlp->nlp_flag & NLP_NPR_ADISC) != 0) {
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);
/* go thru NPR nodes and issue any remaining ELS PLOGIs */
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes, nlp_listp) {
+ if (!NLP_CHK_NODE_ACT(ndlp))
+ continue;
if (ndlp->nlp_state == NLP_STE_NPR_NODE &&
(ndlp->nlp_flag & NLP_NPR_2B_DISC) != 0 &&
(ndlp->nlp_flag & NLP_DELAY_TMO) == 0 &&
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);
struct lpfc_hba *phba = vport->phba;
int i;
+ spin_lock_irq(shost->host_lock);
+ if (vport->fc_rscn_flush) {
+ /* Another thread is walking fc_rscn_id_list on this vport */
+ spin_unlock_irq(shost->host_lock);
+ return;
+ }
+ /* Indicate we are walking lpfc_els_flush_rscn on this vport */
+ vport->fc_rscn_flush = 1;
+ spin_unlock_irq(shost->host_lock);
+
for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
lpfc_in_buf_free(phba, vport->fc_rscn_id_list[i]);
vport->fc_rscn_id_list[i] = NULL;
vport->fc_flag &= ~(FC_RSCN_MODE | FC_RSCN_DISCOVERY);
spin_unlock_irq(shost->host_lock);
lpfc_can_disctmo(vport);
+ /* Indicate we are done walking this fc_rscn_id_list */
+ vport->fc_rscn_flush = 0;
}
int
D_ID rscn_did;
uint32_t *lp;
uint32_t payload_len, i;
- struct lpfc_hba *phba = vport->phba;
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
ns_did.un.word = did;
if (vport->fc_flag & FC_RSCN_DISCOVERY)
return did;
+ spin_lock_irq(shost->host_lock);
+ if (vport->fc_rscn_flush) {
+ /* Another thread is walking fc_rscn_id_list on this vport */
+ spin_unlock_irq(shost->host_lock);
+ return 0;
+ }
+ /* Indicate we are walking fc_rscn_id_list on this vport */
+ vport->fc_rscn_flush = 1;
+ spin_unlock_irq(shost->host_lock);
for (i = 0; i < vport->fc_rscn_id_cnt; i++) {
lp = vport->fc_rscn_id_list[i]->virt;
payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
switch (rscn_did.un.b.resv) {
case 0: /* Single N_Port ID effected */
if (ns_did.un.word == rscn_did.un.word)
- return did;
+ goto return_did_out;
break;
case 1: /* Whole N_Port Area effected */
if ((ns_did.un.b.domain == rscn_did.un.b.domain)
&& (ns_did.un.b.area == rscn_did.un.b.area))
- return did;
+ goto return_did_out;
break;
case 2: /* Whole N_Port Domain effected */
if (ns_did.un.b.domain == rscn_did.un.b.domain)
- return did;
+ goto return_did_out;
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;
+ goto return_did_out;
}
}
}
+ /* Indicate we are done with walking fc_rscn_id_list on this vport */
+ vport->fc_rscn_flush = 0;
return 0;
+return_did_out:
+ /* Indicate we are done with walking fc_rscn_id_list on this vport */
+ vport->fc_rscn_flush = 0;
+ return did;
}
static int
*/
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
- if (ndlp->nlp_state == NLP_STE_UNUSED_NODE ||
+ if (!NLP_CHK_NODE_ACT(ndlp) ||
+ ndlp->nlp_state == NLP_STE_UNUSED_NODE ||
lpfc_rscn_payload_check(vport, ndlp->nlp_DID) == 0)
continue;
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;
struct lpfc_dmabuf *pcmd;
- struct lpfc_vport *next_vport;
uint32_t *lp, *datap;
IOCB_t *icmd;
uint32_t payload_len, length, nportid, *cmd;
- int rscn_cnt = vport->fc_rscn_id_cnt;
+ int rscn_cnt;
int rscn_id = 0, hba_id = 0;
int i;
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,
+ vport->fc_rscn_id_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]);
* Discovery processing will satisfy it.
*/
if (vport->port_state <= LPFC_NS_QRY) {
- lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
- newnode);
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "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);
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) {
nportid = ((be32_to_cpu(nportid)) & Mask_DID);
i -= sizeof(uint32_t);
rscn_id++;
- list_for_each_entry(next_vport, &phba->port_list,
- listentry) {
- if (nportid == next_vport->fc_myDID) {
- hba_id++;
- break;
- }
- }
+ if (lpfc_find_vport_by_did(phba, nportid))
+ hba_id++;
}
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, vport->fc_rscn_id_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;
}
}
+ spin_lock_irq(shost->host_lock);
+ if (vport->fc_rscn_flush) {
+ /* Another thread is walking fc_rscn_id_list on this vport */
+ spin_unlock_irq(shost->host_lock);
+ vport->fc_flag |= FC_RSCN_DISCOVERY;
+ return 0;
+ }
+ /* Indicate we are walking fc_rscn_id_list on this vport */
+ vport->fc_rscn_flush = 1;
+ spin_unlock_irq(shost->host_lock);
+ /* Get the array count after sucessfully have the token */
+ rscn_cnt = vport->fc_rscn_id_cnt;
/* If we are already processing an RSCN, save the received
* RSCN payload buffer, cmdiocb->context2 to process later.
*/
if (vport->fc_flag & (FC_RSCN_MODE | FC_NDISC_ACTIVE)) {
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "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) {
if ((rscn_cnt) &&
(payload_len + length <= LPFC_BPL_SIZE)) {
*cmd &= ELS_CMD_MASK;
- *cmd |= be32_to_cpu(payload_len + length);
+ *cmd |= cpu_to_be32(payload_len + length);
memcpy(((uint8_t *)cmd) + length, lp,
payload_len);
} else {
*/
cmdiocb->context2 = NULL;
}
-
/* 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);
}
+ /* Indicate we are done walking fc_rscn_id_list on this vport */
+ vport->fc_rscn_flush = 0;
/* 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_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "RCV RSCN: 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_MODE;
spin_unlock_irq(shost->host_lock);
vport->fc_rscn_id_list[vport->fc_rscn_id_cnt++] = pcmd;
+ /* Indicate we are done walking fc_rscn_id_list on this vport */
+ vport->fc_rscn_flush = 0;
/*
* If we zero, cmdiocb->context2, the calling routine will
* not try to free it.
*/
cmdiocb->context2 = NULL;
-
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);
-
return lpfc_els_handle_rscn(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) {
+ if (ndlp && NLP_CHK_NODE_ACT(ndlp)
+ && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
/* Good ndlp, issue CT Request to NameServer */
if (lpfc_ns_cmd(vport, SLI_CTNS_GID_FT, 0, 0) == 0)
/* Wait for NameServer query cmpl before we can
/* If login to NameServer does not exist, issue one */
/* Good status, issue PLOGI to NameServer */
ndlp = lpfc_findnode_did(vport, NameServer_DID);
- if (ndlp)
+ if (ndlp && NLP_CHK_NODE_ACT(ndlp))
/* Wait for NameServer login cmpl before we can
continue */
return 1;
- ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
- if (!ndlp) {
- lpfc_els_flush_rscn(vport);
- return 0;
+ if (ndlp) {
+ ndlp = lpfc_enable_node(vport, ndlp,
+ NLP_STE_PLOGI_ISSUE);
+ if (!ndlp) {
+ lpfc_els_flush_rscn(vport);
+ return 0;
+ }
+ ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
} else {
+ ndlp = mempool_alloc(phba->nlp_mem_pool, GFP_KERNEL);
+ if (!ndlp) {
+ lpfc_els_flush_rscn(vport);
+ return 0;
+ }
lpfc_nlp_init(vport, ndlp, NameServer_DID);
- ndlp->nlp_type |= NLP_FABRIC;
ndlp->nlp_prev_state = ndlp->nlp_state;
lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
- lpfc_issue_els_plogi(vport, NameServer_DID, 0);
- /* Wait for NameServer login cmpl before we can
- continue */
- return 1;
}
+ ndlp->nlp_type |= NLP_FABRIC;
+ lpfc_issue_els_plogi(vport, NameServer_DID, 0);
+ /* Wait for NameServer login cmpl before we can
+ * continue
+ */
+ return 1;
}
lpfc_els_flush_rscn(vport);
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);
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_SPARM_OPTIONS;
stat.un.b.vendorUnique = 0;
- lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
+ lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+ NULL);
return 1;
}
/* 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;
}
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
stat.un.b.vendorUnique = 0;
- lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
+ lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+ NULL);
}
return 0;
}
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
stat.un.b.vendorUnique = 0;
- lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
+ lpfc_els_rsp_reject(vport, stat.un.lsRjtError, 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);
-
- elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
+ 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)
lpfc_els_free_iocb(phba, elsiocb);
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
stat.un.b.vendorUnique = 0;
- lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
+ lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+ NULL);
}
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
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);
}
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
stat.un.b.vendorUnique = 0;
- lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
+ lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp, NULL);
return 0;
}
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);
-
- elsiocb->iocb_cmpl = lpfc_cmpl_els_acc;
-
+ 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);
stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
stat.un.b.lsRjtRsnCodeExp = LSEXP_CANT_GIVE_DATA;
stat.un.b.vendorUnique = 0;
- lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp);
+ lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+ NULL);
}
pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
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;
list_for_each_entry_safe(ndlp, next_ndlp,
&vport->fc_nodes, nlp_listp) {
+ if (!NLP_CHK_NODE_ACT(ndlp))
+ continue;
if (ndlp->nlp_state != NLP_STE_NPR_NODE)
continue;
if (ndlp->nlp_type & NLP_FABRIC) {
* 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;
}
*/
list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
nlp_listp) {
+ if (!NLP_CHK_NODE_ACT(ndlp))
+ continue;
if (ndlp->nlp_state != NLP_STE_NPR_NODE)
continue;
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);
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
struct lpfc_iocbq *tmp_iocb, *piocb;
IOCB_t *cmd = NULL;
- struct lpfc_dmabuf *pcmd;
- uint32_t *elscmd;
- uint32_t els_command;
lpfc_fabric_abort_vport(vport);
cmd->ulpCommand == CMD_ABORT_XRI_CN)
continue;
- pcmd = (struct lpfc_dmabuf *) piocb->context2;
- elscmd = (uint32_t *) (pcmd->virt);
- els_command = *elscmd;
-
if (piocb->vport != vport)
continue;
return;
}
+void
+lpfc_els_flush_all_cmd(struct lpfc_hba *phba)
+{
+ LIST_HEAD(completions);
+ struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
+ struct lpfc_iocbq *tmp_iocb, *piocb;
+ IOCB_t *cmd = NULL;
+
+ lpfc_fabric_abort_hba(phba);
+ spin_lock_irq(&phba->hbalock);
+ list_for_each_entry_safe(piocb, tmp_iocb, &pring->txq, list) {
+ cmd = &piocb->iocb;
+ if (piocb->iocb_flag & LPFC_IO_LIBDFC)
+ continue;
+ /* Do not flush out the QUE_RING and ABORT/CLOSE iocbs */
+ if (cmd->ulpCommand == CMD_QUE_RING_BUF_CN ||
+ cmd->ulpCommand == CMD_QUE_RING_BUF64_CN ||
+ cmd->ulpCommand == CMD_CLOSE_XRI_CN ||
+ cmd->ulpCommand == CMD_ABORT_XRI_CN)
+ continue;
+ list_move_tail(&piocb->list, &completions);
+ pring->txq_cnt--;
+ }
+ list_for_each_entry_safe(piocb, tmp_iocb, &pring->txcmplq, list) {
+ if (piocb->iocb_flag & LPFC_IO_LIBDFC)
+ continue;
+ lpfc_sli_issue_abort_iotag(phba, pring, piocb);
+ }
+ spin_unlock_irq(&phba->hbalock);
+ while (!list_empty(&completions)) {
+ piocb = list_get_first(&completions, struct lpfc_iocbq, list);
+ cmd = &piocb->iocb;
+ list_del_init(&piocb->list);
+ if (!piocb->iocb_cmpl)
+ lpfc_sli_release_iocbq(phba, piocb);
+ else {
+ cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+ cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+ (piocb->iocb_cmpl) (phba, piocb, piocb);
+ }
+ }
+ return;
+}
+
static void
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;
uint32_t cmd, did, newnode, rjt_err = 0;
IOCB_t *icmd = &elsiocb->iocb;
- if (vport == NULL || elsiocb->context2 == NULL)
+ if (!vport || !(elsiocb->context2))
goto dropit;
newnode = 0;
if ((phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) == 0)
lpfc_post_buffer(phba, pring, 1, 1);
- if (icmd->ulpStatus)
+ did = icmd->un.rcvels.remoteID;
+ if (icmd->ulpStatus) {
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "RCV Unsol ELS: status:x%x/x%x did:x%x",
+ icmd->ulpStatus, icmd->un.ulpWord[4], did);
goto dropit;
+ }
/* Check to see if link went down during discovery */
if (lpfc_els_chk_latt(vport))
if (vport->load_flag & FC_UNLOADING)
goto dropit;
- did = icmd->un.rcvels.remoteID;
ndlp = lpfc_findnode_did(vport, did);
if (!ndlp) {
/* Cannot find existing Fabric ndlp, so allocate a new one */
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) {
+ if ((did & Fabric_DID_MASK) == Fabric_DID_MASK)
ndlp->nlp_type |= NLP_FABRIC;
+ } else {
+ if (!NLP_CHK_NODE_ACT(ndlp)) {
+ ndlp = lpfc_enable_node(vport, ndlp,
+ NLP_STE_UNUSED_NODE);
+ if (!ndlp)
+ goto dropit;
+ }
+ if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
+ /* This is simular to the new node path */
+ ndlp = lpfc_nlp_get(ndlp);
+ if (!ndlp)
+ goto dropit;
+ lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+ newnode = 1;
}
- lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
}
phba->fc_stat.elsRcvFrame++;
if (elsiocb->context1)
lpfc_nlp_put(elsiocb->context1);
+
elsiocb->context1 = lpfc_nlp_get(ndlp);
elsiocb->vport = vport;
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,
+ "RCV PLOGI: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
phba->fc_stat.elsRcvPLOGI++;
- if ((vport->port_state < LPFC_DISC_AUTH) ||
- ((vport->port_type == LPFC_NPIV_PORT &&
- phba->cfg_vport_restrict_login))) {
- rjt_err = 2;
- break;
- }
ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
+
+ if (vport->port_state < LPFC_DISC_AUTH) {
+ if (!(phba->pport->fc_flag & FC_PT2PT) ||
+ (phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
+ rjt_err = LSRJT_UNABLE_TPC;
+ break;
+ }
+ /* We get here, and drop thru, if we are PT2PT with
+ * another NPort and the other side has initiated
+ * the PLOGI before responding to our FLOGI.
+ */
+ }
+
+ 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);
+
break;
case ELS_CMD_FLOGI:
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "RCV FLOGI: did:x%x/ste:x%x flg:x%x",
+ 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,
+ "RCV LOGO: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
phba->fc_stat.elsRcvLOGO++;
if (vport->port_state < LPFC_DISC_AUTH) {
- rjt_err = 1;
+ rjt_err = LSRJT_UNABLE_TPC;
break;
}
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_LOGO);
break;
case ELS_CMD_PRLO:
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "RCV PRLO: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
phba->fc_stat.elsRcvPRLO++;
if (vport->port_state < LPFC_DISC_AUTH) {
- rjt_err = 1;
+ rjt_err = LSRJT_UNABLE_TPC;
break;
}
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLO);
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,
+ "RCV ADISC: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
phba->fc_stat.elsRcvADISC++;
if (vport->port_state < LPFC_DISC_AUTH) {
- rjt_err = 1;
+ rjt_err = LSRJT_UNABLE_TPC;
break;
}
lpfc_disc_state_machine(vport, ndlp, elsiocb,
NLP_EVT_RCV_ADISC);
break;
case ELS_CMD_PDISC:
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "RCV PDISC: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
phba->fc_stat.elsRcvPDISC++;
if (vport->port_state < LPFC_DISC_AUTH) {
- rjt_err = 1;
+ rjt_err = LSRJT_UNABLE_TPC;
break;
}
lpfc_disc_state_machine(vport, ndlp, elsiocb,
NLP_EVT_RCV_PDISC);
break;
case ELS_CMD_FARPR:
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "RCV FARPR: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
phba->fc_stat.elsRcvFARPR++;
lpfc_els_rcv_farpr(vport, elsiocb, ndlp);
break;
case ELS_CMD_FARP:
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "RCV FARP: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
phba->fc_stat.elsRcvFARP++;
lpfc_els_rcv_farp(vport, elsiocb, ndlp);
break;
case ELS_CMD_FAN:
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "RCV FAN: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
phba->fc_stat.elsRcvFAN++;
lpfc_els_rcv_fan(vport, elsiocb, ndlp);
break;
case ELS_CMD_PRLI:
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "RCV PRLI: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
phba->fc_stat.elsRcvPRLI++;
if (vport->port_state < LPFC_DISC_AUTH) {
- rjt_err = 1;
+ rjt_err = LSRJT_UNABLE_TPC;
break;
}
lpfc_disc_state_machine(vport, ndlp, elsiocb, NLP_EVT_RCV_PRLI);
break;
case ELS_CMD_LIRR:
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
+ "RCV LIRR: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
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,
+ "RCV RPS: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
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,
+ "RCV RPL: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
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,
+ "RCV RNID: did:x%x/ste:x%x flg:x%x",
+ did, vport->port_state, ndlp->nlp_flag);
+
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,
+ "RCV ELS cmd: cmd:x%x did:x%x/ste:x%x",
+ cmd, did, vport->port_state);
+
/* Unsupported ELS command, reject */
- rjt_err = 2;
+ 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;
}
/* check if need to LS_RJT received ELS cmd */
if (rjt_err) {
memset(&stat, 0, sizeof(stat));
- if (rjt_err == 1)
- stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
- else
- stat.un.b.lsRjtRsnCode = LSRJT_INVALID_CMD;
+ stat.un.b.lsRjtRsnCode = rjt_err;
stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
- lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp);
- if (newnode)
- lpfc_drop_node(vport, ndlp);
+ lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp,
+ NULL);
}
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++;
}
lpfc_find_vport_by_vpid(struct lpfc_hba *phba, uint16_t vpi)
{
struct lpfc_vport *vport;
+ unsigned long flags;
+ spin_lock_irqsave(&phba->hbalock, flags);
list_for_each_entry(vport, &phba->port_list, listentry) {
- if (vport->vpi == vpi)
+ if (vport->vpi == vpi) {
+ spin_unlock_irqrestore(&phba->hbalock, flags);
return vport;
+ }
}
+ spin_unlock_irqrestore(&phba->hbalock, flags);
return NULL;
}
vport = lpfc_find_vport_by_vpid(phba, vpi);
}
}
- /* If there are no BDEs associated
- * with this IOCB, there is nothing to do.
- */
+ /* If there are no BDEs associated
+ * with this IOCB, there is nothing to do.
+ */
if (icmd->ulpBdeCount == 0)
return;
- /* type of ELS cmd is first 32bit word
- * in packet
- */
+ /* type of ELS cmd is first 32bit word
+ * in packet
+ */
if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED) {
elsiocb->context2 = bdeBuf1;
} else {
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);
ndlp->nlp_type |= NLP_FABRIC;
+ } else if (!NLP_CHK_NODE_ACT(ndlp)) {
+ ndlp = lpfc_enable_node(vport, ndlp, NLP_STE_UNUSED_NODE);
+ if (!ndlp) {
+ if (phba->fc_topology == TOPOLOGY_LOOP) {
+ lpfc_disc_start(vport);
+ return;
+ }
+ lpfc_vport_set_state(vport, FC_VPORT_FAILED);
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+ "0348 NameServer login: node freed\n");
+ return;
+ }
}
lpfc_nlp_set_state(vport, ndlp, NLP_STE_PLOGI_ISSUE);
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 */
case 0x9603: /* max_vpi exceeded */
+ case 0x9602: /* Link event since CLEAR_LA */
/* giving up on vport registration */
lpfc_vport_set_state(vport, FC_VPORT_FAILED);
spin_lock_irq(shost->host_lock);
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;
- lpfc_initial_fdisc(vport);
+ spin_unlock_irq(shost->host_lock);
+ if (vport->port_type == LPFC_PHYSICAL_PORT)
+ lpfc_initial_flogi(vport);
+ else
+ 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.
lpfc_set_disctmo(piocb->vport);
}
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "FDISC cmpl: status:x%x/x%x prevdid:x%x",
+ irsp->ulpStatus, irsp->un.ulpWord[4], vport->fc_prevDID);
+
if (irsp->ulpStatus) {
/* 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_nlp_put(ndlp);
/* giving up on FDISC. Cancel discovery timer */
lpfc_can_disctmo(vport);
*/
list_for_each_entry_safe(np, next_np,
&vport->fc_nodes, nlp_listp) {
- if (np->nlp_state != NLP_STE_NPR_NODE
- || !(np->nlp_flag & NLP_NPR_ADISC))
+ if (!NLP_CHK_NODE_ACT(ndlp) ||
+ (np->nlp_state != NLP_STE_NPR_NODE) ||
+ !(np->nlp_flag & NLP_NPR_ADISC))
continue;
spin_lock_irq(shost->host_lock);
np->nlp_flag &= ~NLP_NPR_ADISC;
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)
{
uint16_t cmdsize;
int did = ndlp->nlp_DID;
int rc;
- int new_ndlp = 0;
cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
ELS_CMD_FDISC);
if (!elsiocb) {
- if (new_ndlp)
- mempool_free(ndlp, phba->nlp_mem_pool);
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;
}
phba->fc_stat.elsXmitFDISC++;
elsiocb->iocb_cmpl = lpfc_cmpl_els_fdisc;
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue FDISC: did:x%x",
+ did, 0, 0);
+
rc = lpfc_issue_fabric_iocb(phba, elsiocb);
if (rc == IOCB_ERROR) {
lpfc_els_free_iocb(phba, elsiocb);
- if (new_ndlp)
- mempool_free(ndlp, phba->nlp_mem_pool);
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);
struct lpfc_iocbq *rspiocb)
{
struct lpfc_vport *vport = cmdiocb->vport;
+ IOCB_t *irsp;
+ struct lpfc_nodelist *ndlp;
+ ndlp = (struct lpfc_nodelist *)cmdiocb->context1;
+
+ irsp = &rspiocb->iocb;
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "LOGO npiv cmpl: status:x%x/x%x did:x%x",
+ irsp->ulpStatus, irsp->un.ulpWord[4], irsp->un.rcvels.remoteID);
lpfc_els_free_iocb(phba, cmdiocb);
vport->unreg_vpi_cmpl = VPORT_ERROR;
+
+ /* Trigger the release of the ndlp after logo */
+ lpfc_nlp_put(ndlp);
}
int
pcmd += sizeof(uint32_t);
memcpy(pcmd, &vport->fc_portname, sizeof(struct lpfc_name));
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_CMD,
+ "Issue LOGO npiv did:x%x flg:x%x",
+ ndlp->nlp_DID, ndlp->nlp_flag, 0);
+
elsiocb->iocb_cmpl = lpfc_cmpl_els_npiv_logo;
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_LOGO_SND;
repeat:
iocb = NULL;
spin_lock_irqsave(&phba->hbalock, iflags);
- /* Post any pending iocb to the SLI layer */
+ /* Post any pending iocb to the SLI layer */
if (atomic_read(&phba->fabric_iocb_count) == 0) {
list_remove_head(&phba->fabric_iocb_list, iocb, typeof(*iocb),
list);
if (iocb)
+ /* Increment fabric iocb count to hold the position */
atomic_inc(&phba->fabric_iocb_count);
}
spin_unlock_irqrestore(&phba->hbalock, iflags);
iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
iocb->iocb_flag |= LPFC_IO_FABRIC;
+ lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
+ "Fabric sched1: ste:x%x",
+ iocb->vport->port_state, 0, 0);
+
ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
if (ret == IOCB_ERROR) {
int blocked;
blocked = test_and_set_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
- /* Start a timer to unblock fabric
- * iocbs after 100ms
- */
+ /* Start a timer to unblock fabric iocbs after 100ms */
if (!blocked)
mod_timer(&phba->fabric_block_timer, jiffies + HZ/10 );
atomic_dec(&phba->fabric_iocb_count);
if (!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags)) {
- /* Post any pending iocbs to HBA */
- lpfc_resume_fabric_iocbs(phba);
+ /* Post any pending iocbs to HBA */
+ lpfc_resume_fabric_iocbs(phba);
}
}
-int
+static int
lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
{
unsigned long iflags;
ready = atomic_read(&phba->fabric_iocb_count) == 0 &&
!test_bit(FABRIC_COMANDS_BLOCKED, &phba->bit_flags);
+ if (ready)
+ /* Increment fabric iocb count to hold the position */
+ atomic_inc(&phba->fabric_iocb_count);
spin_unlock_irqrestore(&phba->hbalock, iflags);
if (ready) {
iocb->fabric_iocb_cmpl = iocb->iocb_cmpl;
iocb->iocb_cmpl = lpfc_cmpl_fabric_iocb;
iocb->iocb_flag |= LPFC_IO_FABRIC;
- atomic_inc(&phba->fabric_iocb_count);
+ lpfc_debugfs_disc_trc(iocb->vport, LPFC_DISC_TRC_ELS_CMD,
+ "Fabric sched2: ste:x%x",
+ iocb->vport->port_state, 0, 0);
+
ret = lpfc_sli_issue_iocb(phba, pring, iocb, 0);
if (ret == IOCB_ERROR) {
}
-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 */