struct hbq_s {
        uint16_t entry_count;     /* Current number of HBQ slots */
+       uint16_t buffer_count;    /* Current number of buffers posted */
        uint32_t next_hbqPutIdx;  /* Index to next HBQ slot to use */
        uint32_t hbqPutIdx;       /* HBQ slot to use */
        uint32_t local_hbqGetIdx; /* Local copy of Get index from Port */
 
        case LPFC_LINK_UP:
        case LPFC_CLEAR_LA:
        case LPFC_HBA_READY:
-               len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - \n");
+               len += snprintf(buf + len, PAGE_SIZE-len, "Link Up - ");
 
                switch (vport->port_state) {
-                       len += snprintf(buf + len, PAGE_SIZE-len,
-                                       "initializing\n");
-                       break;
                case LPFC_LOCAL_CFG_LINK:
                        len += snprintf(buf + len, PAGE_SIZE-len,
                                        "Configuring Link\n");
 
                switch (phba->sysfs_mbox.mbox->mb.mbxCommand) {
                        /* Offline only */
-               case MBX_WRITE_NV:
                case MBX_INIT_LINK:
                case MBX_DOWN_LINK:
                case MBX_CONFIG_LINK:
                                spin_unlock_irq(&phba->hbalock);
                                return -EPERM;
                        }
+               case MBX_WRITE_NV:
+               case MBX_WRITE_VPARMS:
                case MBX_LOAD_SM:
                case MBX_READ_NV:
                case MBX_READ_CONFIG:
 
        raw_index = phba->hbq_get[i];
        getidx = le32_to_cpu(raw_index);
        len +=  snprintf(buf+len, size-len,
-               "entrys:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n",
-               hbqs->entry_count, hbqs->hbqPutIdx, hbqs->next_hbqPutIdx,
-               hbqs->local_hbqGetIdx, getidx);
+               "entrys:%d bufcnt:%d Put:%d nPut:%d localGet:%d hbaGet:%d\n",
+               hbqs->entry_count, hbqs->buffer_count, hbqs->hbqPutIdx,
+               hbqs->next_hbqPutIdx, hbqs->local_hbqGetIdx, getidx);
 
        hbqe = (struct lpfc_hbq_entry *) phba->hbqs[i].hbq_virt;
        for (j=0; j<hbqs->entry_count; j++) {
                len +=  snprintf(buf+len, size-len,
                        "%03d: %08x %04x %05x ", j,
-                       hbqe->bde.addrLow, hbqe->bde.tus.w, hbqe->buffer_tag);
-
+                       le32_to_cpu(hbqe->bde.addrLow),
+                       le32_to_cpu(hbqe->bde.tus.w),
+                       le32_to_cpu(hbqe->buffer_tag));
                i = 0;
                found = 0;
 
                list_for_each_entry(d_buf, &hbqs->hbq_buffer_list, list) {
                        hbq_buf = container_of(d_buf, struct hbq_dmabuf, dbuf);
                        phys = ((uint64_t)hbq_buf->dbuf.phys & 0xffffffff);
-                       if (phys == hbqe->bde.addrLow) {
+                       if (phys == le32_to_cpu(hbqe->bde.addrLow)) {
                                len +=  snprintf(buf+len, size-len,
                                        "Buf%d: %p %06x\n", i,
                                        hbq_buf->dbuf.virt, hbq_buf->tag);
 
 #define NLP_LOGO_SND       0x100       /* sent LOGO request for this entry */
 #define NLP_RNID_SND       0x400       /* sent RNID request for this entry */
 #define NLP_ELS_SND_MASK   0x7e0       /* sent ELS request for this entry */
+#define NLP_DEFER_RM       0x10000     /* Remove this ndlp if no longer used */
 #define NLP_DELAY_TMO      0x20000     /* delay timeout is running for node */
 #define NLP_NPR_2B_DISC    0x40000     /* node is included in num_disc_nodes */
 #define NLP_RCV_PLOGI      0x80000     /* Rcv'ed PLOGI from remote system */
 
 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 */
        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);
+               /* This is the end of the default RPI cleanup logic for this
+                * ndlp. If no other discovery threads are using this ndlp.
+                * we should free all resources associated with it.
+                */
+               lpfc_nlp_not_used(ndlp);
+       }
        return;
 }
 
 
        struct lpfc_vport *vport;
        struct lpfc_hba   *phba;
        struct lpfc_work_evt *evtp;
+       int  put_node;
+       int  put_rport;
 
        rdata = rport->dd_data;
        ndlp = rdata->pnode;
                "rport devlosscb: sid:x%x did:x%x flg:x%x",
                ndlp->nlp_sid, ndlp->nlp_DID, ndlp->nlp_flag);
 
+       /* Don't defer this if we are in the process of deleting the vport
+        * or unloading the driver. The unload will cleanup the node
+        * appropriately we just need to cleanup the ndlp rport info here.
+        */
+       if (vport->load_flag & FC_UNLOADING) {
+               put_node = rdata->pnode != NULL;
+               put_rport = ndlp->rport != NULL;
+               rdata->pnode = NULL;
+               ndlp->rport = NULL;
+               if (put_node)
+                       lpfc_nlp_put(ndlp);
+               if (put_rport)
+                       put_device(&rport->dev);
+               return;
+       }
+
+       if (ndlp->nlp_state == NLP_STE_MAPPED_NODE)
+               return;
+
        evtp = &ndlp->dev_loss_evt;
 
        if (!list_empty(&evtp->evt_listp))
                "rport devlosstmo:did:x%x type:x%x id:x%x",
                ndlp->nlp_DID, ndlp->nlp_type, rport->scsi_target_id);
 
-       if (!(vport->load_flag & FC_UNLOADING) &&
-           ndlp->nlp_state == NLP_STE_MAPPED_NODE)
+       /* Don't defer this if we are in the process of deleting the vport
+        * or unloading the driver. The unload will cleanup the node
+        * appropriately we just need to cleanup the ndlp rport info here.
+        */
+       if (vport->load_flag & FC_UNLOADING) {
+               put_node = rdata->pnode != NULL;
+               put_rport = ndlp->rport != NULL;
+               rdata->pnode = NULL;
+               ndlp->rport = NULL;
+               if (put_node)
+                       lpfc_nlp_put(ndlp);
+               if (put_rport)
+                       put_device(&rport->dev);
+               return;
+       }
+
+       if (ndlp->nlp_state == NLP_STE_MAPPED_NODE)
                return;
 
        if (ndlp->nlp_type & NLP_FABRIC) {
 static void
 lpfc_nlp_remove(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 {
+       struct lpfc_hba  *phba = vport->phba;
        struct lpfc_rport_data *rdata;
+       LPFC_MBOXQ_t *mbox;
+       int rc;
 
        if (ndlp->nlp_flag & NLP_DELAY_TMO) {
                lpfc_cancel_retry_delay_tmo(vport, ndlp);
        }
 
+       if (ndlp->nlp_flag & NLP_DEFER_RM && !ndlp->nlp_rpi) {
+               /* For this case we need to cleanup the default rpi
+                * allocated by the firmware.
+                */
+               if ((mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL))
+                       != NULL) {
+                       rc = lpfc_reg_login(phba, vport->vpi, ndlp->nlp_DID,
+                           (uint8_t *) &vport->fc_sparam, mbox, 0);
+                       if (rc) {
+                               mempool_free(mbox, phba->mbox_mem_pool);
+                       }
+                       else {
+                               mbox->mbox_flag |= LPFC_MBX_IMED_UNREG;
+                               mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
+                               mbox->vport = vport;
+                               mbox->context2 = 0;
+                               rc =lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+                               if (rc == MBX_NOT_FINISHED) {
+                                       mempool_free(mbox, phba->mbox_mem_pool);
+                               }
+                       }
+               }
+       }
+
        lpfc_cleanup_node(vport, ndlp);
 
        /*
 
                struct gff_acc {
                        uint8_t fbits[128];
                } gff_acc;
-#ifdef __BIG_ENDIAN_BITFIELD
 #define FCP_TYPE_FEATURE_OFFSET 7
-#else  /*  __LITTLE_ENDIAN_BITFIELD */
-#define FCP_TYPE_FEATURE_OFFSET 4
-#endif
                struct rff {
                        uint32_t PortId;
                        uint8_t reserved[2];
 #define MBX_KILL_BOARD      0x24
 #define MBX_CONFIG_FARP     0x25
 #define MBX_BEACON          0x2A
-#define MBX_ASYNCEVT_ENABLE 0x33
 #define MBX_HEARTBEAT       0x31
+#define MBX_WRITE_VPARMS    0x32
+#define MBX_ASYNCEVT_ENABLE 0x33
 
 #define MBX_CONFIG_HBQ     0x7C
 #define MBX_LOAD_AREA       0x81
 
 {
        struct lpfc_hba   *phba = vport->phba;
        struct lpfc_nodelist *ndlp, *next_ndlp;
+       int i = 0;
 
        if (phba->link_state > LPFC_LINK_DOWN)
                lpfc_port_link_failure(vport);
                                             NLP_EVT_DEVICE_RM);
        }
 
-       /* At this point, ALL ndlp's should be gone */
+       /* At this point, ALL ndlp's should be gone
+        * because of the previous NLP_EVT_DEVICE_RM.
+        * Lets wait for this to happen, if needed.
+        */
        while (!list_empty(&vport->fc_nodes)) {
 
-               list_for_each_entry_safe(ndlp, next_ndlp, &vport->fc_nodes,
-                       nlp_listp) {
+               if (i++ > 3000) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
-                               "0233 Nodelist x%x not free: %d\n",
-                               ndlp->nlp_DID,
-                               atomic_read(&ndlp->kref.refcount));
-                       lpfc_drop_node(vport, ndlp);
+                               "0233 Nodelist not empty\n");
+                       break;
                }
+
+               /* Wait for any activity on ndlps to settle */
+               msleep(10);
        }
        return;
 }
                for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
                        struct Scsi_Host *shost;
 
+                       if (vports[i]->load_flag & FC_UNLOADING)
+                               continue;
                        shost = lpfc_shost_from_vport(vports[i]);
                        list_for_each_entry_safe(ndlp, next_ndlp,
                                                 &vports[i]->fc_nodes,
        fc_host_supported_speeds(shost) = 0;
        if (phba->lmt & LMT_10Gb)
                fc_host_supported_speeds(shost) |= FC_PORTSPEED_10GBIT;
+       if (phba->lmt & LMT_8Gb)
+               fc_host_supported_speeds(shost) |= FC_PORTSPEED_8GBIT;
        if (phba->lmt & LMT_4Gb)
                fc_host_supported_speeds(shost) |= FC_PORTSPEED_4GBIT;
        if (phba->lmt & LMT_2Gb)
 
        pcmd = (struct lpfc_dmabuf *) cmdiocb->context2;
        lp = (uint32_t *) pcmd->virt;
        sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
+       if (wwn_to_u64(sp->portName.u.wwn) == 0) {
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+                                "0140 PLOGI Reject: invalid nname\n");
+               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+               stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_PNAME;
+               lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+                       NULL);
+               return 0;
+       }
+       if (wwn_to_u64(sp->nodeName.u.wwn) == 0) {
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+                                "0141 PLOGI Reject: invalid pname\n");
+               stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
+               stat.un.b.lsRjtRsnCodeExp = LSEXP_INVALID_NNAME;
+               lpfc_els_rsp_reject(vport, stat.un.lsRjtError, cmdiocb, ndlp,
+                       NULL);
+               return 0;
+       }
        if ((lpfc_check_sparm(vport, ndlp, sp, CLASS3) == 0)) {
                /* Reject this request because invalid parameters */
                stat.un.b.lsRjtRsnCode = LSRJT_UNABLE_TPC;
 
        lp = (uint32_t *) prsp->virt;
        sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
+       if (wwn_to_u64(sp->portName.u.wwn) == 0 ||
+           wwn_to_u64(sp->nodeName.u.wwn) == 0) {
+               lpfc_printf_vlog(vport, KERN_ERR, LOG_ELS,
+                                "0142 PLOGI RSP: Invalid WWN.\n");
+               goto out;
+       }
        if (!lpfc_check_sparm(vport, ndlp, sp, CLASS3))
                goto out;
        /* PLOGI chkparm OK */
                                 "0261 Cannot Register NameServer login\n");
        }
 
-       /* Free this node since the driver cannot login or has the wrong
-          sparm */
-       lpfc_nlp_not_used(ndlp);
+       ndlp->nlp_flag |= NLP_DEFER_RM;
        return NLP_STE_FREED_NODE;
 }
 
 
        irsp = &rspiocb->iocb;
        if (irsp->ulpStatus) {
-               lpfc_nlp_not_used(ndlp);
+               ndlp->nlp_flag |= NLP_DEFER_RM;
                return NLP_STE_FREED_NODE;
        }
        return ndlp->nlp_state;
 
                        list_del(&hbq_buf->dbuf.list);
                        (phba->hbqs[i].hbq_free_buffer)(phba, hbq_buf);
                }
+               phba->hbqs[i].buffer_count = 0;
        }
 }
 
                return 0;
        }
 
-       start = lpfc_hbq_defs[hbqno]->buffer_count;
-       end = count + lpfc_hbq_defs[hbqno]->buffer_count;
+       start = phba->hbqs[hbqno].buffer_count;
+       end = count + start;
        if (end > lpfc_hbq_defs[hbqno]->entry_count) {
                end = lpfc_hbq_defs[hbqno]->entry_count;
        }
                        return 1;
                hbq_buffer->tag = (i | (hbqno << 16));
                if (lpfc_sli_hbq_to_firmware(phba, hbqno, hbq_buffer))
-                       lpfc_hbq_defs[hbqno]->buffer_count++;
+                       phba->hbqs[hbqno].buffer_count++;
                else
                        (phba->hbqs[hbqno].hbq_free_buffer)(phba, hbq_buffer);
        }
        }
        lpfc_printf_log(phba, KERN_ERR, LOG_SLI | LOG_VPORT,
                        "1803 Bad hbq tag. Data: x%x x%x\n",
-                       tag, lpfc_hbq_defs[tag >> 16]->buffer_count);
+                       tag, phba->hbqs[tag >> 16].buffer_count);
        return NULL;
 }
 
        case MBX_LOAD_SM:
        case MBX_READ_NV:
        case MBX_WRITE_NV:
+       case MBX_WRITE_VPARMS:
        case MBX_RUN_BIU_DIAG:
        case MBX_INIT_LINK:
        case MBX_DOWN_LINK: