]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/lpfc/lpfc_els.c
x86: don't disable TSC in any C states on AMD Fam10h
[linux-2.6-omap-h63xx.git] / drivers / scsi / lpfc / lpfc_els.c
index b8e048a467d285cda74f39f64fdbaedb4524703f..c6b739dc6bc32c695e9721e32a5e4df79daa7900 100644 (file)
@@ -18,7 +18,7 @@
  * 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>
@@ -42,6 +42,14 @@ 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;
 
@@ -63,10 +71,10 @@ lpfc_els_chk_latt(struct lpfc_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
@@ -109,14 +117,11 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
 
        /* 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);
 
@@ -126,13 +131,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
                if (prsp)
                        prsp->virt = lpfc_mbuf_alloc(phba, MEM_PRI,
                                                     &prsp->phys);
-               if (prsp == 0 || prsp->virt == 0) {
-                       kfree(prsp);
-                       lpfc_mbuf_free(phba, pcmd->virt, pcmd->phys);
-                       kfree(pcmd);
-                       lpfc_sli_release_iocbq(phba, elsiocb);
-                       return NULL;
-               }
+               if (!prsp || !prsp->virt)
+                       goto els_iocb_free_prsp_exit;
                INIT_LIST_HEAD(&prsp->list);
        } else {
                prsp = NULL;
@@ -143,15 +143,8 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
        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);
 
@@ -196,9 +189,10 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
                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;
@@ -208,26 +202,36 @@ lpfc_prep_els_iocb(struct lpfc_vport *vport, uint8_t expectRsp,
        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)
@@ -238,40 +242,53 @@ lpfc_issue_fabric_reglogin(struct lpfc_vport *vport)
        struct lpfc_nodelist *ndlp;
        struct serv_parm *sp;
        int rc;
+       int err = 0;
 
        sp = &phba->fc_fabparam;
        ndlp = lpfc_findnode_did(vport, Fabric_DID);
-       if (!ndlp)
+       if (!ndlp) {
+               err = 1;
                goto fail;
+       }
 
        mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-       if (!mbox)
+       if (!mbox) {
+               err = 2;
                goto fail;
+       }
 
        vport->port_state = LPFC_FABRIC_CFG_LINK;
        lpfc_config_link(phba, mbox);
        mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
        mbox->vport = vport;
 
-       rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
-       if (rc == MBX_NOT_FINISHED)
+       rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+       if (rc == MBX_NOT_FINISHED) {
+               err = 3;
                goto fail_free_mbox;
+       }
 
        mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-       if (!mbox)
+       if (!mbox) {
+               err = 4;
                goto fail;
+       }
        rc = lpfc_reg_login(phba, vport->vpi, Fabric_DID, (uint8_t *)sp, mbox,
                            0);
-       if (rc)
+       if (rc) {
+               err = 5;
                goto fail_free_mbox;
+       }
 
        mbox->mbox_cmpl = lpfc_mbx_cmpl_fabric_reg_login;
        mbox->vport = vport;
        mbox->context2 = lpfc_nlp_get(ndlp);
 
-       rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
-       if (rc == MBX_NOT_FINISHED)
+       rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+       if (rc == MBX_NOT_FINISHED) {
+               err = 6;
                goto fail_issue_reg_login;
+       }
 
        return 0;
 
@@ -285,9 +302,8 @@ fail_free_mbox:
 
 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;
 }
 
@@ -340,20 +356,19 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 
        if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
                if (sp->cmn.response_multiple_NPort) {
-                       lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
-                                       "%d:1816 FLOGI NPIV supported, "
-                                       "response data 0x%x\n",
-                                       phba->brd_no,
-                                       sp->cmn.response_multiple_NPort);
+                       lpfc_printf_vlog(vport, KERN_WARNING,
+                                        LOG_ELS | LOG_VPORT,
+                                        "1816 FLOGI NPIV supported, "
+                                        "response data 0x%x\n",
+                                        sp->cmn.response_multiple_NPort);
                        phba->link_flag |= LS_NPIV_FAB_SUPPORTED;
-
                } else {
                        /* Because we asked f/w for NPIV it still expects us
-                          to call reg_vnpid atleast for the physcial host */
-                       lpfc_printf_log(phba, KERN_WARNING, LOG_ELS | LOG_VPORT,
-                                       "%d:1817 Fabric does not support NPIV "
-                                       "- configuring single port mode.\n",
-                                       phba->brd_no);
+                       to call reg_vnpid atleast for the physcial host */
+                       lpfc_printf_vlog(vport, KERN_WARNING,
+                                        LOG_ELS | LOG_VPORT,
+                                        "1817 Fabric does not support NPIV "
+                                        "- configuring single port mode.\n");
                        phba->link_flag &= ~LS_NPIV_FAB_SUPPORTED;
                }
        }
@@ -376,11 +391,12 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                }
                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 &&
@@ -435,8 +451,7 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
 
                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;
@@ -469,6 +484,9 @@ lpfc_cmpl_els_flogi_nport(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                lpfc_nlp_put(ndlp);
        }
 
+       /* If we are pt2pt with another NPort, force NPIV off! */
+       phba->sli3_options &= ~LPFC_SLI3_NPIV_ENABLED;
+
        spin_lock_irq(shost->host_lock);
        vport->fc_flag |= FC_PT2PT;
        spin_unlock_irq(shost->host_lock);
@@ -494,6 +512,9 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 
        /* 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;
        }
@@ -518,16 +539,15 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                 * 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;
        }
 
@@ -540,12 +560,11 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        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) {
                /*
@@ -570,8 +589,13 @@ flogifail:
 
                /* 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);
 }
@@ -662,8 +686,8 @@ lpfc_els_abort_flogi(struct lpfc_hba *phba)
 
        /* 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];
 
@@ -693,6 +717,9 @@ lpfc_initial_flogi(struct lpfc_vport *vport)
        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) {
@@ -704,7 +731,11 @@ lpfc_initial_flogi(struct lpfc_vport *vport)
        } else {
                lpfc_dequeue_node(vport, ndlp);
        }
+
        if (lpfc_issue_els_flogi(vport, ndlp, 0)) {
+               /* This decrement of reference count to node shall kick off
+                * the release of the node.
+                */
                lpfc_nlp_put(ndlp);
        }
        return 1;
@@ -728,26 +759,29 @@ lpfc_initial_fdisc(struct lpfc_vport *vport)
                lpfc_dequeue_node(vport, ndlp);
        }
        if (lpfc_issue_els_fdisc(vport, ndlp, 0)) {
+               /* decrement node reference count to trigger the release of
+                * the node.
+                */
                lpfc_nlp_put(ndlp);
+               return 0;
        }
        return 1;
 }
-static void
+
+void
 lpfc_more_plogi(struct lpfc_vport *vport)
 {
        int sentplogi;
-       struct lpfc_hba *phba = vport->phba;
 
        if (vport->num_disc_nodes)
                vport->num_disc_nodes--;
 
        /* Continue discovery with <num_disc_nodes> PLOGIs to go */
-       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-                       "%d (%d):0232 Continue discovery with %d PLOGIs to go "
-                       "Data: x%x x%x x%x\n",
-                       phba->brd_no, vport->vpi, vport->num_disc_nodes,
-                       vport->fc_plogi_cnt, vport->fc_flag, vport->port_state);
-
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+                        "0232 Continue discovery with %d PLOGIs to go "
+                        "Data: x%x x%x x%x\n",
+                        vport->num_disc_nodes, vport->fc_plogi_cnt,
+                        vport->fc_flag, vport->port_state);
        /* Check to see if there are more PLOGIs to be sent */
        if (vport->fc_flag & FC_NLP_MORE)
                /* go thru NPR nodes and issue any remaining ELS PLOGIs */
@@ -762,6 +796,8 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
 {
        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;
@@ -798,11 +834,34 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
        lpfc_unreg_rpi(vport, new_ndlp);
        new_ndlp->nlp_DID = ndlp->nlp_DID;
        new_ndlp->nlp_prev_state = ndlp->nlp_prev_state;
+
+       if (ndlp->nlp_flag & NLP_NPR_2B_DISC)
+               new_ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+
        lpfc_nlp_set_state(vport, new_ndlp, ndlp->nlp_state);
 
        /* Move this back to NPR state */
-       if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0)
+       if (memcmp(&ndlp->nlp_portname, name, sizeof(struct lpfc_name)) == 0) {
+               /* The new_ndlp is replacing ndlp totally, so we need
+                * to put ndlp on UNUSED list and try to free it.
+                */
+
+               /* Fix up the rport accordingly */
+               rport =  ndlp->rport;
+               if (rport) {
+                       rdata = rport->dd_data;
+                       if (rdata->pnode == ndlp) {
+                               lpfc_nlp_put(ndlp);
+                               ndlp->rport = NULL;
+                               rdata->pnode = lpfc_nlp_get(new_ndlp);
+                               new_ndlp->rport = rport;
+                       }
+                       new_ndlp->nlp_type = ndlp->nlp_type;
+               }
+
                lpfc_drop_node(vport, ndlp);
+       }
        else {
                lpfc_unreg_rpi(vport, ndlp);
                ndlp->nlp_DID = 0; /* Two ndlps cannot have the same did */
@@ -811,6 +870,27 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp,
        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)
@@ -833,11 +913,12 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 
        ndlp = lpfc_findnode_did(vport, irsp->un.elsreq64.remoteID);
        if (!ndlp) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-                       "%d (%d):0136 PLOGI completes to NPort x%x "
-                       "with no ndlp. Data: x%x x%x x%x\n",
-                       phba->brd_no, vport->vpi, irsp->un.elsreq64.remoteID,
-                       irsp->ulpStatus, irsp->un.ulpWord[4], irsp->ulpIoTag);
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+                                "0136 PLOGI completes to NPort x%x "
+                                "with no ndlp. Data: x%x x%x x%x\n",
+                                irsp->un.elsreq64.remoteID,
+                                irsp->ulpStatus, irsp->un.ulpWord[4],
+                                irsp->ulpIoTag);
                goto out;
        }
 
@@ -851,13 +932,11 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        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);
@@ -881,17 +960,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        }
                        goto out;
                }
-
                /* PLOGI failed */
-               if (ndlp->nlp_DID == NameServer_DID) {
-                       lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-                       lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-                               "%d (%d):0250 Nameserver login error: "
-                               "0x%x / 0x%x\n",
-                               phba->brd_no, vport->vpi,
-                               irsp->ulpStatus, irsp->un.ulpWord[4]);
-               }
-
                /* Do not call DSM for lpfc_els_abort'ed ELS cmds */
                if (lpfc_error_lost_link(irsp)) {
                        rc = NLP_STE_FREED_NODE;
@@ -919,20 +988,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        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);
                }
        }
 
@@ -947,6 +1003,7 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
        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;
@@ -957,8 +1014,11 @@ lpfc_issue_els_plogi(struct lpfc_vport *vport, uint32_t did, uint8_t retry)
        psli = &phba->sli;
        pring = &psli->ring[LPFC_ELS_RING];     /* ELS ring */
 
+       ndlp = lpfc_findnode_did(vport, did);
+       /* If ndlp if not NULL, we will bump the reference count on it */
+
        cmdsize = (sizeof(uint32_t) + sizeof(struct serv_parm));
-       elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, NULL, did,
+       elsiocb = lpfc_prep_els_iocb(vport, 1, cmdsize, retry, ndlp, did,
                                     ELS_CMD_PLOGI);
        if (!elsiocb)
                return 1;
@@ -1017,14 +1077,12 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                "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 */
@@ -1125,22 +1183,19 @@ lpfc_issue_els_prli(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        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);
@@ -1153,8 +1208,6 @@ lpfc_more_adisc(struct lpfc_vport *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 */
@@ -1163,19 +1216,7 @@ lpfc_rscn_disc(struct lpfc_vport *vport)
                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
@@ -1206,15 +1247,12 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        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);
@@ -1374,15 +1412,12 @@ lpfc_cmpl_els_logo(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                "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;
@@ -1438,6 +1473,13 @@ lpfc_issue_els_logo(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        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);
@@ -1488,15 +1530,11 @@ lpfc_cmpl_els_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                "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);
@@ -1528,6 +1566,9 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
                                     ndlp->nlp_DID, ELS_CMD_SCR);
 
        if (!elsiocb) {
+               /* This will trigger the release of the node just
+                * allocated
+                */
                lpfc_nlp_put(ndlp);
                return 1;
        }
@@ -1549,10 +1590,17 @@ lpfc_issue_els_scr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
        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;
 }
@@ -1584,6 +1632,9 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
        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;
        }
@@ -1620,35 +1671,21 @@ lpfc_issue_els_farpr(struct lpfc_vport *vport, uint32_t nportid, uint8_t retry)
        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)
 {
@@ -1704,7 +1741,10 @@ lpfc_els_retry_delay(unsigned long ptr)
                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)
@@ -1788,6 +1828,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        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;
 
@@ -1831,17 +1872,20 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                case IOERR_ILLEGAL_COMMAND:
                        if ((phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) &&
                            (cmd == ELS_CMD_FDISC)) {
-                               lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-                               "%d (%d):0124 FDISC failed (3/6) retrying...\n",
-                                       phba->brd_no, vport->vpi);
+                               lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+                                                "0124 FDISC failed (3/6) "
+                                                "retrying...\n");
                                lpfc_mbx_unreg_vpi(vport);
                                retry = 1;
-                               /* Always retry for this case */
-                               cmdiocb->retry = 0;
+                               /* FDISC retry policy */
+                               maxretry = 48;
+                               if (cmdiocb->retry >= 32)
+                                       delay = 1000;
                        }
                        break;
 
                case IOERR_NO_RESOURCES:
+                       logerr = 1; /* HBA out of resources */
                        retry = 1;
                        if (cmdiocb->retry > 100)
                                delay = 100;
@@ -1870,6 +1914,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
 
        case IOSTAT_NPORT_BSY:
        case IOSTAT_FABRIC_BSY:
+               logerr = 1; /* Fabric / Remote NPort out of resources */
                retry = 1;
                break;
 
@@ -1898,10 +1943,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        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);
                        }
@@ -1913,8 +1958,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                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;
@@ -1926,10 +1973,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                          ((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);
                        }
@@ -1948,6 +1995,15 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        if (did == FDMI_DID)
                retry = 1;
 
+       if ((cmd == ELS_CMD_FLOGI) &&
+           (phba->fc_topology != TOPOLOGY_LOOP)) {
+               /* FLOGI retry policy */
+               retry = 1;
+               maxretry = 48;
+               if (cmdiocb->retry >= 32)
+                       delay = 1000;
+       }
+
        if ((++cmdiocb->retry) >= maxretry) {
                phba->fc_stat.elsRetryExceeded++;
                retry = 0;
@@ -1959,11 +2015,10 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        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) ||
@@ -2031,13 +2086,47 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        return 1;
                }
        }
-
        /* No retry ELS command <elsCmd> to remote NPORT <did> */
-       lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+       if (logerr) {
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+                        "0137 No retry ELS command x%x to remote "
+                        "NPORT x%x: Out of Resources: Error:x%x/%x\n",
+                        cmd, did, irsp->ulpStatus,
+                        irsp->un.ulpWord[4]);
+       }
+       else {
+               lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
                         "0108 No retry ELS command x%x to remote "
                         "NPORT x%x Retried:%d Error:x%x/%x\n",
                         cmd, did, cmdiocb->retry, irsp->ulpStatus,
                         irsp->un.ulpWord[4]);
+       }
+       return 0;
+}
+
+static int
+lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
+{
+       struct lpfc_dmabuf *buf_ptr;
+
+       /* Free the response before processing the command.  */
+       if (!list_empty(&buf_ptr1->list)) {
+               list_remove_head(&buf_ptr1->list, buf_ptr,
+                                struct lpfc_dmabuf,
+                                list);
+               lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+               kfree(buf_ptr);
+       }
+       lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
+       kfree(buf_ptr1);
+       return 0;
+}
+
+static int
+lpfc_els_free_bpl(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr)
+{
+       lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
+       kfree(buf_ptr);
        return 0;
 }
 
@@ -2045,30 +2134,63 @@ int
 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;
@@ -2086,23 +2208,26 @@ lpfc_cmpl_els_logo_acc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        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;
@@ -2118,7 +2243,14 @@ lpfc_mbx_cmpl_dflt_rpi(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        lpfc_mbuf_free(phba, mp->virt, mp->phys);
        kfree(mp);
        mempool_free(pmb, phba->mbox_mem_pool);
-       lpfc_nlp_put(ndlp);
+       if (ndlp) {
+               lpfc_nlp_put(ndlp);
+               /* This is the end of the default RPI cleanup logic for this
+                * ndlp. If no other discovery threads are using this ndlp.
+                * we should free all resources associated with it.
+                */
+               lpfc_nlp_not_used(ndlp);
+       }
        return;
 }
 
@@ -2129,15 +2261,29 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        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) {
@@ -2148,24 +2294,30 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                        }
                        mempool_free(mbox, phba->mbox_mem_pool);
                }
+               if (ndlp && (ndlp->nlp_flag & NLP_RM_DFLT_RPI))
+                       if (lpfc_nlp_not_used(ndlp)) {
+                               ndlp = NULL;
+                               /* Indicate the node has already released,
+                                * should not reference to it from within
+                                * the routine lpfc_els_free_iocb.
+                                */
+                               cmdiocb->context1 = NULL;
+                       }
                goto out;
        }
 
        lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
-               "ACC cmpl:        status:x%x/x%x did:x%x",
+               "ELS rsp cmpl:    status:x%x/x%x did:x%x",
                irsp->ulpStatus, irsp->un.ulpWord[4],
-               irsp->un.rcvels.remoteID);
-
+               cmdiocb->iocb.un.elsreq64.remoteID);
        /* ELS response tag <ulpIoTag> completes */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "%d (%d):0110 ELS response tag x%x completes "
-                       "Data: x%x x%x x%x x%x x%x x%x x%x\n",
-                       phba->brd_no, vport->vpi,
-                       cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
-                       rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
-                       ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
-                       ndlp->nlp_rpi);
-
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                        "0110 ELS response tag x%x completes "
+                        "Data: x%x x%x x%x x%x x%x x%x x%x\n",
+                        cmdiocb->iocb.ulpIoTag, rspiocb->iocb.ulpStatus,
+                        rspiocb->iocb.un.ulpWord[4], rspiocb->iocb.ulpTimeout,
+                        ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+                        ndlp->nlp_rpi);
        if (mbox) {
                if ((rspiocb->iocb.ulpStatus == 0)
                    && (ndlp->nlp_flag & NLP_ACC_REGLOGIN)) {
@@ -2182,20 +2334,39 @@ lpfc_cmpl_els_rsp(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                lpfc_nlp_set_state(vport, ndlp,
                                           NLP_STE_REG_LOGIN_ISSUE);
                        }
-                       if (lpfc_sli_issue_mbox(phba, mbox,
-                                               (MBX_NOWAIT | MBX_STOP_IOCB))
+                       if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
                            != MBX_NOT_FINISHED) {
                                goto out;
                        }
-                       lpfc_nlp_put(ndlp);
-                       /* NOTE: we should have messages for unsuccessful
-                          reglogin */
+
+                       /* ELS rsp: Cannot issue reg_login for <NPortid> */
+                       lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+                               "0138 ELS rsp: Cannot issue reg_login for x%x "
+                               "Data: x%x x%x x%x\n",
+                               ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+                               ndlp->nlp_rpi);
+
+                       if (lpfc_nlp_not_used(ndlp)) {
+                               ndlp = NULL;
+                               /* Indicate node has already been released,
+                                * should not reference to it from within
+                                * the routine lpfc_els_free_iocb.
+                                */
+                               cmdiocb->context1 = NULL;
+                       }
                } else {
                        /* Do not drop node for lpfc_els_abort'ed ELS cmds */
                        if (!lpfc_error_lost_link(irsp) &&
                            ndlp->nlp_flag & NLP_ACC_REGLOGIN) {
-                               lpfc_drop_node(vport, ndlp);
-                               ndlp = NULL;
+                               if (lpfc_nlp_not_used(ndlp)) {
+                                       ndlp = NULL;
+                                       /* Indicate node has already been
+                                        * released, should not reference
+                                        * to it from within the routine
+                                        * lpfc_els_free_iocb.
+                                        */
+                                       cmdiocb->context1 = NULL;
+                               }
                        }
                }
                mp = (struct lpfc_dmabuf *) mbox->context1;
@@ -2210,7 +2381,21 @@ out:
                spin_lock_irq(shost->host_lock);
                ndlp->nlp_flag &= ~(NLP_ACC_REGLOGIN | NLP_RM_DFLT_RPI);
                spin_unlock_irq(shost->host_lock);
+
+               /* If the node is not being used by another discovery thread,
+                * and we are sending a reject, we are done with it.
+                * Release driver reference count here and free associated
+                * resources.
+                */
+               if (ls_rjt)
+                       if (lpfc_nlp_not_used(ndlp))
+                               /* Indicate node has already been released,
+                                * should not reference to it from within
+                                * the routine lpfc_els_free_iocb.
+                                */
+                               cmdiocb->context1 = NULL;
        }
+
        lpfc_els_free_iocb(phba, cmdiocb);
        return;
 }
@@ -2218,7 +2403,7 @@ out:
 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;
@@ -2304,20 +2489,13 @@ lpfc_els_rsp_acc(struct lpfc_vport *vport, uint32_t flag,
        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;
@@ -2369,20 +2547,17 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
        pcmd += sizeof(uint32_t);
        *((uint32_t *) (pcmd)) = rejectError;
 
-       if (mbox) {
+       if (mbox)
                elsiocb->context_un.mbox = mbox;
-               elsiocb->context1 = lpfc_nlp_get(ndlp);
-       }
 
        /* Xmit ELS RJT <err> response tag <ulpIoTag> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "%d (%d):0129 Xmit ELS RJT x%x response tag x%x "
-                       "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
-                       "rpi x%x\n",
-                       phba->brd_no, vport->vpi, rejectError, elsiocb->iotag,
-                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
-                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
-
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                        "0129 Xmit ELS RJT x%x response tag x%x "
+                        "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
+                        "rpi x%x\n",
+                        rejectError, elsiocb->iotag,
+                        elsiocb->iocb.ulpContext, ndlp->nlp_DID,
+                        ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
        lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
                "Issue LS_RJT:    did:x%x flg:x%x err:x%x",
                ndlp->nlp_DID, ndlp->nlp_flag, rejectError);
@@ -2390,6 +2565,7 @@ lpfc_els_rsp_reject(struct lpfc_vport *vport, uint32_t rejectError,
        phba->fc_stat.elsXmitLSRJT++;
        elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
        rc = lpfc_sli_issue_iocb(phba, pring, elsiocb, 0);
+
        if (rc == IOCB_ERROR) {
                lpfc_els_free_iocb(phba, elsiocb);
                return 1;
@@ -2422,13 +2598,12 @@ lpfc_els_rsp_adisc_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
        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;
@@ -2482,15 +2657,13 @@ lpfc_els_rsp_prli_acc(struct lpfc_vport *vport, struct lpfc_iocbq *oldiocb,
        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));
@@ -2564,16 +2737,11 @@ lpfc_els_rsp_rnid_acc(struct lpfc_vport *vport, uint8_t format,
        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);
 
@@ -2640,7 +2808,7 @@ lpfc_els_disc_adisc(struct lpfc_vport *vport)
                        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);
@@ -2675,7 +2843,7 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport)
                        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);
@@ -2683,7 +2851,10 @@ lpfc_els_disc_plogi(struct lpfc_vport *vport)
                        }
                }
        }
-       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);
@@ -2716,7 +2887,6 @@ lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did)
        D_ID rscn_did;
        uint32_t *lp;
        uint32_t payload_len, i;
-       struct lpfc_hba *phba = vport->phba;
 
        ns_did.un.word = did;
 
@@ -2751,12 +2921,10 @@ lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did)
                                break;
                        default:
                                /* Unknown Identifier in RSCN node */
-                               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-                                               "%d (%d):0217 Unknown "
-                                               "Identifier in RSCN payload "
-                                               "Data: x%x\n",
-                                               phba->brd_no, vport->vpi,
-                                               rscn_did.un.word);
+                               lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
+                                                "0217 Unknown Identifier in "
+                                                "RSCN payload Data: x%x\n",
+                                                rscn_did.un.word);
                        case 3: /* Whole Fabric effected */
                                return did;
                        }
@@ -2795,7 +2963,7 @@ lpfc_rscn_recovery_check(struct lpfc_vport *vport)
 
 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;
@@ -2813,13 +2981,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
 
        payload_len = be32_to_cpu(*lp++ & ~ELS_CMD_MASK);
        payload_len -= sizeof(uint32_t);        /* take off word 0 */
-
        /* RSCN received */
-       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-                       "%d (%d):0214 RSCN received Data: x%x x%x x%x x%x\n",
-                       phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
-                       *lp, rscn_cnt);
-
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+                        "0214 RSCN received Data: x%x x%x x%x x%x\n",
+                        vport->fc_flag, payload_len, *lp, rscn_cnt);
        for (i = 0; i < payload_len/sizeof(uint32_t); i++)
                fc_host_post_event(shost, fc_get_event_number(),
                        FCH_EVT_RSCN, lp[i]);
@@ -2832,8 +2997,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                        "RCV RSCN ignore: did:x%x/ste:x%x flg:x%x",
                        ndlp->nlp_DID, vport->port_state, ndlp->nlp_flag);
 
-               lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
-                                newnode);
+               lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
                return 0;
        }
 
@@ -2841,7 +3005,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
         * 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) {
@@ -2854,18 +3018,18 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                }
                if (rscn_id == hba_id) {
                        /* ALL NPortIDs in RSCN are on HBA */
-                       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-                         "%d (%d):0214 Ignore RSCN Data: x%x x%x x%x x%x\n",
-                         phba->brd_no, vport->vpi, vport->fc_flag, payload_len,
-                         *lp, rscn_cnt);
-
+                       lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+                                        "0214 Ignore RSCN "
+                                        "Data: x%x x%x x%x x%x\n",
+                                        vport->fc_flag, payload_len,
+                                        *lp, rscn_cnt);
                        lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_UNSOL,
                                "RCV RSCN vport:  did:x%x/ste:x%x flg:x%x",
                                ndlp->nlp_DID, vport->port_state,
                                ndlp->nlp_flag);
 
                        lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb,
-                               ndlp, NULL, newnode);
+                               ndlp, NULL);
                        return 0;
                }
        }
@@ -2878,10 +3042,10 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                        "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) {
@@ -2904,31 +3068,29 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                        }
 
                        /* Deferred RSCN */
-                       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-                                       "%d (%d):0235 Deferred RSCN "
-                                       "Data: x%x x%x x%x\n",
-                                       phba->brd_no, vport->vpi,
-                                       vport->fc_rscn_id_cnt, vport->fc_flag,
-                                       vport->port_state);
+                       lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+                                        "0235 Deferred RSCN "
+                                        "Data: x%x x%x x%x\n",
+                                        vport->fc_rscn_id_cnt, vport->fc_flag,
+                                        vport->port_state);
                } else {
-                       spin_lock_irq(shost->host_lock);
                        vport->fc_flag |= FC_RSCN_DISCOVERY;
                        spin_unlock_irq(shost->host_lock);
                        /* ReDiscovery RSCN */
-                       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-                                       "%d (%d):0234 ReDiscovery RSCN "
-                                       "Data: x%x x%x x%x\n",
-                                       phba->brd_no, vport->vpi,
-                                       vport->fc_rscn_id_cnt, vport->fc_flag,
-                                       vport->port_state);
+                       lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+                                        "0234 ReDiscovery RSCN "
+                                        "Data: x%x x%x x%x\n",
+                                        vport->fc_rscn_id_cnt, vport->fc_flag,
+                                        vport->port_state);
                }
                /* Send back ACC */
-               lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL,
-                                                               newnode);
+               lpfc_els_rsp_acc(vport, ELS_CMD_ACC, cmdiocb, ndlp, NULL);
 
                /* send RECOVERY event for ALL nodes that match RSCN payload */
                lpfc_rscn_recovery_check(vport);
+               spin_lock_irq(shost->host_lock);
                vport->fc_flag &= ~FC_RSCN_DEFERRED;
+               spin_unlock_irq(shost->host_lock);
                return 0;
        }
 
@@ -2949,7 +3111,7 @@ lpfc_els_rcv_rscn(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
        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);
@@ -2973,14 +3135,15 @@ lpfc_els_handle_rscn(struct lpfc_vport *vport)
        lpfc_set_disctmo(vport);
 
        /* RSCN processed */
-       lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
-                       "%d (%d):0215 RSCN processed Data: x%x x%x x%x x%x\n",
-                       phba->brd_no, vport->vpi,
-                       vport->fc_flag, 0, vport->fc_rscn_id_cnt,
-                       vport->port_state);
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_DISCOVERY,
+                        "0215 RSCN processed Data: x%x x%x x%x x%x\n",
+                        vport->fc_flag, 0, vport->fc_rscn_id_cnt,
+                        vport->port_state);
 
        /* To process RSCN, first compare RSCN data with NameServer */
        vport->fc_ns_retry = 0;
+       vport->num_disc_nodes = 0;
+
        ndlp = lpfc_findnode_did(vport, NameServer_DID);
        if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
                /* Good ndlp, issue CT Request to NameServer */
@@ -3019,7 +3182,7 @@ lpfc_els_handle_rscn(struct lpfc_vport *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;
@@ -3045,10 +3208,10 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
 
                /* 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;
        }
 
@@ -3074,8 +3237,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                        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);
@@ -3102,7 +3264,7 @@ lpfc_els_rcv_flogi(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
        }
 
        /* 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;
 }
@@ -3192,7 +3354,10 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        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;
 
@@ -3212,23 +3377,20 @@ lpfc_els_rsp_rps_acc(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                status |= 0x4;
 
        rps_rsp->rsvd1 = 0;
-       rps_rsp->portStatus = be16_to_cpu(status);
-       rps_rsp->linkFailureCnt = be32_to_cpu(mb->un.varRdLnk.linkFailureCnt);
-       rps_rsp->lossSyncCnt = be32_to_cpu(mb->un.varRdLnk.lossSyncCnt);
-       rps_rsp->lossSignalCnt = be32_to_cpu(mb->un.varRdLnk.lossSignalCnt);
-       rps_rsp->primSeqErrCnt = be32_to_cpu(mb->un.varRdLnk.primSeqErrCnt);
-       rps_rsp->invalidXmitWord = be32_to_cpu(mb->un.varRdLnk.invalidXmitWord);
-       rps_rsp->crcCnt = be32_to_cpu(mb->un.varRdLnk.crcCnt);
-
+       rps_rsp->portStatus = cpu_to_be16(status);
+       rps_rsp->linkFailureCnt = cpu_to_be32(mb->un.varRdLnk.linkFailureCnt);
+       rps_rsp->lossSyncCnt = cpu_to_be32(mb->un.varRdLnk.lossSyncCnt);
+       rps_rsp->lossSignalCnt = cpu_to_be32(mb->un.varRdLnk.lossSignalCnt);
+       rps_rsp->primSeqErrCnt = cpu_to_be32(mb->un.varRdLnk.primSeqErrCnt);
+       rps_rsp->invalidXmitWord = cpu_to_be32(mb->un.varRdLnk.invalidXmitWord);
+       rps_rsp->crcCnt = cpu_to_be32(mb->un.varRdLnk.crcCnt);
        /* Xmit ELS RPS ACC response tag <ulpIoTag> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "%d (%d):0118 Xmit ELS RPS ACC response tag x%x "
-                       "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
-                       "rpi x%x\n",
-                       phba->brd_no, ndlp->vport->vpi, elsiocb->iotag,
-                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
-                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
-
+       lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_ELS,
+                        "0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
+                        "did x%x, nlp_flag x%x, nlp_state x%x, rpi x%x\n",
+                        elsiocb->iotag, elsiocb->iocb.ulpContext,
+                        ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+                        ndlp->nlp_rpi);
        elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
        phba->fc_stat.elsXmitACC++;
        if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR)
@@ -3278,11 +3440,13 @@ lpfc_els_rcv_rps(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                        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);
                }
@@ -3330,21 +3494,16 @@ lpfc_els_rsp_rpl_acc(struct lpfc_vport *vport, uint16_t cmdsize,
        rpl_rsp.port_num_blk.portID = be32_to_cpu(vport->fc_myDID);
        memcpy(&rpl_rsp.port_num_blk.portName, &vport->fc_portname,
            sizeof(struct lpfc_name));
-
        memcpy(pcmd, &rpl_rsp, cmdsize - sizeof(uint32_t));
-
-
        /* Xmit ELS RPL ACC response tag <ulpIoTag> */
-       lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-                       "%d (%d):0120 Xmit ELS RPL ACC response tag x%x "
-                       "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
-                       "rpi x%x\n",
-                       phba->brd_no, vport->vpi, elsiocb->iotag,
-                       elsiocb->iocb.ulpContext, ndlp->nlp_DID,
-                       ndlp->nlp_flag, ndlp->nlp_state, ndlp->nlp_rpi);
-
+       lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
+                        "0120 Xmit ELS RPL ACC response tag x%x "
+                        "xri x%x, did x%x, nlp_flag x%x, nlp_state x%x, "
+                        "rpi x%x\n",
+                        elsiocb->iotag, elsiocb->iocb.ulpContext,
+                        ndlp->nlp_DID, ndlp->nlp_flag, ndlp->nlp_state,
+                        ndlp->nlp_rpi);
        elsiocb->iocb_cmpl = lpfc_cmpl_els_rsp;
-
        phba->fc_stat.elsXmitACC++;
        if (lpfc_sli_issue_iocb(phba, pring, elsiocb, 0) == IOCB_ERROR) {
                lpfc_els_free_iocb(phba, elsiocb);
@@ -3397,7 +3556,6 @@ static int
 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;
@@ -3411,12 +3569,9 @@ lpfc_els_rcv_farp(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
 
        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;
@@ -3464,7 +3619,6 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
        uint32_t *lp;
        IOCB_t *icmd;
        uint32_t cmd, did;
-       struct lpfc_hba *phba = vport->phba;
 
        icmd = &cmdiocb->iocb;
        did = icmd->un.elsreq64.remoteID;
@@ -3473,11 +3627,10 @@ lpfc_els_rcv_farpr(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
 
        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;
 }
@@ -3495,10 +3648,8 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
        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;
@@ -3529,6 +3680,7 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                                         * 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
@@ -3537,8 +3689,6 @@ lpfc_els_rcv_fan(struct lpfc_vport *vport, struct lpfc_iocbq *cmdiocb,
                                }
                        }
 
-                       vport->port_state = LPFC_FLOGI;
-                       lpfc_set_disctmo(vport);
                        lpfc_initial_flogi(vport);
                        return 0;
                }
@@ -3657,13 +3807,10 @@ lpfc_els_timeout_handler(struct lpfc_vport *vport)
                        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);
@@ -3782,6 +3929,7 @@ 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;
@@ -3821,11 +3969,19 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                        goto dropit;
 
                lpfc_nlp_init(vport, ndlp, did);
+               lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
                newnode = 1;
                if ((did & Fabric_DID_MASK) == Fabric_DID_MASK) {
                        ndlp->nlp_type |= NLP_FABRIC;
                }
-               lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
+       }
+       else {
+               if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) {
+                       /* This is simular to the new node path */
+                       lpfc_nlp_get(ndlp);
+                       lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
+                       newnode = 1;
+               }
        }
 
        phba->fc_stat.elsRcvFrame++;
@@ -3838,11 +3994,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                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,
@@ -3856,6 +4010,12 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                        rjt_err = LSRJT_UNABLE_TPC;
                        break;
                }
+
+               shost = lpfc_shost_from_vport(vport);
+               spin_lock_irq(shost->host_lock);
+               ndlp->nlp_flag &= ~NLP_TARGET_REMOVE;
+               spin_unlock_irq(shost->host_lock);
+
                lpfc_disc_state_machine(vport, ndlp, elsiocb,
                                        NLP_EVT_RCV_PLOGI);
 
@@ -3866,9 +4026,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                        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,
@@ -3896,9 +4056,9 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                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,
@@ -3970,7 +4130,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                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,
@@ -3980,7 +4140,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                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,
@@ -3990,7 +4150,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                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,
@@ -4000,7 +4160,7 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                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,
@@ -4011,12 +4171,11 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                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;
        }
 
@@ -4027,19 +4186,17 @@ lpfc_els_unsol_buffer(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
                stat.un.b.lsRjtRsnCodeExp = LSEXP_NOTHING_MORE;
                lpfc_els_rsp_reject(vport, stat.un.lsRjtError, elsiocb, ndlp,
                        NULL);
-               if (newnode)
-                       lpfc_drop_node(vport, ndlp);
        }
 
        return;
 
 dropit:
-       lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-                       "%d (%d):0111 Dropping received ELS cmd "
+       if (vport && !(vport->load_flag & FC_UNLOADING))
+               lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+                       "(%d):0111 Dropping received ELS cmd "
                        "Data: x%x x%x x%x\n",
-                       phba->brd_no, vport ? vport->vpi : 0xffff,
-                       icmd->ulpStatus, icmd->un.ulpWord[4],
-                       icmd->ulpTimeout);
+                       vport->vpi, icmd->ulpStatus,
+                       icmd->un.ulpWord[4], icmd->ulpTimeout);
        phba->fc_stat.elsRcvDrop++;
 }
 
@@ -4151,9 +4308,8 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
                                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);
@@ -4164,13 +4320,12 @@ lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
 
        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) {
@@ -4193,13 +4348,14 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
        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 */
@@ -4214,7 +4370,9 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                default:
                        /* Try to recover from this error */
                        lpfc_mbx_unreg_vpi(vport);
+                       spin_lock_irq(shost->host_lock);
                        vport->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+                       spin_unlock_irq(shost->host_lock);
                        lpfc_initial_fdisc(vport);
                        break;
                }
@@ -4225,14 +4383,21 @@ lpfc_cmpl_reg_new_vport(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
                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);
@@ -4241,28 +4406,31 @@ lpfc_register_new_vport(struct lpfc_hba *phba, struct lpfc_vport *vport,
                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
@@ -4277,11 +4445,10 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        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.
@@ -4298,13 +4465,10 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                /* 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);
 
@@ -4337,7 +4501,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                                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)
@@ -4345,14 +4511,15 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
                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)
 {
@@ -4370,10 +4537,8 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
                                     ELS_CMD_FDISC);
        if (!elsiocb) {
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-
-               lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-                       "%d (%d):0255 Issue FDISC: no IOCB\n",
-                       phba->brd_no, vport->vpi);
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+                                "0255 Issue FDISC: no IOCB\n");
                return 1;
        }
 
@@ -4419,11 +4584,8 @@ lpfc_issue_els_fdisc(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
        if (rc == IOCB_ERROR) {
                lpfc_els_free_iocb(phba, elsiocb);
                lpfc_vport_set_state(vport, FC_VPORT_FAILED);
-
-               lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
-                       "%d (%d):0256 Issue FDISC: Cannot send IOCB\n",
-                       phba->brd_no, vport->vpi);
-
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+                                "0256 Issue FDISC: Cannot send IOCB\n");
                return 1;
        }
        lpfc_vport_set_state(vport, FC_VPORT_INITIALIZING);
@@ -4630,7 +4792,7 @@ lpfc_cmpl_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
        }
 }
 
-int
+static int
 lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
 {
        unsigned long iflags;
@@ -4674,7 +4836,7 @@ lpfc_issue_fabric_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *iocb)
 }
 
 
-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;
@@ -4754,6 +4916,7 @@ void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
 }
 
 
+#if 0
 void lpfc_fabric_abort_flogi(struct lpfc_hba *phba)
 {
        LIST_HEAD(completions);
@@ -4784,5 +4947,6 @@ void lpfc_fabric_abort_flogi(struct lpfc_hba *phba)
                (piocb->iocb_cmpl) (phba, piocb, piocb);
        }
 }
+#endif  /*  0  */