/*******************************************************************
* 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 *
struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_hba *phba = vport->phba;
struct lpfc_dmabuf *pcmd;
+ struct lpfc_work_evt *evtp;
uint32_t *lp;
IOCB_t *icmd;
struct serv_parm *sp;
del_timer_sync(&ndlp->nlp_delayfunc);
ndlp->nlp_last_elscmd = 0;
- if (!list_empty(&ndlp->els_retry_evt.evt_listp))
+ if (!list_empty(&ndlp->els_retry_evt.evt_listp)) {
list_del_init(&ndlp->els_retry_evt.evt_listp);
+ /* Decrement ndlp reference count held for the
+ * delayed retry
+ */
+ evtp = &ndlp->els_retry_evt;
+ lpfc_nlp_put((struct lpfc_nodelist *)evtp->evt_arg1);
+ }
if (ndlp->nlp_flag & NLP_NPR_2B_DISC) {
spin_lock_irq(shost->host_lock);
ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
spin_unlock_irq(shost->host_lock);
- if (vport->num_disc_nodes) {
+
+ if ((ndlp->nlp_flag & NLP_ADISC_SND) &&
+ (vport->num_disc_nodes)) {
/* Check to see if there are more
- * PLOGIs to be sent
+ * ADISCs to be sent
*/
- lpfc_more_plogi(vport);
+ lpfc_more_adisc(vport);
+
+ if ((vport->num_disc_nodes == 0) &&
+ (vport->fc_npr_cnt))
+ lpfc_els_disc_plogi(vport);
if (vport->num_disc_nodes == 0) {
spin_lock_irq(shost->host_lock);
}
}
}
+ } else if ((ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) &&
+ (ndlp->nlp_flag & NLP_NPR_2B_DISC) &&
+ (vport->num_disc_nodes)) {
+ spin_lock_irq(shost->host_lock);
+ ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+ spin_unlock_irq(shost->host_lock);
+ /* Check to see if there are more
+ * PLOGIs to be sent
+ */
+ lpfc_more_plogi(vport);
+ if (vport->num_disc_nodes == 0) {
+ spin_lock_irq(shost->host_lock);
+ vport->fc_flag &= ~FC_NDISC_ACTIVE;
+ spin_unlock_irq(shost->host_lock);
+ lpfc_can_disctmo(vport);
+ lpfc_end_rscn(vport);
+ }
}
lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox);
return 0;
}
- /* Check config parameter use-adisc or FCP-2 */
- if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
- ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
- spin_lock_irq(shost->host_lock);
- ndlp->nlp_flag |= NLP_NPR_ADISC;
- spin_unlock_irq(shost->host_lock);
- return 1;
+ if (!(vport->fc_flag & FC_PT2PT)) {
+ /* Check config parameter use-adisc or FCP-2 */
+ if ((vport->cfg_use_adisc && (vport->fc_flag & FC_RSCN_MODE)) ||
+ ndlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
+ spin_lock_irq(shost->host_lock);
+ ndlp->nlp_flag |= NLP_NPR_ADISC;
+ spin_unlock_irq(shost->host_lock);
+ return 1;
+ }
}
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
lpfc_unreg_rpi(vport, ndlp);
void *arg, uint32_t evt)
{
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
- "0253 Illegal State Transition: node x%x "
+ "0271 Illegal State Transition: node x%x "
"event x%x, state x%x Data: x%x x%x\n",
ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
ndlp->nlp_flag);
*/
if (!(ndlp->nlp_flag & NLP_RCV_PLOGI)) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
- "0253 Illegal State Transition: node x%x "
+ "0272 Illegal State Transition: node x%x "
"event x%x, state x%x Data: x%x x%x\n",
ndlp->nlp_DID, evt, ndlp->nlp_state, ndlp->nlp_rpi,
ndlp->nlp_flag);
uint32_t evt)
{
struct lpfc_hba *phba = vport->phba;
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
struct lpfc_iocbq *cmdiocb, *rspiocb;
struct lpfc_dmabuf *pcmd, *prsp, *mp;
uint32_t *lp;
lp = (uint32_t *) prsp->virt;
sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
- if (wwn_to_u64(sp->portName.u.wwn) == 0 ||
- wwn_to_u64(sp->nodeName.u.wwn) == 0) {
+
+ /* Some switches have FDMI servers returning 0 for WWN */
+ if ((ndlp->nlp_DID != FDMI_DID) &&
+ (wwn_to_u64(sp->portName.u.wwn) == 0 ||
+ wwn_to_u64(sp->nodeName.u.wwn) == 0)) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
"0142 PLOGI RSP: Invalid WWN.\n");
goto out;
NLP_STE_REG_LOGIN_ISSUE);
return ndlp->nlp_state;
}
+ /* decrement node reference count to the failed mbox
+ * command
+ */
lpfc_nlp_put(ndlp);
mp = (struct lpfc_dmabuf *) mbox->context1;
lpfc_mbuf_free(phba, mp->virt, mp->phys);
"0261 Cannot Register NameServer login\n");
}
+ spin_lock_irq(shost->host_lock);
ndlp->nlp_flag |= NLP_DEFER_RM;
+ spin_unlock_irq(shost->host_lock);
return NLP_STE_FREED_NODE;
}
+static uint32_t
+lpfc_cmpl_logo_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
+ void *arg, uint32_t evt)
+{
+ return ndlp->nlp_state;
+}
+
+static uint32_t
+lpfc_cmpl_reglogin_plogi_issue(struct lpfc_vport *vport,
+ struct lpfc_nodelist *ndlp, void *arg, uint32_t evt)
+{
+ return ndlp->nlp_state;
+}
+
static uint32_t
lpfc_device_rm_plogi_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
void *arg, uint32_t evt)
lpfc_rcv_els_plogi_issue, /* RCV_PRLO */
lpfc_cmpl_plogi_plogi_issue, /* CMPL_PLOGI */
lpfc_disc_illegal, /* CMPL_PRLI */
- lpfc_disc_illegal, /* CMPL_LOGO */
+ lpfc_cmpl_logo_plogi_issue, /* CMPL_LOGO */
lpfc_disc_illegal, /* CMPL_ADISC */
- lpfc_disc_illegal, /* CMPL_REG_LOGIN */
+ lpfc_cmpl_reglogin_plogi_issue,/* CMPL_REG_LOGIN */
lpfc_device_rm_plogi_issue, /* DEVICE_RM */
lpfc_device_recov_plogi_issue, /* DEVICE_RECOVERY */
uint32_t cur_state, rc;
uint32_t(*func) (struct lpfc_vport *, struct lpfc_nodelist *, void *,
uint32_t);
+ uint32_t got_ndlp = 0;
+
+ if (lpfc_nlp_get(ndlp))
+ got_ndlp = 1;
- lpfc_nlp_get(ndlp);
cur_state = ndlp->nlp_state;
/* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */
rc = (func) (vport, ndlp, arg, evt);
/* DSM out state <rc> on NPort <nlp_DID> */
- lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ if (got_ndlp) {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
"0212 DSM out state %d on NPort x%x Data: x%x\n",
rc, ndlp->nlp_DID, ndlp->nlp_flag);
- lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
- "DSM out: ste:%d did:x%x flg:x%x",
- rc, ndlp->nlp_DID, ndlp->nlp_flag);
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
+ "DSM out: ste:%d did:x%x flg:x%x",
+ rc, ndlp->nlp_DID, ndlp->nlp_flag);
+ /* Decrement the ndlp reference count held for this function */
+ lpfc_nlp_put(ndlp);
+ } else {
+ lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+ "0212 DSM out state %d on NPort free\n", rc);
- lpfc_nlp_put(ndlp);
+ lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_DSM,
+ "DSM out: ste:%d did:x%x flg:x%x",
+ rc, 0, 0);
+ }
return rc;
}