struct list_head port_list;
        struct lpfc_vport *pport;       /* physical lpfc_vport pointer */
        uint16_t max_vpi;               /* Maximum virtual nports */
-#define LPFC_MAX_VPI 100               /* Max number of VPI supported */
-#define LPFC_MAX_VPORTS (LPFC_MAX_VPI+1)/* Max number of VPorts supported */
+#define LPFC_MAX_VPI 0xFFFF            /* Max number of VPI supported */
        unsigned long *vpi_bmask;       /* vpi allocation table */
 
        /* Data structure used by fabric iocb scheduler */
 
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2007 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2008 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
 
        psli = &phba->sli;
 
+       /* Wait a little for things to settle down, but not
+        * long enough for dev loss timeout to expire.
+        */
        for (i = 0; i < psli->num_rings; i++) {
                pring = &psli->ring[i];
-               /* The linkdown event takes 30 seconds to timeout. */
                while (pring->txcmplq_cnt) {
                        msleep(10);
-                       if (cnt++ > 3000) {
+                       if (cnt++ > 500) {  /* 5 secs */
                                lpfc_printf_log(phba,
                                        KERN_WARNING, LOG_INIT,
                                        "0466 Outstanding IO when "
        spin_lock_irq(&phba->hbalock);
        if (phba->over_temp_state == HBA_OVER_TEMP) {
                spin_unlock_irq(&phba->hbalock);
-               return -EPERM;
+               return -EACCES;
        }
        spin_unlock_irq(&phba->hbalock);
        /* count may include a LF at end of string */
        if (phba->over_temp_state == HBA_OVER_TEMP) {
                sysfs_mbox_idle(phba);
                spin_unlock_irq(&phba->hbalock);
-               return  -EPERM;
+               return  -EACCES;
        }
 
        if (off == 0 &&
                case MBX_DUMP_CONTEXT:
                case MBX_RUN_DIAGS:
                case MBX_RESTART:
-               case MBX_FLASH_WR_ULA:
                case MBX_SET_MASK:
-               case MBX_SET_SLIM:
                case MBX_SET_DEBUG:
                        if (!(vport->fc_flag & FC_OFFLINE_MODE)) {
                                printk(KERN_WARNING "mbox_read:Command 0x%x "
                case MBX_LOAD_EXP_ROM:
                case MBX_BEACON:
                case MBX_DEL_LD_ENTRY:
+               case MBX_SET_VARIABLE:
+               case MBX_WRITE_WWN:
                        break;
                case MBX_READ_SPARM64:
                case MBX_READ_LA:
                        return -EPERM;
                }
 
+               /* If HBA encountered an error attention, allow only DUMP
+                * mailbox command until the HBA is restarted.
+                */
+               if ((phba->pport->stopped) &&
+                       (phba->sysfs_mbox.mbox->mb.mbxCommand
+                               != MBX_DUMP_MEMORY)) {
+                       sysfs_mbox_idle(phba);
+                       spin_unlock_irq(&phba->hbalock);
+                       return -EPERM;
+               }
+
                phba->sysfs_mbox.mbox->vport = vport;
 
                if (phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO) {
                                fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
                        break;
                }
-       }
+       } else
+               fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
 
        spin_unlock_irq(shost->host_lock);
 }
                node_name = wwn_to_u64(phba->fc_fabparam.nodeName.u.wwn);
        else
                /* fabric is local port if there is no F/FL_Port */
-               node_name = wwn_to_u64(vport->fc_nodename.u.wwn);
+               node_name = 0;
 
        spin_unlock_irq(shost->host_lock);
 
 
  *******************************************************************/
 
 /*
- * Fibre Channel SCSI LAN Device Driver CT support
+ * Fibre Channel SCSI LAN Device Driver CT support: FC Generic Services FC-GS
  */
 
 #include <linux/blkdev.h>
        struct lpfc_dmabuf *mp;
        int cnt, i = 0;
 
-       /* We get chucks of FCELSSIZE */
+       /* We get chunks of FCELSSIZE */
        cnt = size > FCELSSIZE ? FCELSSIZE: size;
 
        while (size) {
        case SLI_CTNS_GFF_ID:
                CtReq->CommandResponse.bits.CmdRsp =
                        be16_to_cpu(SLI_CTNS_GFF_ID);
-               CtReq->un.gff.PortId = be32_to_cpu(context);
+               CtReq->un.gff.PortId = cpu_to_be32(context);
                cmpl = lpfc_cmpl_ct_cmd_gff_id;
                break;
 
                vport->ct_flags &= ~FC_CT_RFT_ID;
                CtReq->CommandResponse.bits.CmdRsp =
                    be16_to_cpu(SLI_CTNS_RFT_ID);
-               CtReq->un.rft.PortId = be32_to_cpu(vport->fc_myDID);
+               CtReq->un.rft.PortId = cpu_to_be32(vport->fc_myDID);
                CtReq->un.rft.fcpReg = 1;
                cmpl = lpfc_cmpl_ct_cmd_rft_id;
                break;
                vport->ct_flags &= ~FC_CT_RNN_ID;
                CtReq->CommandResponse.bits.CmdRsp =
                    be16_to_cpu(SLI_CTNS_RNN_ID);
-               CtReq->un.rnn.PortId = be32_to_cpu(vport->fc_myDID);
+               CtReq->un.rnn.PortId = cpu_to_be32(vport->fc_myDID);
                memcpy(CtReq->un.rnn.wwnn,  &vport->fc_nodename,
                       sizeof (struct lpfc_name));
                cmpl = lpfc_cmpl_ct_cmd_rnn_id;
                vport->ct_flags &= ~FC_CT_RSPN_ID;
                CtReq->CommandResponse.bits.CmdRsp =
                    be16_to_cpu(SLI_CTNS_RSPN_ID);
-               CtReq->un.rspn.PortId = be32_to_cpu(vport->fc_myDID);
+               CtReq->un.rspn.PortId = cpu_to_be32(vport->fc_myDID);
                size = sizeof(CtReq->un.rspn.symbname);
                CtReq->un.rspn.len =
                        lpfc_vport_symbolic_port_name(vport,
                /* Implement DA_ID Nameserver request */
                CtReq->CommandResponse.bits.CmdRsp =
                        be16_to_cpu(SLI_CTNS_DA_ID);
-               CtReq->un.da_id.port_id = be32_to_cpu(vport->fc_myDID);
+               CtReq->un.da_id.port_id = cpu_to_be32(vport->fc_myDID);
                cmpl = lpfc_cmpl_ct_cmd_da_id;
                break;
        case SLI_CTNS_RFF_ID:
                vport->ct_flags &= ~FC_CT_RFF_ID;
                CtReq->CommandResponse.bits.CmdRsp =
                    be16_to_cpu(SLI_CTNS_RFF_ID);
-               CtReq->un.rff.PortId = be32_to_cpu(vport->fc_myDID);;
+               CtReq->un.rff.PortId = cpu_to_be32(vport->fc_myDID);;
                CtReq->un.rff.fbits = FC4_FEATURE_INIT;
                CtReq->un.rff.type_code = FC_FCP_DATA;
                cmpl = lpfc_cmpl_ct_cmd_rff_id;
 
  * 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>
                }
                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 &&
                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);
        return 0;
 }
 
-int
+static int
 lpfc_els_free_data(struct lpfc_hba *phba, struct lpfc_dmabuf *buf_ptr1)
 {
        struct lpfc_dmabuf *buf_ptr;
        return 0;
 }
 
-int
+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);
                        "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) {
                                         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 */
 
                /* 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;
        }
 
                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_vlog(ndlp->vport, KERN_INFO, LOG_ELS,
                         "0118 Xmit ELS RPS ACC response tag x%x xri x%x, "
        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;
+       spin_unlock_irq(shost->host_lock);
        lpfc_nlp_put(ndlp);
 
        if (mb->mbxStatus) {
                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;
                }
 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);
                if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT)
                    == MBX_NOT_FINISHED) {
                        mempool_free(mbox, phba->mbox_mem_pool);
+                       spin_lock_irq(shost->host_lock);
                        vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+                       spin_unlock_irq(shost->host_lock);
 
                        lpfc_vport_set_state(vport, FC_VPORT_FAILED);
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
                lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX,
                                 "0254 Register VPI: no memory\n");
 
+               spin_lock_irq(shost->host_lock);
                vport->fc_flag &= ~FC_VPORT_NEEDS_REG_VPI;
+               spin_unlock_irq(shost->host_lock);
                lpfc_nlp_put(ndlp);
        }
 }
                                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)
 
 
        rdata = rport->dd_data;
        ndlp = rdata->pnode;
-
-       if (!ndlp) {
-               if (rport->scsi_target_id != -1) {
-                       printk(KERN_ERR "Cannot find remote node"
-                               " for rport in dev_loss_tmo_callbk x%x\n",
-                               rport->port_id);
-               }
+       if (!ndlp)
                return;
-       }
 
        vport = ndlp->vport;
        phba  = vport->phba;
         * appropriately we just need to cleanup the ndlp rport info here.
         */
        if (vport->load_flag & FC_UNLOADING) {
+               if (ndlp->nlp_sid != NLP_NO_SID) {
+                       /* flush the target */
+                       lpfc_sli_abort_iocb(vport,
+                                       &phba->sli.ring[phba->sli.fcp_ring],
+                                       ndlp->nlp_sid, 0, LPFC_CTX_TGT);
+               }
                put_node = rdata->pnode != NULL;
                put_rport = ndlp->rport != NULL;
                rdata->pnode = NULL;
                lpfc_handle_latt(phba);
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
-               for(i = 0; i < LPFC_MAX_VPORTS; i++) {
+               for(i = 0; i <= phba->max_vpi; i++) {
                        /*
                         * We could have no vports in array if unloading, so if
                         * this happens then just use the pport
                        vport->work_port_events &= ~work_port_events;
                        spin_unlock_irq(&vport->work_port_lock);
                }
-       lpfc_destroy_vport_work_array(vports);
+       lpfc_destroy_vport_work_array(phba, vports);
 
        pring = &phba->sli.ring[LPFC_ELS_RING];
        status = (ha_copy & (HA_RXMASK  << (4*LPFC_ELS_RING)));
 void
 lpfc_cleanup_rpis(struct lpfc_vport *vport, int remove)
 {
+       struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
        struct lpfc_hba  *phba = vport->phba;
        struct lpfc_nodelist *ndlp, *next_ndlp;
        int  rc;
        }
        if (phba->sli3_options & LPFC_SLI3_VPORT_TEARDOWN) {
                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);
        }
 }
 
        spin_unlock_irq(&phba->hbalock);
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
-               for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
+               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
                        /* Issue a LINK DOWN event to all nodes */
                        lpfc_linkdown_port(vports[i]);
                }
-       lpfc_destroy_vport_work_array(vports);
+       lpfc_destroy_vport_work_array(phba, vports);
        /* Clean up any firmware default rpi's */
        mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (mb) {
 
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
-               for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++)
+               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++)
                        lpfc_linkup_port(vports[i]);
-       lpfc_destroy_vport_work_array(vports);
+       lpfc_destroy_vport_work_array(phba, vports);
        if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
                lpfc_issue_clear_la(phba, phba->pport);
 
                vports = lpfc_create_vport_work_array(phba);
                if (vports != NULL)
                        for(i = 0;
-                           i < LPFC_MAX_VPORTS && vports[i] != NULL;
+                           i <= phba->max_vpi && vports[i] != NULL;
                            i++) {
                                if (vports[i]->port_type == LPFC_PHYSICAL_PORT)
                                        continue;
                                                        "Fabric support\n");
                                }
                        }
-               lpfc_destroy_vport_work_array(vports);
+               lpfc_destroy_vport_work_array(phba, vports);
                lpfc_do_scr_ns_plogi(phba, vport);
        }
 
                lpfc_unreg_login(phba, vport->vpi, 0xffff, mbox);
                mbox->vport = vport;
                mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-               rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+               mbox->context1 = NULL;
+               rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
                if (rc == MBX_NOT_FINISHED) {
                        mempool_free(mbox, phba->mbox_mem_pool);
                }
                lpfc_unreg_did(phba, vport->vpi, 0xffffffff, mbox);
                mbox->vport = vport;
                mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-               rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
+               mbox->context1 = NULL;
+               rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
                if (rc == MBX_NOT_FINISHED) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
                                         "1815 Could not issue "
                                mbox->mbox_flag |= LPFC_MBX_IMED_UNREG;
                                mbox->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
                                mbox->vport = vport;
-                               mbox->context2 = 0;
+                               mbox->context2 = NULL;
                                rc =lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT);
                                if (rc == MBX_NOT_FINISHED) {
                                        mempool_free(mbox, phba->mbox_mem_pool);
                clrlaerr = 1;
                break;
 
+       case LPFC_LINK_UP:
+               lpfc_issue_clear_la(phba, vport);
+               /* Drop thru */
        case LPFC_LINK_UNKNOWN:
        case LPFC_WARM_START:
        case LPFC_INIT_START:
        case LPFC_INIT_MBX_CMDS:
        case LPFC_LINK_DOWN:
-       case LPFC_LINK_UP:
        case LPFC_HBA_ERROR:
                lpfc_printf_vlog(vport, KERN_ERR, LOG_DISCOVERY,
                                 "0230 Unexpected timeout, hba link "
 
 #define MBX_DEL_LD_ENTRY    0x1D
 #define MBX_RUN_PROGRAM     0x1E
 #define MBX_SET_MASK        0x20
-#define MBX_SET_SLIM        0x21
+#define MBX_SET_VARIABLE    0x21
 #define MBX_UNREG_D_ID      0x23
 #define MBX_KILL_BOARD      0x24
 #define MBX_CONFIG_FARP     0x25
 #define MBX_REG_VNPID      0x96
 #define MBX_UNREG_VNPID            0x97
 
-#define MBX_FLASH_WR_ULA    0x98
+#define MBX_WRITE_WWN       0x98
 #define MBX_SET_DEBUG       0x99
 #define MBX_LOAD_EXP_ROM    0x9C
 
            (device == PCI_DEVICE_ID_BSMB) ||
            (device == PCI_DEVICE_ID_ZMID) ||
            (device == PCI_DEVICE_ID_ZSMB) ||
+           (device == PCI_DEVICE_ID_SAT_MID) ||
+           (device == PCI_DEVICE_ID_SAT_SMB) ||
            (device == PCI_DEVICE_ID_RFLY))
                return 1;
        else
 
        struct lpfc_sli *psli = &phba->sli;
        struct lpfc_sli_ring *pring;
        struct lpfc_dmabuf *mp, *next_mp;
+       struct lpfc_iocbq *iocb;
+       IOCB_t *cmd = NULL;
+       LIST_HEAD(completions);
        int i;
 
        if (phba->sli3_options & LPFC_SLI3_HBQ_ENABLED)
                }
        }
 
+       spin_lock_irq(&phba->hbalock);
        for (i = 0; i < psli->num_rings; i++) {
                pring = &psli->ring[i];
+
+               /* At this point in time the HBA is either reset or DOA. Either
+                * way, nothing should be on txcmplq as it will NEVER complete.
+                */
+               list_splice_init(&pring->txcmplq, &completions);
+               pring->txcmplq_cnt = 0;
+               spin_unlock_irq(&phba->hbalock);
+
+               while (!list_empty(&completions)) {
+                       iocb = list_get_first(&completions, struct lpfc_iocbq,
+                               list);
+                       cmd = &iocb->iocb;
+                       list_del_init(&iocb->list);
+
+                       if (!iocb->iocb_cmpl)
+                               lpfc_sli_release_iocbq(phba, iocb);
+                       else {
+                               cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
+                               cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
+                               (iocb->iocb_cmpl) (phba, iocb, iocb);
+                       }
+               }
+
                lpfc_sli_abort_iocb_ring(phba, pring);
+               spin_lock_irq(&phba->hbalock);
        }
+       spin_unlock_irq(&phba->hbalock);
 
        return 0;
 }
        }
 }
 
+static void
+lpfc_offline_eratt(struct lpfc_hba *phba)
+{
+       struct lpfc_sli   *psli = &phba->sli;
+
+       spin_lock_irq(&phba->hbalock);
+       psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+       spin_unlock_irq(&phba->hbalock);
+       lpfc_offline_prep(phba);
+
+       lpfc_offline(phba);
+       lpfc_reset_barrier(phba);
+       lpfc_sli_brdreset(phba);
+       lpfc_hba_down_post(phba);
+       lpfc_sli_brdready(phba, HS_MBRDY);
+       lpfc_unblock_mgmt_io(phba);
+       phba->link_state = LPFC_HBA_ERROR;
+       return;
+}
+
 /************************************************************************/
 /*                                                                      */
 /*    lpfc_handle_eratt                                                 */
                vports = lpfc_create_vport_work_array(phba);
                if (vports != NULL)
                        for(i = 0;
-                           i < LPFC_MAX_VPORTS && vports[i] != NULL;
+                           i <= phba->max_vpi && vports[i] != NULL;
                            i++){
                                shost = lpfc_shost_from_vport(vports[i]);
                                spin_lock_irq(shost->host_lock);
                                vports[i]->fc_flag |= FC_ESTABLISH_LINK;
                                spin_unlock_irq(shost->host_lock);
                        }
-               lpfc_destroy_vport_work_array(vports);
+               lpfc_destroy_vport_work_array(phba, vports);
                spin_lock_irq(&phba->hbalock);
                psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
                spin_unlock_irq(&phba->hbalock);
                                          | PCI_VENDOR_ID_EMULEX);
 
                spin_lock_irq(&phba->hbalock);
-               psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
                phba->over_temp_state = HBA_OVER_TEMP;
                spin_unlock_irq(&phba->hbalock);
-               lpfc_offline_prep(phba);
-               lpfc_offline(phba);
-               lpfc_unblock_mgmt_io(phba);
-               phba->link_state = LPFC_HBA_ERROR;
-               lpfc_hba_down_post(phba);
+               lpfc_offline_eratt(phba);
 
        } else {
                /* The if clause above forces this code path when the status
                                sizeof(event_data), (char *) &event_data,
                                SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
 
-               spin_lock_irq(&phba->hbalock);
-               psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
-               spin_unlock_irq(&phba->hbalock);
-               lpfc_offline_prep(phba);
-               lpfc_offline(phba);
-               lpfc_unblock_mgmt_io(phba);
-               phba->link_state = LPFC_HBA_ERROR;
-               lpfc_hba_down_post(phba);
+               lpfc_offline_eratt(phba);
        }
 }
 
        LPFC_MBOXQ_t *pmb;
        volatile uint32_t control;
        struct lpfc_dmabuf *mp;
-       int rc = -ENOMEM;
+       int rc = 0;
 
        pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
-       if (!pmb)
+       if (!pmb) {
+               rc = 1;
                goto lpfc_handle_latt_err_exit;
+       }
 
        mp = kmalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
-       if (!mp)
+       if (!mp) {
+               rc = 2;
                goto lpfc_handle_latt_free_pmb;
+       }
 
        mp->virt = lpfc_mbuf_alloc(phba, 0, &mp->phys);
-       if (!mp->virt)
+       if (!mp->virt) {
+               rc = 3;
                goto lpfc_handle_latt_free_mp;
-
-       rc = -EIO;
+       }
 
        /* Cleanup any outstanding ELS commands */
        lpfc_els_flush_all_cmd(phba);
        pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la;
        pmb->vport = vport;
        rc = lpfc_sli_issue_mbox (phba, pmb, MBX_NOWAIT);
-       if (rc == MBX_NOT_FINISHED)
+       if (rc == MBX_NOT_FINISHED) {
+               rc = 4;
                goto lpfc_handle_latt_free_mbuf;
+       }
 
        /* Clear Link Attention in HA REG */
        spin_lock_irq(&phba->hbalock);
        lpfc_linkdown(phba);
        phba->link_state = LPFC_HBA_ERROR;
 
-       /* The other case is an error from issue_mbox */
-       if (rc == -ENOMEM)
-               lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
-                               "0300 READ_LA: no buffers\n");
+       lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+                    "0300 LATT: Cannot issue READ_LA: Data:%d\n", rc);
 
        return;
 }
                        phba->pport->fc_flag, phba->pport->port_state);
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
-               for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
+               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
                        struct Scsi_Host *shost;
                        shost = lpfc_shost_from_vport(vports[i]);
                        spin_lock_irqsave(shost->host_lock, iflag);
                        vports[i]->fc_flag &= ~FC_ESTABLISH_LINK;
                        spin_unlock_irqrestore(shost->host_lock, iflag);
                }
-       lpfc_destroy_vport_work_array(vports);
+       lpfc_destroy_vport_work_array(phba, vports);
 }
 
 void
 
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
-               for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
+               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
                        struct Scsi_Host *shost;
                        shost = lpfc_shost_from_vport(vports[i]);
                        spin_lock_irq(shost->host_lock);
                                vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
                        spin_unlock_irq(shost->host_lock);
                }
-               lpfc_destroy_vport_work_array(vports);
+               lpfc_destroy_vport_work_array(phba, vports);
 
        lpfc_unblock_mgmt_io(phba);
        return 0;
        /* Issue an unreg_login to all nodes on all vports */
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL) {
-               for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
+               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
                        struct Scsi_Host *shost;
 
                        if (vports[i]->load_flag & FC_UNLOADING)
                        }
                }
        }
-       lpfc_destroy_vport_work_array(vports);
+       lpfc_destroy_vport_work_array(phba, vports);
 
        lpfc_sli_flush_mbox_queue(phba);
 }
        lpfc_stop_phba_timers(phba);
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
-               for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++)
+               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++)
                        lpfc_stop_vport_timers(vports[i]);
-       lpfc_destroy_vport_work_array(vports);
+       lpfc_destroy_vport_work_array(phba, vports);
        lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
                        "0460 Bring Adapter offline\n");
        /* Bring down the SLI Layer and cleanup.  The HBA is offline
        spin_unlock_irq(&phba->hbalock);
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
-               for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
+               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
                        shost = lpfc_shost_from_vport(vports[i]);
                        spin_lock_irq(shost->host_lock);
                        vports[i]->work_port_events = 0;
                        vports[i]->fc_flag |= FC_OFFLINE_MODE;
                        spin_unlock_irq(shost->host_lock);
                }
-       lpfc_destroy_vport_work_array(vports);
+       lpfc_destroy_vport_work_array(phba, vports);
 }
 
 /******************************************************************************
        kfree(vport->vname);
        lpfc_free_sysfs_attr(vport);
 
+       kthread_stop(phba->worker_thread);
+
        fc_remove_host(shost);
        scsi_remove_host(shost);
        lpfc_cleanup(vport);
 
        lpfc_debugfs_terminate(vport);
 
-       kthread_stop(phba->worker_thread);
-
        /* Release the irq reservation */
        free_irq(phba->pcidev->irq, phba);
        if (phba->using_msi)
 
        case MBX_DOWN_LOAD:     /* 0x1C */
        case MBX_DEL_LD_ENTRY:  /* 0x1D */
        case MBX_LOAD_AREA:     /* 0x81 */
-       case MBX_FLASH_WR_ULA:  /* 0x98 */
+       case MBX_WRITE_WWN:     /* 0x98 */
        case MBX_LOAD_EXP_ROM:  /* 0x9C */
                return LPFC_MBOX_TMO_FLASH_CMD;
        }
 
 
  fail_free_hbq_pool:
        lpfc_sli_hbqbuf_free_all(phba);
+       pci_pool_destroy(phba->lpfc_hbq_pool);
  fail_free_nlp_mem_pool:
        mempool_destroy(phba->nlp_mem_pool);
        phba->nlp_mem_pool = NULL;
 
 
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
-               for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
+               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
                        shost = lpfc_shost_from_vport(vports[i]);
                        shost_for_each_device(sdev, shost) {
                                new_queue_depth =
                                                        new_queue_depth);
                        }
                }
-       lpfc_destroy_vport_work_array(vports);
+       lpfc_destroy_vport_work_array(phba, vports);
        atomic_set(&phba->num_rsrc_err, 0);
        atomic_set(&phba->num_cmd_success, 0);
 }
 
        vports = lpfc_create_vport_work_array(phba);
        if (vports != NULL)
-               for(i = 0; i < LPFC_MAX_VPORTS && vports[i] != NULL; i++) {
+               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
                        shost = lpfc_shost_from_vport(vports[i]);
                        shost_for_each_device(sdev, shost) {
                                if (sdev->ordered_tags)
                                                        sdev->queue_depth+1);
                        }
                }
-       lpfc_destroy_vport_work_array(vports);
+       lpfc_destroy_vport_work_array(phba, vports);
        atomic_set(&phba->num_rsrc_err, 0);
        atomic_set(&phba->num_cmd_success, 0);
 }
                (num_bde * sizeof (struct ulp_bde64));
        iocb_cmd->ulpBdeCount = 1;
        iocb_cmd->ulpLe = 1;
-       fcp_cmnd->fcpDl = be32_to_cpu(scsi_bufflen(scsi_cmnd));
+       fcp_cmnd->fcpDl = cpu_to_be32(scsi_bufflen(scsi_cmnd));
        return 0;
 }
 
        piocbq->iocb.ulpContext = pnode->nlp_rpi;
        if (pnode->nlp_fcp_info & NLP_FCP_2_DEVICE)
                piocbq->iocb.ulpFCP2Rcvy = 1;
+       else
+               piocbq->iocb.ulpFCP2Rcvy = 0;
 
        piocbq->iocb.ulpClass = (pnode->nlp_fcp_info & 0x0f);
        piocbq->context1  = lpfc_cmd;
 
        case MBX_DEL_LD_ENTRY:
        case MBX_RUN_PROGRAM:
        case MBX_SET_MASK:
-       case MBX_SET_SLIM:
+       case MBX_SET_VARIABLE:
        case MBX_UNREG_D_ID:
        case MBX_KILL_BOARD:
        case MBX_CONFIG_FARP:
        case MBX_READ_RPI64:
        case MBX_REG_LOGIN64:
        case MBX_READ_LA64:
-       case MBX_FLASH_WR_ULA:
+       case MBX_WRITE_WWN:
        case MBX_SET_DEBUG:
        case MBX_LOAD_EXP_ROM:
        case MBX_ASYNCEVT_ENABLE:
                           <status> */
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                        "0436 Adapter failed to init, "
-                                       "timeout, status reg x%x\n", status);
+                                       "timeout, status reg x%x, "
+                                       "FW Data: A8 x%x AC x%x\n", status,
+                                       readl(phba->MBslimaddr + 0xa8),
+                                       readl(phba->MBslimaddr + 0xac));
                        phba->link_state = LPFC_HBA_ERROR;
                        return -ETIMEDOUT;
                }
                           <status> */
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                        "0437 Adapter failed to init, "
-                                       "chipset, status reg x%x\n", status);
+                                       "chipset, status reg x%x, "
+                                       "FW Data: A8 x%x AC x%x\n", status,
+                                       readl(phba->MBslimaddr + 0xa8),
+                                       readl(phba->MBslimaddr + 0xac));
                        phba->link_state = LPFC_HBA_ERROR;
                        return -EIO;
                }
                /* Adapter failed to init, chipset, status reg <status> */
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "0438 Adapter failed to init, chipset, "
-                               "status reg x%x\n", status);
+                               "status reg x%x, "
+                               "FW Data: A8 x%x AC x%x\n", status,
+                               readl(phba->MBslimaddr + 0xa8),
+                               readl(phba->MBslimaddr + 0xac));
                phba->link_state = LPFC_HBA_ERROR;
                return -EIO;
        }
        uint32_t status, evtctr;
        uint32_t ha_copy;
        int i;
+       unsigned long timeout;
        unsigned long drvr_flag = 0;
        volatile uint32_t word0, ldata;
        void __iomem *to_slim;
        }
 
        wmb();
-       /* interrupt board to doit right away */
-       writel(CA_MBATT, phba->CAregaddr);
-       readl(phba->CAregaddr); /* flush */
 
        switch (flag) {
        case MBX_NOWAIT:
-               /* Don't wait for it to finish, just return */
+               /* Set up reference to mailbox command */
                psli->mbox_active = pmbox;
+               /* Interrupt board to do it */
+               writel(CA_MBATT, phba->CAregaddr);
+               readl(phba->CAregaddr); /* flush */
+               /* Don't wait for it to finish, just return */
                break;
 
        case MBX_POLL:
+               /* Set up null reference to mailbox command */
                psli->mbox_active = NULL;
+               /* Interrupt board to do it */
+               writel(CA_MBATT, phba->CAregaddr);
+               readl(phba->CAregaddr); /* flush */
+
                if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
                        /* First read mbox status word */
                        word0 = *((volatile uint32_t *)&phba->slim2p->mbx);
 
                /* Read the HBA Host Attention Register */
                ha_copy = readl(phba->HAregaddr);
-
-               i = lpfc_mbox_tmo_val(phba, mb->mbxCommand);
-               i *= 1000; /* Convert to ms */
-
+               timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
+                                                            mb->mbxCommand) *
+                                          1000) + jiffies;
+               i = 0;
                /* Wait for command to complete */
                while (((word0 & OWN_CHIP) == OWN_CHIP) ||
                       (!(ha_copy & HA_MBATT) &&
                        (phba->link_state > LPFC_WARM_START))) {
-                       if (i-- <= 0) {
+                       if (time_after(jiffies, timeout)) {
                                psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
                                spin_unlock_irqrestore(&phba->hbalock,
                                                       drvr_flag);
                            && (evtctr != psli->slistat.mbox_event))
                                break;
 
-                       spin_unlock_irqrestore(&phba->hbalock,
-                                              drvr_flag);
-
-                       msleep(1);
-
-                       spin_lock_irqsave(&phba->hbalock, drvr_flag);
+                       if (i++ > 10) {
+                               spin_unlock_irqrestore(&phba->hbalock,
+                                                      drvr_flag);
+                               msleep(1);
+                               spin_lock_irqsave(&phba->hbalock, drvr_flag);
+                       }
 
                        if (psli->sli_flag & LPFC_SLI2_ACTIVE) {
                                /* First copy command data */
        if (evt_code == ASYNC_TEMP_WARN) {
                temp_event_data.event_code = LPFC_THRESHOLD_TEMP;
                lpfc_printf_log(phba,
-                               KERN_WARNING,
+                               KERN_ERR,
                                LOG_TEMP,
                                "0347 Adapter is very hot, please take "
                                "corrective action. temperature : %d Celsius\n",
        if (evt_code == ASYNC_TEMP_SAFE) {
                temp_event_data.event_code = LPFC_NORMAL_TEMP;
                lpfc_printf_log(phba,
-                               KERN_INFO,
+                               KERN_ERR,
                                LOG_TEMP,
                                "0340 Adapter temperature is OK now. "
                                "temperature : %d Celsius\n",
                }
 
                if (work_ha_copy & HA_ERATT) {
-                       phba->link_state = LPFC_HBA_ERROR;
                        /*
                         * There was a link/board error.  Read the
                         * status register to retrieve the error event
                                 * Stray Mailbox Interrupt, mbxCommand <cmd>
                                 * mbxStatus <status>
                                 */
-                               lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX |
+                               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX |
                                                LOG_SLI,
                                                "(%d):0304 Stray Mailbox "
                                                "Interrupt mbxCommand x%x "
                                                (vport ? vport->vpi : 0),
                                                pmbox->mbxCommand,
                                                pmbox->mbxStatus);
-                       }
-                       phba->last_completion_time = jiffies;
-                       del_timer_sync(&phba->sli.mbox_tmo);
-
-                       phba->sli.mbox_active = NULL;
-                       if (pmb->mbox_cmpl) {
-                               lpfc_sli_pcimem_bcopy(mbox, pmbox,
-                                                     MAILBOX_CMD_SIZE);
-                       }
-                       if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) {
-                               pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG;
+                               /* clear mailbox attention bit */
+                               work_ha_copy &= ~HA_MBATT;
+                       } else {
+                               phba->last_completion_time = jiffies;
+                               del_timer(&phba->sli.mbox_tmo);
 
-                               lpfc_debugfs_disc_trc(vport,
-                                       LPFC_DISC_TRC_MBOX_VPORT,
-                                       "MBOX dflt rpi: : status:x%x rpi:x%x",
-                                       (uint32_t)pmbox->mbxStatus,
-                                       pmbox->un.varWords[0], 0);
-
-                               if ( !pmbox->mbxStatus) {
-                                       mp = (struct lpfc_dmabuf *)
-                                               (pmb->context1);
-                                       ndlp = (struct lpfc_nodelist *)
-                                               pmb->context2;
-
-                                       /* Reg_LOGIN of dflt RPI was successful.
-                                        * new lets get rid of the RPI using the
-                                        * same mbox buffer.
-                                        */
-                                       lpfc_unreg_login(phba, vport->vpi,
-                                               pmbox->un.varWords[0], pmb);
-                                       pmb->mbox_cmpl = lpfc_mbx_cmpl_dflt_rpi;
-                                       pmb->context1 = mp;
-                                       pmb->context2 = ndlp;
-                                       pmb->vport = vport;
-                                       spin_lock(&phba->hbalock);
-                                       phba->sli.sli_flag &=
-                                               ~LPFC_SLI_MBOX_ACTIVE;
-                                       spin_unlock(&phba->hbalock);
-                                       goto send_current_mbox;
+                               phba->sli.mbox_active = NULL;
+                               if (pmb->mbox_cmpl) {
+                                       lpfc_sli_pcimem_bcopy(mbox, pmbox,
+                                                       MAILBOX_CMD_SIZE);
+                               }
+                               if (pmb->mbox_flag & LPFC_MBX_IMED_UNREG) {
+                                       pmb->mbox_flag &= ~LPFC_MBX_IMED_UNREG;
+
+                                       lpfc_debugfs_disc_trc(vport,
+                                               LPFC_DISC_TRC_MBOX_VPORT,
+                                               "MBOX dflt rpi: : "
+                                               "status:x%x rpi:x%x",
+                                               (uint32_t)pmbox->mbxStatus,
+                                               pmbox->un.varWords[0], 0);
+
+                                       if (!pmbox->mbxStatus) {
+                                               mp = (struct lpfc_dmabuf *)
+                                                       (pmb->context1);
+                                               ndlp = (struct lpfc_nodelist *)
+                                                       pmb->context2;
+
+                                               /* Reg_LOGIN of dflt RPI was
+                                                * successful. new lets get
+                                                * rid of the RPI using the
+                                                * same mbox buffer.
+                                                */
+                                               lpfc_unreg_login(phba,
+                                                       vport->vpi,
+                                                       pmbox->un.varWords[0],
+                                                       pmb);
+                                               pmb->mbox_cmpl =
+                                                       lpfc_mbx_cmpl_dflt_rpi;
+                                               pmb->context1 = mp;
+                                               pmb->context2 = ndlp;
+                                               pmb->vport = vport;
+                                               spin_lock(&phba->hbalock);
+                                               phba->sli.sli_flag &=
+                                                       ~LPFC_SLI_MBOX_ACTIVE;
+                                               spin_unlock(&phba->hbalock);
+                                               goto send_current_mbox;
+                                       }
                                }
+                               spin_lock(&phba->pport->work_port_lock);
+                               phba->pport->work_port_events &=
+                                       ~WORKER_MBOX_TMO;
+                               spin_unlock(&phba->pport->work_port_lock);
+                               lpfc_mbox_cmpl_put(phba, pmb);
                        }
-                       spin_lock(&phba->pport->work_port_lock);
-                       phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
-                       spin_unlock(&phba->pport->work_port_lock);
-                       lpfc_mbox_cmpl_put(phba, pmb);
                }
                if ((work_ha_copy & HA_MBATT) &&
                    (phba->sli.mbox_active == NULL)) {
 
        struct lpfc_vport *port_iterator;
        struct lpfc_vport **vports;
        int index = 0;
-       vports = kzalloc(LPFC_MAX_VPORTS * sizeof(struct lpfc_vport *),
+       vports = kzalloc((phba->max_vpi + 1) * sizeof(struct lpfc_vport *),
                         GFP_KERNEL);
        if (vports == NULL)
                return NULL;
 }
 
 void
-lpfc_destroy_vport_work_array(struct lpfc_vport **vports)
+lpfc_destroy_vport_work_array(struct lpfc_hba *phba, struct lpfc_vport **vports)
 {
        int i;
        if (vports == NULL)
                return;
-       for (i=0; vports[i] != NULL && i < LPFC_MAX_VPORTS; i++)
+       for (i=0; vports[i] != NULL && i <= phba->max_vpi; i++)
                scsi_host_put(lpfc_shost_from_vport(vports[i]));
        kfree(vports);
 }
 
 int lpfc_vport_getinfo(struct Scsi_Host *, struct vport_info *);
 int lpfc_vport_tgt_remove(struct Scsi_Host *, uint, uint);
 struct lpfc_vport **lpfc_create_vport_work_array(struct lpfc_hba *);
-void lpfc_destroy_vport_work_array(struct lpfc_vport **);
+void lpfc_destroy_vport_work_array(struct lpfc_hba *, struct lpfc_vport **);
 
 /*
  *  queuecommand  VPORT-specific return codes. Specified in  the host byte code.