[SCSI] qla1280: Drop host_lock while requesting firmware
[safe/jmp/linux-2.6] / drivers / scsi / lpfc / lpfc_init.c
index fc67cc6..b8eb1b6 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/pci.h>
 #include <linux/spinlock.h>
 #include <linux/ctype.h>
+#include <linux/aer.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
@@ -211,7 +212,7 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
                goto out_free_mbox;
 
        do {
-               lpfc_dump_mem(phba, pmb, offset);
+               lpfc_dump_mem(phba, pmb, offset, DMP_REGION_VPD);
                rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
 
                if (rc != MBX_SUCCESS) {
@@ -425,6 +426,9 @@ lpfc_config_port_post(struct lpfc_hba *phba)
                return -EIO;
        }
 
+       /* Check if the port is disabled */
+       lpfc_sli_read_link_ste(phba);
+
        /* Reset the DFT_HBA_Q_DEPTH to the max xri  */
        if (phba->cfg_hba_queue_depth > (mb->un.varRdConfig.max_xri+1))
                phba->cfg_hba_queue_depth =
@@ -524,27 +528,46 @@ lpfc_config_port_post(struct lpfc_hba *phba)
        /* Set up error attention (ERATT) polling timer */
        mod_timer(&phba->eratt_poll, jiffies + HZ * LPFC_ERATT_POLL_INTERVAL);
 
-       lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
-       pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
-       lpfc_set_loopback_flag(phba);
-       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
-       if (rc != MBX_SUCCESS) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+       if (phba->hba_flag & LINK_DISABLED) {
+               lpfc_printf_log(phba,
+                       KERN_ERR, LOG_INIT,
+                       "2598 Adapter Link is disabled.\n");
+               lpfc_down_link(phba, pmb);
+               pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+               if ((rc != MBX_SUCCESS) && (rc != MBX_BUSY)) {
+                       lpfc_printf_log(phba,
+                       KERN_ERR, LOG_INIT,
+                       "2599 Adapter failed to issue DOWN_LINK"
+                       " mbox command rc 0x%x\n", rc);
+
+                       mempool_free(pmb, phba->mbox_mem_pool);
+                       return -EIO;
+               }
+       } else {
+               lpfc_init_link(phba, pmb, phba->cfg_topology,
+                       phba->cfg_link_speed);
+               pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+               lpfc_set_loopback_flag(phba);
+               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
+               if (rc != MBX_SUCCESS) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "0454 Adapter failed to init, mbxCmd x%x "
                                "INIT_LINK, mbxStatus x%x\n",
                                mb->mbxCommand, mb->mbxStatus);
 
-               /* Clear all interrupt enable conditions */
-               writel(0, phba->HCregaddr);
-               readl(phba->HCregaddr); /* flush */
-               /* Clear all pending interrupts */
-               writel(0xffffffff, phba->HAregaddr);
-               readl(phba->HAregaddr); /* flush */
+                       /* Clear all interrupt enable conditions */
+                       writel(0, phba->HCregaddr);
+                       readl(phba->HCregaddr); /* flush */
+                       /* Clear all pending interrupts */
+                       writel(0xffffffff, phba->HAregaddr);
+                       readl(phba->HAregaddr); /* flush */
 
-               phba->link_state = LPFC_HBA_ERROR;
-               if (rc != MBX_BUSY)
-                       mempool_free(pmb, phba->mbox_mem_pool);
-               return -EIO;
+                       phba->link_state = LPFC_HBA_ERROR;
+                       if (rc != MBX_BUSY)
+                               mempool_free(pmb, phba->mbox_mem_pool);
+                       return -EIO;
+               }
        }
        /* MBOX buffer will be freed in mbox compl */
        pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
@@ -558,7 +581,7 @@ lpfc_config_port_post(struct lpfc_hba *phba)
                                KERN_ERR,
                                LOG_INIT,
                                "0456 Adapter failed to issue "
-                               "ASYNCEVT_ENABLE mbox status x%x \n.",
+                               "ASYNCEVT_ENABLE mbox status x%x\n",
                                rc);
                mempool_free(pmb, phba->mbox_mem_pool);
        }
@@ -572,7 +595,7 @@ lpfc_config_port_post(struct lpfc_hba *phba)
 
        if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0435 Adapter failed "
-                               "to get Option ROM version status x%x\n.", rc);
+                               "to get Option ROM version status x%x\n", rc);
                mempool_free(pmb, phba->mbox_mem_pool);
        }
 
@@ -623,7 +646,7 @@ lpfc_hba_down_prep(struct lpfc_hba *phba)
  * down the SLI Layer.
  *
  * Return codes
- *   0 - sucess.
+ *   0 - success.
  *   Any other value - error.
  **/
 static int
@@ -678,7 +701,7 @@ lpfc_hba_down_post_s3(struct lpfc_hba *phba)
  * down the SLI Layer.
  *
  * Return codes
- *   0 - sucess.
+ *   0 - success.
  *   Any other value - error.
  **/
 static int
@@ -733,7 +756,7 @@ lpfc_hba_down_post_s4(struct lpfc_hba *phba)
  * uninitialization after the HBA is reset when bring down the SLI Layer.
  *
  * Return codes
- *   0 - sucess.
+ *   0 - success.
  *   Any other value - error.
  **/
 int
@@ -830,12 +853,19 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
 void
 lpfc_hb_timeout_handler(struct lpfc_hba *phba)
 {
+       struct lpfc_vport **vports;
        LPFC_MBOXQ_t *pmboxq;
        struct lpfc_dmabuf *buf_ptr;
-       int retval;
+       int retval, i;
        struct lpfc_sli *psli = &phba->sli;
        LIST_HEAD(completions);
 
+       vports = lpfc_create_vport_work_array(phba);
+       if (vports != NULL)
+               for (i = 0; i <= phba->max_vports && vports[i] != NULL; i++)
+                       lpfc_rcv_seq_check_edtov(vports[i]);
+       lpfc_destroy_vport_work_array(phba, vports);
+
        if ((phba->link_state == LPFC_HBA_ERROR) ||
                (phba->pport->load_flag & FC_UNLOADING) ||
                (phba->pport->fc_flag & FC_OFFLINE_MODE))
@@ -1232,7 +1262,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
  * routine from the API jump table function pointer from the lpfc_hba struct.
  *
  * Return codes
- *   0 - sucess.
+ *   0 - success.
  *   Any other value - error.
  **/
 void
@@ -1499,10 +1529,10 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
        int GE = 0;
        int oneConnect = 0; /* default is not a oneConnect */
        struct {
-               char * name;
-               int    max_speed;
-               char * bus;
-       } m = {"<Unknown>", 0, ""};
+               char *name;
+               char *bus;
+               char *function;
+       } m = {"<Unknown>", "", ""};
 
        if (mdp && mdp[0] != '\0'
                && descp && descp[0] != '\0')
@@ -1523,132 +1553,155 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
 
        switch (dev_id) {
        case PCI_DEVICE_ID_FIREFLY:
-               m = (typeof(m)){"LP6000", max_speed, "PCI"};
+               m = (typeof(m)){"LP6000", "PCI", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_SUPERFLY:
                if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3)
-                       m = (typeof(m)){"LP7000", max_speed,  "PCI"};
+                       m = (typeof(m)){"LP7000", "PCI",
+                                       "Fibre Channel Adapter"};
                else
-                       m = (typeof(m)){"LP7000E", max_speed, "PCI"};
+                       m = (typeof(m)){"LP7000E", "PCI",
+                                       "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_DRAGONFLY:
-               m = (typeof(m)){"LP8000", max_speed, "PCI"};
+               m = (typeof(m)){"LP8000", "PCI",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_CENTAUR:
                if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID)
-                       m = (typeof(m)){"LP9002", max_speed, "PCI"};
+                       m = (typeof(m)){"LP9002", "PCI",
+                                       "Fibre Channel Adapter"};
                else
-                       m = (typeof(m)){"LP9000", max_speed, "PCI"};
+                       m = (typeof(m)){"LP9000", "PCI",
+                                       "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_RFLY:
-               m = (typeof(m)){"LP952", max_speed, "PCI"};
+               m = (typeof(m)){"LP952", "PCI",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_PEGASUS:
-               m = (typeof(m)){"LP9802", max_speed, "PCI-X"};
+               m = (typeof(m)){"LP9802", "PCI-X",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_THOR:
-               m = (typeof(m)){"LP10000", max_speed, "PCI-X"};
+               m = (typeof(m)){"LP10000", "PCI-X",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_VIPER:
-               m = (typeof(m)){"LPX1000", max_speed,  "PCI-X"};
+               m = (typeof(m)){"LPX1000",  "PCI-X",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_PFLY:
-               m = (typeof(m)){"LP982", max_speed, "PCI-X"};
+               m = (typeof(m)){"LP982", "PCI-X",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_TFLY:
-               m = (typeof(m)){"LP1050", max_speed, "PCI-X"};
+               m = (typeof(m)){"LP1050", "PCI-X",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_HELIOS:
-               m = (typeof(m)){"LP11000", max_speed, "PCI-X2"};
+               m = (typeof(m)){"LP11000", "PCI-X2",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_HELIOS_SCSP:
-               m = (typeof(m)){"LP11000-SP", max_speed, "PCI-X2"};
+               m = (typeof(m)){"LP11000-SP", "PCI-X2",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_HELIOS_DCSP:
-               m = (typeof(m)){"LP11002-SP", max_speed, "PCI-X2"};
+               m = (typeof(m)){"LP11002-SP",  "PCI-X2",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_NEPTUNE:
-               m = (typeof(m)){"LPe1000", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe1000", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_NEPTUNE_SCSP:
-               m = (typeof(m)){"LPe1000-SP", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe1000-SP", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_NEPTUNE_DCSP:
-               m = (typeof(m)){"LPe1002-SP", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe1002-SP", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_BMID:
-               m = (typeof(m)){"LP1150", max_speed, "PCI-X2"};
+               m = (typeof(m)){"LP1150", "PCI-X2", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_BSMB:
-               m = (typeof(m)){"LP111", max_speed, "PCI-X2"};
+               m = (typeof(m)){"LP111", "PCI-X2", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_ZEPHYR:
-               m = (typeof(m)){"LPe11000", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe11000", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_ZEPHYR_SCSP:
-               m = (typeof(m)){"LPe11000", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe11000", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_ZEPHYR_DCSP:
-               m = (typeof(m)){"LP2105", max_speed, "PCIe"};
+               m = (typeof(m)){"LP2105", "PCIe", "FCoE Adapter"};
                GE = 1;
                break;
        case PCI_DEVICE_ID_ZMID:
-               m = (typeof(m)){"LPe1150", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe1150", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_ZSMB:
-               m = (typeof(m)){"LPe111", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe111", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_LP101:
-               m = (typeof(m)){"LP101", max_speed, "PCI-X"};
+               m = (typeof(m)){"LP101", "PCI-X", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_LP10000S:
-               m = (typeof(m)){"LP10000-S", max_speed, "PCI"};
+               m = (typeof(m)){"LP10000-S", "PCI", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_LP11000S:
-               m = (typeof(m)){"LP11000-S", max_speed,
-                       "PCI-X2"};
+               m = (typeof(m)){"LP11000-S", "PCI-X2", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_LPE11000S:
-               m = (typeof(m)){"LPe11000-S", max_speed,
-                       "PCIe"};
+               m = (typeof(m)){"LPe11000-S", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_SAT:
-               m = (typeof(m)){"LPe12000", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe12000", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_SAT_MID:
-               m = (typeof(m)){"LPe1250", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe1250", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_SAT_SMB:
-               m = (typeof(m)){"LPe121", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe121", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_SAT_DCSP:
-               m = (typeof(m)){"LPe12002-SP", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe12002-SP", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_SAT_SCSP:
-               m = (typeof(m)){"LPe12000-SP", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe12000-SP", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_SAT_S:
-               m = (typeof(m)){"LPe12000-S", max_speed, "PCIe"};
+               m = (typeof(m)){"LPe12000-S", "PCIe", "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_HORNET:
-               m = (typeof(m)){"LP21000", max_speed, "PCIe"};
+               m = (typeof(m)){"LP21000", "PCIe", "FCoE Adapter"};
                GE = 1;
                break;
        case PCI_DEVICE_ID_PROTEUS_VF:
-               m = (typeof(m)) {"LPev12000", max_speed, "PCIe IOV"};
+               m = (typeof(m)){"LPev12000", "PCIe IOV",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_PROTEUS_PF:
-               m = (typeof(m)) {"LPev12000", max_speed, "PCIe IOV"};
+               m = (typeof(m)){"LPev12000", "PCIe IOV",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_PROTEUS_S:
-               m = (typeof(m)) {"LPemv12002-S", max_speed, "PCIe IOV"};
+               m = (typeof(m)){"LPemv12002-S", "PCIe IOV",
+                               "Fibre Channel Adapter"};
                break;
        case PCI_DEVICE_ID_TIGERSHARK:
                oneConnect = 1;
-               m = (typeof(m)) {"OCe10100-F", max_speed, "PCIe"};
+               m = (typeof(m)){"OCe10100", "PCIe", "FCoE"};
+               break;
+       case PCI_DEVICE_ID_TOMCAT:
+               oneConnect = 1;
+               m = (typeof(m)){"OCe11100", "PCIe", "FCoE"};
+               break;
+       case PCI_DEVICE_ID_FALCON:
+               m = (typeof(m)){"LPSe12002-ML1-E", "PCIe",
+                               "EmulexSecure Fibre"};
                break;
        default:
-               m = (typeof(m)){ NULL };
+               m = (typeof(m)){"Unknown", "", ""};
                break;
        }
 
@@ -1660,17 +1713,14 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
        if (descp && descp[0] == '\0') {
                if (oneConnect)
                        snprintf(descp, 255,
-                               "Emulex OneConnect %s, FCoE Initiator, Port %s",
-                               m.name,
+                               "Emulex OneConnect %s, %s Initiator, Port %s",
+                               m.name, m.function,
                                phba->Port);
                else
                        snprintf(descp, 255,
                                "Emulex %s %d%s %s %s",
-                               m.name, m.max_speed,
-                               (GE) ? "GE" : "Gb",
-                               m.bus,
-                               (GE) ? "FCoE Adapter" :
-                                       "Fibre Channel Adapter");
+                               m.name, max_speed, (GE) ? "GE" : "Gb",
+                               m.bus, m.function);
        }
 }
 
@@ -2133,6 +2183,8 @@ lpfc_online(struct lpfc_hba *phba)
                        vports[i]->fc_flag &= ~FC_OFFLINE_MODE;
                        if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED)
                                vports[i]->fc_flag |= FC_VPORT_NEEDS_REG_VPI;
+                       if (phba->sli_rev == LPFC_SLI_REV4)
+                               vports[i]->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
                        spin_unlock_irq(shost->host_lock);
                }
                lpfc_destroy_vport_work_array(phba, vports);
@@ -2193,7 +2245,7 @@ lpfc_offline_prep(struct lpfc_hba * phba)
 
                        if (vports[i]->load_flag & FC_UNLOADING)
                                continue;
-                       vports[i]->vfi_state &= ~LPFC_VFI_REGISTERED;
+                       vports[i]->vpi_state &= ~LPFC_VPI_REGISTERED;
                        shost = lpfc_shost_from_vport(vports[i]);
                        list_for_each_entry_safe(ndlp, next_ndlp,
                                                 &vports[i]->fc_nodes,
@@ -2284,6 +2336,7 @@ lpfc_scsi_free(struct lpfc_hba *phba)
 
        spin_lock_irq(&phba->hbalock);
        /* Release all the lpfc_scsi_bufs maintained by this host. */
+       spin_lock(&phba->scsi_buf_list_lock);
        list_for_each_entry_safe(sb, sb_next, &phba->lpfc_scsi_buf_list, list) {
                list_del(&sb->list);
                pci_pool_free(phba->lpfc_scsi_dma_buf_pool, sb->data,
@@ -2291,6 +2344,7 @@ lpfc_scsi_free(struct lpfc_hba *phba)
                kfree(sb);
                phba->total_scsi_bufs--;
        }
+       spin_unlock(&phba->scsi_buf_list_lock);
 
        /* Release all the lpfc_iocbq entries maintained by this host. */
        list_for_each_entry_safe(io, io_next, &phba->lpfc_iocb_list, list) {
@@ -2298,9 +2352,7 @@ lpfc_scsi_free(struct lpfc_hba *phba)
                kfree(io);
                phba->total_iocbq_bufs--;
        }
-
        spin_unlock_irq(&phba->hbalock);
-
        return 0;
 }
 
@@ -2384,7 +2436,7 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev)
        vport->els_tmofunc.function = lpfc_els_timeout;
        vport->els_tmofunc.data = (unsigned long)vport;
 
-       error = scsi_add_host(shost, dev);
+       error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);
        if (error)
                goto out_put_shost;
 
@@ -2675,6 +2727,63 @@ lpfc_sli_remove_dflt_fcf(struct lpfc_hba *phba)
 }
 
 /**
+ * lpfc_sli4_fw_cfg_check - Read the firmware config and verify FCoE support
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This function uses the QUERY_FW_CFG mailbox command to determine if the
+ * firmware loaded supports FCoE. A return of zero indicates that the mailbox
+ * was successful and the firmware supports FCoE. Any other return indicates
+ * a error. It is assumed that this function will be called before interrupts
+ * are enabled.
+ **/
+static int
+lpfc_sli4_fw_cfg_check(struct lpfc_hba *phba)
+{
+       int rc = 0;
+       LPFC_MBOXQ_t *mboxq;
+       struct lpfc_mbx_query_fw_cfg *query_fw_cfg;
+       uint32_t length;
+       uint32_t shdr_status, shdr_add_status;
+
+       mboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+       if (!mboxq) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "2621 Failed to allocate mbox for "
+                               "query firmware config cmd\n");
+               return -ENOMEM;
+       }
+       query_fw_cfg = &mboxq->u.mqe.un.query_fw_cfg;
+       length = (sizeof(struct lpfc_mbx_query_fw_cfg) -
+                 sizeof(struct lpfc_sli4_cfg_mhdr));
+       lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+                        LPFC_MBOX_OPCODE_QUERY_FW_CFG,
+                        length, LPFC_SLI4_MBX_EMBED);
+       rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+       /* The IOCTL status is embedded in the mailbox subheader. */
+       shdr_status = bf_get(lpfc_mbox_hdr_status,
+                            &query_fw_cfg->header.cfg_shdr.response);
+       shdr_add_status = bf_get(lpfc_mbox_hdr_add_status,
+                                &query_fw_cfg->header.cfg_shdr.response);
+       if (shdr_status || shdr_add_status || rc != MBX_SUCCESS) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "2622 Query Firmware Config failed "
+                               "mbx status x%x, status x%x add_status x%x\n",
+                               rc, shdr_status, shdr_add_status);
+               return -EINVAL;
+       }
+       if (!bf_get(lpfc_function_mode_fcoe_i, query_fw_cfg)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+                               "2623 FCoE Function not supported by firmware. "
+                               "Function mode = %08x\n",
+                               query_fw_cfg->function_mode);
+               return -EINVAL;
+       }
+       if (rc != MBX_TIMEOUT)
+               mempool_free(mboxq, phba->mbox_mem_pool);
+       return 0;
+}
+
+/**
  * lpfc_sli4_parse_latt_fault - Parse sli4 link-attention link fault code
  * @phba: pointer to lpfc hba data structure.
  * @acqe_link: pointer to the async link completion queue entry.
@@ -2807,6 +2916,7 @@ lpfc_sli4_async_link_evt(struct lpfc_hba *phba,
        att_type = lpfc_sli4_parse_latt_type(phba, acqe_link);
        if (att_type != AT_LINK_DOWN && att_type != AT_LINK_UP)
                return;
+       phba->fcoe_eventtag = acqe_link->event_tag;
        pmb = (LPFC_MBOXQ_t *)mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
        if (!pmb) {
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
@@ -2893,57 +3003,87 @@ lpfc_sli4_async_fcoe_evt(struct lpfc_hba *phba,
 {
        uint8_t event_type = bf_get(lpfc_acqe_fcoe_event_type, acqe_fcoe);
        int rc;
+       struct lpfc_vport *vport;
+       struct lpfc_nodelist *ndlp;
+       struct Scsi_Host  *shost;
+       uint32_t link_state;
 
+       phba->fc_eventTag = acqe_fcoe->event_tag;
+       phba->fcoe_eventtag = acqe_fcoe->event_tag;
        switch (event_type) {
        case LPFC_FCOE_EVENT_TYPE_NEW_FCF:
                lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-                       "2546 New FCF found index 0x%x tag 0x%x \n",
-                       acqe_fcoe->fcf_index,
+                       "2546 New FCF found index 0x%x tag 0x%x\n",
+                       acqe_fcoe->index,
                        acqe_fcoe->event_tag);
                /*
-                * If the current FCF is in discovered state,
-                * do nothing.
+                * If the current FCF is in discovered state, or
+                * FCF discovery is in progress do nothing.
                 */
                spin_lock_irq(&phba->hbalock);
-               if (phba->fcf.fcf_flag & FCF_DISCOVERED) {
+               if ((phba->fcf.fcf_flag & FCF_DISCOVERED) ||
+                  (phba->hba_flag & FCF_DISC_INPROGRESS)) {
                        spin_unlock_irq(&phba->hbalock);
                        break;
                }
                spin_unlock_irq(&phba->hbalock);
 
                /* Read the FCF table and re-discover SAN. */
-               rc = lpfc_sli4_read_fcf_record(phba,
-                       LPFC_FCOE_FCF_GET_FIRST);
+               rc = lpfc_sli4_read_fcf_record(phba, LPFC_FCOE_FCF_GET_FIRST);
                if (rc)
                        lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-                               "2547 Read FCF record failed 0x%x\n",
-                               rc);
+                                       "2547 Read FCF record failed 0x%x\n",
+                                       rc);
                break;
 
        case LPFC_FCOE_EVENT_TYPE_FCF_TABLE_FULL:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                       "2548 FCF Table full count 0x%x tag 0x%x \n",
+                       "2548 FCF Table full count 0x%x tag 0x%x\n",
                        bf_get(lpfc_acqe_fcoe_fcf_count, acqe_fcoe),
                        acqe_fcoe->event_tag);
                break;
 
        case LPFC_FCOE_EVENT_TYPE_FCF_DEAD:
                lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
-                       "2549 FCF disconnected fron network index 0x%x"
-                       " tag 0x%x \n", acqe_fcoe->fcf_index,
+                       "2549 FCF disconnected from network index 0x%x"
+                       " tag 0x%x\n", acqe_fcoe->index,
                        acqe_fcoe->event_tag);
                /* If the event is not for currently used fcf do nothing */
-               if (phba->fcf.fcf_indx != acqe_fcoe->fcf_index)
+               if (phba->fcf.fcf_indx != acqe_fcoe->index)
                        break;
                /*
                 * Currently, driver support only one FCF - so treat this as
-                * a link down.
+                * a link down, but save the link state because we don't want
+                * it to be changed to Link Down unless it is already down.
                 */
+               link_state = phba->link_state;
                lpfc_linkdown(phba);
+               phba->link_state = link_state;
                /* Unregister FCF if no devices connected to it */
                lpfc_unregister_unused_fcf(phba);
                break;
-
+       case LPFC_FCOE_EVENT_TYPE_CVL:
+               lpfc_printf_log(phba, KERN_ERR, LOG_DISCOVERY,
+                       "2718 Clear Virtual Link Received for VPI 0x%x"
+                       " tag 0x%x\n", acqe_fcoe->index, acqe_fcoe->event_tag);
+               vport = lpfc_find_vport_by_vpid(phba,
+                               acqe_fcoe->index - phba->vpi_base);
+               if (!vport)
+                       break;
+               ndlp = lpfc_findnode_did(vport, Fabric_DID);
+               if (!ndlp)
+                       break;
+               shost = lpfc_shost_from_vport(vport);
+               lpfc_linkdown_port(vport);
+               if (vport->port_type != LPFC_NPIV_PORT) {
+                       mod_timer(&ndlp->nlp_delayfunc, jiffies + HZ);
+                       spin_lock_irq(shost->host_lock);
+                       ndlp->nlp_flag |= NLP_DELAY_TMO;
+                       spin_unlock_irq(shost->host_lock);
+                       ndlp->nlp_last_elscmd = ELS_CMD_FLOGI;
+                       vport->port_state = LPFC_FLOGI;
+               }
+               break;
        default:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                        "0288 Unknown FCoE event type 0x%x event tag "
@@ -2963,6 +3103,7 @@ static void
 lpfc_sli4_async_dcbx_evt(struct lpfc_hba *phba,
                         struct lpfc_acqe_dcbx *acqe_dcbx)
 {
+       phba->fc_eventTag = acqe_dcbx->event_tag;
        lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                        "0290 The SLI4 DCBX asynchronous event is not "
                        "handled yet\n");
@@ -3097,7 +3238,7 @@ static void lpfc_log_intr_mode(struct lpfc_hba *phba, uint32_t intr_mode)
  * PCI devices.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  **/
 static int
@@ -3193,7 +3334,7 @@ lpfc_reset_hba(struct lpfc_hba *phba)
  * support the SLI-3 HBA device it attached to.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  **/
 static int
@@ -3294,7 +3435,7 @@ lpfc_sli_driver_resource_unset(struct lpfc_hba *phba)
  * support the SLI-4 HBA device it attached to.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  **/
 static int
@@ -3405,7 +3546,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        /* Driver internel slow-path CQ Event pool */
        INIT_LIST_HEAD(&phba->sli4_hba.sp_cqe_event_pool);
        /* Response IOCB work queue list */
-       INIT_LIST_HEAD(&phba->sli4_hba.sp_rspiocb_work_queue);
+       INIT_LIST_HEAD(&phba->sli4_hba.sp_queue_event);
        /* Asynchronous event CQ Event work queue list */
        INIT_LIST_HEAD(&phba->sli4_hba.sp_asynce_work_queue);
        /* Fast-path XRI aborted CQ Event work queue list */
@@ -3434,6 +3575,10 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
        if (unlikely(rc))
                goto out_free_bsmbx;
 
+       rc = lpfc_sli4_fw_cfg_check(phba);
+       if (unlikely(rc))
+               goto out_free_bsmbx;
+
        /* Set up the hba's configuration parameters. */
        rc = lpfc_sli4_read_config(phba);
        if (unlikely(rc))
@@ -3567,8 +3712,10 @@ lpfc_sli4_driver_resource_unset(struct lpfc_hba *phba)
 
        /* Free the current connect table */
        list_for_each_entry_safe(conn_entry, next_conn_entry,
-               &phba->fcf_conn_rec_list, list)
+               &phba->fcf_conn_rec_list, list) {
+               list_del_init(&conn_entry->list);
                kfree(conn_entry);
+       }
 
        return;
 }
@@ -3615,7 +3762,7 @@ lpfc_init_api_table_setup(struct lpfc_hba *phba, uint8_t dev_grp)
  * device specific resource setup to support the HBA device it attached to.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  **/
 static int
@@ -3661,7 +3808,7 @@ lpfc_setup_driver_resource_phase1(struct lpfc_hba *phba)
  * device specific resource setup to support the HBA device it attached to.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  **/
 static int
@@ -3726,7 +3873,7 @@ lpfc_free_iocb_list(struct lpfc_hba *phba)
  * list and set up the IOCB tag array accordingly.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  **/
 static int
@@ -3797,7 +3944,7 @@ lpfc_free_sgl_list(struct lpfc_hba *phba)
        rc = lpfc_sli4_remove_all_sgl_pages(phba);
        if (rc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                       "2005 Unable to deregister pages from HBA: %x", rc);
+                       "2005 Unable to deregister pages from HBA: %x\n", rc);
        }
        kfree(phba->sli4_hba.lpfc_els_sgl_array);
 }
@@ -3845,7 +3992,7 @@ lpfc_free_active_sgl(struct lpfc_hba *phba)
  * list and set up the sgl xritag tag array accordingly.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  **/
 static int
@@ -3959,7 +4106,7 @@ out_free_mem:
  * enabled and the driver is reinitializing the device.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     ENOMEM - No availble memory
  *      EIO - The mailbox failed to complete successfully.
  **/
@@ -4119,7 +4266,7 @@ lpfc_sli4_remove_rpi_hdrs(struct lpfc_hba *phba)
  * PCI device data structure is set.
  *
  * Return codes
- *      pointer to @phba - sucessful
+ *      pointer to @phba - successful
  *      NULL - error
  **/
 static struct lpfc_hba *
@@ -4130,8 +4277,7 @@ lpfc_hba_alloc(struct pci_dev *pdev)
        /* Allocate memory for HBA structure */
        phba = kzalloc(sizeof(struct lpfc_hba), GFP_KERNEL);
        if (!phba) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "1417 Failed to allocate hba struct.\n");
+               dev_err(&pdev->dev, "failed to allocate hba struct\n");
                return NULL;
        }
 
@@ -4145,6 +4291,9 @@ lpfc_hba_alloc(struct pci_dev *pdev)
                return NULL;
        }
 
+       mutex_init(&phba->ct_event_mutex);
+       INIT_LIST_HEAD(&phba->ct_ev_waiters);
+
        return phba;
 }
 
@@ -4173,7 +4322,7 @@ lpfc_hba_free(struct lpfc_hba *phba)
  * host with it.
  *
  * Return codes
- *      0 - sucessful
+ *      0 - successful
  *      other values - error
  **/
 static int
@@ -4244,7 +4393,8 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost)
                        _dump_buf_data =
                                (char *) __get_free_pages(GFP_KERNEL, pagecnt);
                        if (_dump_buf_data) {
-                               printk(KERN_ERR "BLKGRD allocated %d pages for "
+                               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                                       "9043 BLKGRD: allocated %d pages for "
                                       "_dump_buf_data at 0x%p\n",
                                       (1 << pagecnt), _dump_buf_data);
                                _dump_buf_data_order = pagecnt;
@@ -4255,17 +4405,20 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost)
                                --pagecnt;
                }
                if (!_dump_buf_data_order)
-                       printk(KERN_ERR "BLKGRD ERROR unable to allocate "
+                       lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                               "9044 BLKGRD: ERROR unable to allocate "
                               "memory for hexdump\n");
        } else
-               printk(KERN_ERR "BLKGRD already allocated _dump_buf_data=0x%p"
+               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                       "9045 BLKGRD: already allocated _dump_buf_data=0x%p"
                       "\n", _dump_buf_data);
        if (!_dump_buf_dif) {
                while (pagecnt) {
                        _dump_buf_dif =
                                (char *) __get_free_pages(GFP_KERNEL, pagecnt);
                        if (_dump_buf_dif) {
-                               printk(KERN_ERR "BLKGRD allocated %d pages for "
+                               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                                       "9046 BLKGRD: allocated %d pages for "
                                       "_dump_buf_dif at 0x%p\n",
                                       (1 << pagecnt), _dump_buf_dif);
                                _dump_buf_dif_order = pagecnt;
@@ -4276,10 +4429,12 @@ lpfc_setup_bg(struct lpfc_hba *phba, struct Scsi_Host *shost)
                                --pagecnt;
                }
                if (!_dump_buf_dif_order)
-                       printk(KERN_ERR "BLKGRD ERROR unable to allocate "
+                       lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                       "9047 BLKGRD: ERROR unable to allocate "
                               "memory for hexdump\n");
        } else
-               printk(KERN_ERR "BLKGRD already allocated _dump_buf_dif=0x%p\n",
+               lpfc_printf_log(phba, KERN_ERR, LOG_BG,
+                       "9048 BLKGRD: already allocated _dump_buf_dif=0x%p\n",
                       _dump_buf_dif);
 }
 
@@ -4336,7 +4491,7 @@ lpfc_post_init_setup(struct lpfc_hba *phba)
  * with SLI-3 interface spec.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  **/
 static int
@@ -4355,9 +4510,13 @@ lpfc_sli_pci_mem_setup(struct lpfc_hba *phba)
                pdev = phba->pcidev;
 
        /* Set the device DMA mask size */
-       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
-               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0
+        || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(64)) != 0) {
+               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0
+                || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(32)) != 0) {
                        return error;
+               }
+       }
 
        /* Get the bus address of Bar0 and Bar2 and the number of bytes
         * required by each mapping.
@@ -4483,29 +4642,11 @@ int
 lpfc_sli4_post_status_check(struct lpfc_hba *phba)
 {
        struct lpfc_register sta_reg, uerrlo_reg, uerrhi_reg, scratchpad;
-       uint32_t onlnreg0, onlnreg1;
        int i, port_error = -ENODEV;
 
        if (!phba->sli4_hba.STAregaddr)
                return -ENODEV;
 
-       /* With uncoverable error, log the error message and return error */
-       onlnreg0 = readl(phba->sli4_hba.ONLINE0regaddr);
-       onlnreg1 = readl(phba->sli4_hba.ONLINE1regaddr);
-       if ((onlnreg0 != LPFC_ONLINE_NERR) || (onlnreg1 != LPFC_ONLINE_NERR)) {
-               uerrlo_reg.word0 = readl(phba->sli4_hba.UERRLOregaddr);
-               uerrhi_reg.word0 = readl(phba->sli4_hba.UERRHIregaddr);
-               if (uerrlo_reg.word0 || uerrhi_reg.word0) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                                       "1422 HBA Unrecoverable error: "
-                                       "uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, "
-                                       "online0_reg=0x%x, online1_reg=0x%x\n",
-                                       uerrlo_reg.word0, uerrhi_reg.word0,
-                                       onlnreg0, onlnreg1);
-               }
-               return -ENODEV;
-       }
-
        /* Wait up to 30 seconds for the SLI Port POST done and ready */
        for (i = 0; i < 3000; i++) {
                sta_reg.word0 = readl(phba->sli4_hba.STAregaddr);
@@ -4544,6 +4685,22 @@ lpfc_sli4_post_status_check(struct lpfc_hba *phba)
                        bf_get(lpfc_scratchpad_slirev, &scratchpad),
                        bf_get(lpfc_scratchpad_featurelevel1, &scratchpad),
                        bf_get(lpfc_scratchpad_featurelevel2, &scratchpad));
+       phba->sli4_hba.ue_mask_lo = readl(phba->sli4_hba.UEMASKLOregaddr);
+       phba->sli4_hba.ue_mask_hi = readl(phba->sli4_hba.UEMASKHIregaddr);
+       /* With uncoverable error, log the error message and return error */
+       uerrlo_reg.word0 = readl(phba->sli4_hba.UERRLOregaddr);
+       uerrhi_reg.word0 = readl(phba->sli4_hba.UERRHIregaddr);
+       if ((~phba->sli4_hba.ue_mask_lo & uerrlo_reg.word0) ||
+           (~phba->sli4_hba.ue_mask_hi & uerrhi_reg.word0)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "1422 HBA Unrecoverable error: "
+                               "uerr_lo_reg=0x%x, uerr_hi_reg=0x%x, "
+                               "ue_mask_lo_reg=0x%x, ue_mask_hi_reg=0x%x\n",
+                               uerrlo_reg.word0, uerrhi_reg.word0,
+                               phba->sli4_hba.ue_mask_lo,
+                               phba->sli4_hba.ue_mask_hi);
+               return -ENODEV;
+       }
 
        return port_error;
 }
@@ -4562,10 +4719,10 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba)
                                        LPFC_UERR_STATUS_LO;
        phba->sli4_hba.UERRHIregaddr = phba->sli4_hba.conf_regs_memmap_p +
                                        LPFC_UERR_STATUS_HI;
-       phba->sli4_hba.ONLINE0regaddr = phba->sli4_hba.conf_regs_memmap_p +
-                                       LPFC_ONLINE0;
-       phba->sli4_hba.ONLINE1regaddr = phba->sli4_hba.conf_regs_memmap_p +
-                                       LPFC_ONLINE1;
+       phba->sli4_hba.UEMASKLOregaddr = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_UE_MASK_LO;
+       phba->sli4_hba.UEMASKHIregaddr = phba->sli4_hba.conf_regs_memmap_p +
+                                       LPFC_UE_MASK_HI;
        phba->sli4_hba.SCRATCHPADregaddr = phba->sli4_hba.conf_regs_memmap_p +
                                        LPFC_SCRATCHPAD;
 }
@@ -4633,7 +4790,7 @@ lpfc_sli4_bar2_register_memmap(struct lpfc_hba *phba, uint32_t vf)
  * this routine.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     ENOMEM - could not allocated memory.
  **/
 static int
@@ -4732,7 +4889,7 @@ lpfc_destroy_bootstrap_mbox(struct lpfc_hba *phba)
  * allocation for the port.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     ENOMEM - No availble memory
  *      EIO - The mailbox failed to complete successfully.
  **/
@@ -4796,7 +4953,8 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
                phba->vpi_base = phba->sli4_hba.max_cfg_param.vpi_base;
                phba->vfi_base = phba->sli4_hba.max_cfg_param.vfi_base;
                phba->sli4_hba.next_rpi = phba->sli4_hba.max_cfg_param.rpi_base;
-               phba->max_vpi = phba->sli4_hba.max_cfg_param.max_vpi;
+               phba->max_vpi = (phba->sli4_hba.max_cfg_param.max_vpi > 0) ?
+                               (phba->sli4_hba.max_cfg_param.max_vpi - 1) : 0;
                phba->max_vports = phba->max_vpi;
                lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
                                "2003 cfg params XRI(B:%d M:%d), "
@@ -4832,7 +4990,7 @@ lpfc_sli4_read_config(struct lpfc_hba *phba)
  * HBA consistent with the SLI-4 interface spec.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     ENOMEM - No availble memory
  *      EIO - The mailbox failed to complete successfully.
  **/
@@ -4881,7 +5039,7 @@ lpfc_setup_endian_order(struct lpfc_hba *phba)
  * we just use some constant number as place holder.
  *
  * Return codes
- *      0 - sucessful
+ *      0 - successful
  *      ENOMEM - No availble memory
  *      EIO - The mailbox failed to complete successfully.
  **/
@@ -4950,10 +5108,9 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
        /* It does not make sense to have more EQs than WQs */
        if (cfg_fcp_eq_count > phba->cfg_fcp_wq_count) {
                lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
-                               "2593 The number of FCP EQs (%d) is more "
-                               "than the number of FCP WQs (%d), take "
-                               "the number of FCP EQs same as than of "
-                               "WQs (%d)\n", cfg_fcp_eq_count,
+                               "2593 The FCP EQ count(%d) cannot be greater "
+                               "than the FCP WQ count(%d), limiting the "
+                               "FCP EQ count to %d\n", cfg_fcp_eq_count,
                                phba->cfg_fcp_wq_count,
                                phba->cfg_fcp_wq_count);
                cfg_fcp_eq_count = phba->cfg_fcp_wq_count;
@@ -5029,15 +5186,6 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
        }
        phba->sli4_hba.els_cq = qdesc;
 
-       /* Create slow-path Unsolicited Receive Complete Queue */
-       qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.cq_esize,
-                                     phba->sli4_hba.cq_ecount);
-       if (!qdesc) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "0502 Failed allocate slow-path USOL RX CQ\n");
-               goto out_free_els_cq;
-       }
-       phba->sli4_hba.rxq_cq = qdesc;
 
        /* Create fast-path FCP Completion Queue(s), one-to-one with EQs */
        phba->sli4_hba.fcp_cq = kzalloc((sizeof(struct lpfc_queue *) *
@@ -5046,7 +5194,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "2577 Failed allocate memory for fast-path "
                                "CQ record array\n");
-               goto out_free_rxq_cq;
+               goto out_free_els_cq;
        }
        for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_eq_count; fcp_cqidx++) {
                qdesc = lpfc_sli4_queue_alloc(phba, phba->sli4_hba.cq_esize,
@@ -5159,9 +5307,6 @@ out_free_fcp_cq:
                phba->sli4_hba.fcp_cq[fcp_cqidx] = NULL;
        }
        kfree(phba->sli4_hba.fcp_cq);
-out_free_rxq_cq:
-       lpfc_sli4_queue_free(phba->sli4_hba.rxq_cq);
-       phba->sli4_hba.rxq_cq = NULL;
 out_free_els_cq:
        lpfc_sli4_queue_free(phba->sli4_hba.els_cq);
        phba->sli4_hba.els_cq = NULL;
@@ -5189,7 +5334,7 @@ out_error:
  * operation.
  *
  * Return codes
- *      0 - sucessful
+ *      0 - successful
  *      ENOMEM - No availble memory
  *      EIO - The mailbox failed to complete successfully.
  **/
@@ -5218,10 +5363,6 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
        lpfc_sli4_queue_free(phba->sli4_hba.dat_rq);
        phba->sli4_hba.dat_rq = NULL;
 
-       /* Release unsolicited receive complete queue */
-       lpfc_sli4_queue_free(phba->sli4_hba.rxq_cq);
-       phba->sli4_hba.rxq_cq = NULL;
-
        /* Release ELS complete queue */
        lpfc_sli4_queue_free(phba->sli4_hba.els_cq);
        phba->sli4_hba.els_cq = NULL;
@@ -5257,7 +5398,7 @@ lpfc_sli4_queue_destroy(struct lpfc_hba *phba)
  * operation.
  *
  * Return codes
- *      0 - sucessful
+ *      0 - successful
  *      ENOMEM - No availble memory
  *      EIO - The mailbox failed to complete successfully.
  **/
@@ -5354,25 +5495,6 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
                        phba->sli4_hba.els_cq->queue_id,
                        phba->sli4_hba.sp_eq->queue_id);
 
-       /* Set up slow-path Unsolicited Receive Complete Queue */
-       if (!phba->sli4_hba.rxq_cq) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "0532 USOL RX CQ not allocated\n");
-               goto out_destroy_els_cq;
-       }
-       rc = lpfc_cq_create(phba, phba->sli4_hba.rxq_cq, phba->sli4_hba.sp_eq,
-                           LPFC_RCQ, LPFC_USOL);
-       if (rc) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "0533 Failed setup of slow-path USOL RX CQ: "
-                               "rc = 0x%x\n", rc);
-               goto out_destroy_els_cq;
-       }
-       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                       "2587 USL CQ setup: cq-id=%d, parent eq-id=%d\n",
-                       phba->sli4_hba.rxq_cq->queue_id,
-                       phba->sli4_hba.sp_eq->queue_id);
-
        /* Set up fast-path FCP Response Complete Queue */
        for (fcp_cqidx = 0; fcp_cqidx < phba->cfg_fcp_eq_count; fcp_cqidx++) {
                if (!phba->sli4_hba.fcp_cq[fcp_cqidx]) {
@@ -5478,7 +5600,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
                goto out_destroy_fcp_wq;
        }
        rc = lpfc_rq_create(phba, phba->sli4_hba.hdr_rq, phba->sli4_hba.dat_rq,
-                           phba->sli4_hba.rxq_cq, LPFC_USOL);
+                           phba->sli4_hba.els_cq, LPFC_USOL);
        if (rc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "0541 Failed setup of Receive Queue: "
@@ -5490,7 +5612,7 @@ lpfc_sli4_queue_setup(struct lpfc_hba *phba)
                        "parent cq-id=%d\n",
                        phba->sli4_hba.hdr_rq->queue_id,
                        phba->sli4_hba.dat_rq->queue_id,
-                       phba->sli4_hba.rxq_cq->queue_id);
+                       phba->sli4_hba.els_cq->queue_id);
        return 0;
 
 out_destroy_fcp_wq:
@@ -5502,8 +5624,6 @@ out_destroy_mbx_wq:
 out_destroy_fcp_cq:
        for (--fcp_cqidx; fcp_cqidx >= 0; fcp_cqidx--)
                lpfc_cq_destroy(phba, phba->sli4_hba.fcp_cq[fcp_cqidx]);
-       lpfc_cq_destroy(phba, phba->sli4_hba.rxq_cq);
-out_destroy_els_cq:
        lpfc_cq_destroy(phba, phba->sli4_hba.els_cq);
 out_destroy_mbx_cq:
        lpfc_cq_destroy(phba, phba->sli4_hba.mbx_cq);
@@ -5523,7 +5643,7 @@ out_error:
  * operation.
  *
  * Return codes
- *      0 - sucessful
+ *      0 - successful
  *      ENOMEM - No availble memory
  *      EIO - The mailbox failed to complete successfully.
  **/
@@ -5545,8 +5665,6 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba)
        lpfc_cq_destroy(phba, phba->sli4_hba.mbx_cq);
        /* Unset ELS complete queue */
        lpfc_cq_destroy(phba, phba->sli4_hba.els_cq);
-       /* Unset unsolicited receive complete queue */
-       lpfc_cq_destroy(phba, phba->sli4_hba.rxq_cq);
        /* Unset FCP response complete queue */
        for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++)
                lpfc_cq_destroy(phba, phba->sli4_hba.fcp_cq[fcp_qidx]);
@@ -5570,7 +5688,7 @@ lpfc_sli4_queue_unset(struct lpfc_hba *phba)
  * Later, this can be used for all the slow-path events.
  *
  * Return codes
- *      0 - sucessful
+ *      0 - successful
  *      -ENOMEM - No availble memory
  **/
 static int
@@ -5731,7 +5849,7 @@ lpfc_sli4_cq_event_release_all(struct lpfc_hba *phba)
  * all resources assigned to the PCI function which originates this request.
  *
  * Return codes
- *      0 - sucessful
+ *      0 - successful
  *      ENOMEM - No availble memory
  *      EIO - The mailbox failed to complete successfully.
  **/
@@ -5894,7 +6012,7 @@ lpfc_sli4_fcfi_unreg(struct lpfc_hba *phba, uint16_t fcfi)
  * with SLI-4 interface spec.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  **/
 static int
@@ -5911,9 +6029,13 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
                pdev = phba->pcidev;
 
        /* Set the device DMA mask size */
-       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0)
-               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)
+       if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) != 0
+        || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(64)) != 0) {
+               if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0
+                || pci_set_consistent_dma_mask(pdev,DMA_BIT_MASK(32)) != 0) {
                        return error;
+               }
+       }
 
        /* Get the bus address of SLI4 device Bar0, Bar1, and Bar2 and the
         * number of bytes required by each mapping. They are actually
@@ -6023,7 +6145,7 @@ lpfc_sli4_pci_mem_unset(struct lpfc_hba *phba)
  * will be left with MSI-X enabled and leaks its vectors.
  *
  * Return codes
- *   0 - sucessful
+ *   0 - successful
  *   other values - error
  **/
 static int
@@ -6155,7 +6277,7 @@ lpfc_sli_disable_msix(struct lpfc_hba *phba)
  * is done in this function.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  */
 static int
@@ -6214,7 +6336,7 @@ lpfc_sli_disable_msi(struct lpfc_hba *phba)
  * MSI-X -> MSI -> IRQ.
  *
  * Return codes
- *   0 - sucessful
+ *   0 - successful
  *   other values - error
  **/
 static uint32_t
@@ -6304,7 +6426,7 @@ lpfc_sli_disable_intr(struct lpfc_hba *phba)
  * enabled and leaks its vectors.
  *
  * Return codes
- * 0 - sucessful
+ * 0 - successful
  * other values - error
  **/
 static int
@@ -6414,7 +6536,7 @@ lpfc_sli4_disable_msix(struct lpfc_hba *phba)
  * which is done in this function.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  **/
 static int
@@ -6479,7 +6601,7 @@ lpfc_sli4_disable_msi(struct lpfc_hba *phba)
  * MSI-X -> MSI -> IRQ.
  *
  * Return codes
- *     0 - sucessful
+ *     0 - successful
  *     other values - error
  **/
 static uint32_t
@@ -6693,6 +6815,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
        struct lpfc_hba   *phba;
        struct lpfc_vport *vport = NULL;
+       struct Scsi_Host  *shost = NULL;
        int error;
        uint32_t cfg_mode, intr_mode;
 
@@ -6771,6 +6894,7 @@ lpfc_pci_probe_one_s3(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_destroy_shost;
        }
 
+       shost = lpfc_shost_from_vport(vport); /* save shost for error cleanup */
        /* Now, trying to enable interrupt and bring up the device */
        cfg_mode = phba->cfg_use_msi;
        while (true) {
@@ -6837,6 +6961,8 @@ out_unset_pci_mem_s3:
        lpfc_sli_pci_mem_unset(phba);
 out_disable_pci_dev:
        lpfc_disable_pci_dev(phba);
+       if (shost)
+               scsi_host_put(shost);
 out_free_phba:
        lpfc_hba_free(phba);
        return error;
@@ -7007,6 +7133,7 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev)
        /* Restore device state from PCI config space */
        pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
+
        if (pdev->is_busmaster)
                pci_set_master(pdev);
 
@@ -7041,6 +7168,73 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev)
 }
 
 /**
+ * lpfc_sli_prep_dev_for_recover - Prepare SLI3 device for pci slot recover
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is called to prepare the SLI3 device for PCI slot recover. It
+ * aborts and stops all the on-going I/Os on the pci device.
+ **/
+static void
+lpfc_sli_prep_dev_for_recover(struct lpfc_hba *phba)
+{
+       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "2723 PCI channel I/O abort preparing for recovery\n");
+       /* Prepare for bringing HBA offline */
+       lpfc_offline_prep(phba);
+       /* Clear sli active flag to prevent sysfs access to HBA */
+       spin_lock_irq(&phba->hbalock);
+       phba->sli.sli_flag &= ~LPFC_SLI_ACTIVE;
+       spin_unlock_irq(&phba->hbalock);
+       /* Stop and flush all I/Os and bring HBA offline */
+       lpfc_offline(phba);
+}
+
+/**
+ * lpfc_sli_prep_dev_for_reset - Prepare SLI3 device for pci slot reset
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is called to prepare the SLI3 device for PCI slot reset. It
+ * disables the device interrupt and pci device, and aborts the internal FCP
+ * pending I/Os.
+ **/
+static void
+lpfc_sli_prep_dev_for_reset(struct lpfc_hba *phba)
+{
+       struct lpfc_sli *psli = &phba->sli;
+       struct lpfc_sli_ring  *pring;
+
+       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "2710 PCI channel disable preparing for reset\n");
+       /* Disable interrupt and pci device */
+       lpfc_sli_disable_intr(phba);
+       pci_disable_device(phba->pcidev);
+       /*
+        * There may be I/Os dropped by the firmware.
+        * Error iocb (I/O) on txcmplq and let the SCSI layer
+        * retry it after re-establishing link.
+        */
+       pring = &psli->ring[psli->fcp_ring];
+       lpfc_sli_abort_iocb_ring(phba, pring);
+}
+
+/**
+ * lpfc_sli_prep_dev_for_perm_failure - Prepare SLI3 dev for pci slot disable
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is called to prepare the SLI3 device for PCI slot permanently
+ * disabling. It blocks the SCSI transport layer traffic and flushes the FCP
+ * pending I/Os.
+ **/
+static void
+lpfc_prep_dev_for_perm_failure(struct lpfc_hba *phba)
+{
+       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                       "2711 PCI channel permanent disable for failure\n");
+       /* Clean up all driver's outstanding SCSI I/Os */
+       lpfc_sli_flush_fcp_rings(phba);
+}
+
+/**
  * lpfc_io_error_detected_s3 - Method for handling SLI-3 device PCI I/O error
  * @pdev: pointer to PCI device.
  * @state: the current PCI connection state.
@@ -7054,6 +7248,7 @@ lpfc_pci_resume_one_s3(struct pci_dev *pdev)
  * as desired.
  *
  * Return codes
+ *     PCI_ERS_RESULT_CAN_RECOVER - can be recovered with reset_link
  *     PCI_ERS_RESULT_NEED_RESET - need to reset before recovery
  *     PCI_ERS_RESULT_DISCONNECT - device could not be recovered
  **/
@@ -7062,33 +7257,30 @@ lpfc_io_error_detected_s3(struct pci_dev *pdev, pci_channel_state_t state)
 {
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
-       struct lpfc_sli *psli = &phba->sli;
-       struct lpfc_sli_ring  *pring;
 
-       if (state == pci_channel_io_perm_failure) {
-               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "0472 PCI channel I/O permanent failure\n");
-               /* Block all SCSI devices' I/Os on the host */
-               lpfc_scsi_dev_block(phba);
-               /* Clean up all driver's outstanding SCSI I/Os */
-               lpfc_sli_flush_fcp_rings(phba);
+       /* Block all SCSI devices' I/Os on the host */
+       lpfc_scsi_dev_block(phba);
+
+       switch (state) {
+       case pci_channel_io_normal:
+               /* Non-fatal error, prepare for recovery */
+               lpfc_sli_prep_dev_for_recover(phba);
+               return PCI_ERS_RESULT_CAN_RECOVER;
+       case pci_channel_io_frozen:
+               /* Fatal error, prepare for slot reset */
+               lpfc_sli_prep_dev_for_reset(phba);
+               return PCI_ERS_RESULT_NEED_RESET;
+       case pci_channel_io_perm_failure:
+               /* Permanent failure, prepare for device down */
+               lpfc_prep_dev_for_perm_failure(phba);
                return PCI_ERS_RESULT_DISCONNECT;
+       default:
+               /* Unknown state, prepare and request slot reset */
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "0472 Unknown PCI error state: x%x\n", state);
+               lpfc_sli_prep_dev_for_reset(phba);
+               return PCI_ERS_RESULT_NEED_RESET;
        }
-
-       pci_disable_device(pdev);
-       /*
-        * There may be I/Os dropped by the firmware.
-        * Error iocb (I/O) on txcmplq and let the SCSI layer
-        * retry it after re-establishing link.
-        */
-       pring = &psli->ring[psli->fcp_ring];
-       lpfc_sli_abort_iocb_ring(phba, pring);
-
-       /* Disable interrupt */
-       lpfc_sli_disable_intr(phba);
-
-       /* Request a slot reset. */
-       return PCI_ERS_RESULT_NEED_RESET;
 }
 
 /**
@@ -7168,7 +7360,12 @@ lpfc_io_resume_s3(struct pci_dev *pdev)
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
 
+       /* Bring the device online */
        lpfc_online(phba);
+
+       /* Clean up Advanced Error Reporting (AER) if needed */
+       if (phba->hba_flag & HBA_AER_ENABLED)
+               pci_cleanup_aer_uncorrect_error_status(pdev);
 }
 
 /**
@@ -7184,15 +7381,15 @@ lpfc_sli4_get_els_iocb_cnt(struct lpfc_hba *phba)
 
        if (phba->sli_rev == LPFC_SLI_REV4) {
                if (max_xri <= 100)
-                       return 4;
+                       return 10;
                else if (max_xri <= 256)
-                       return 8;
+                       return 25;
                else if (max_xri <= 512)
-                       return 16;
+                       return 50;
                else if (max_xri <= 1024)
-                       return 32;
+                       return 100;
                else
-                       return 48;
+                       return 150;
        } else
                return 0;
 }
@@ -7220,6 +7417,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
        struct lpfc_hba   *phba;
        struct lpfc_vport *vport = NULL;
+       struct Scsi_Host  *shost = NULL;
        int error;
        uint32_t cfg_mode, intr_mode;
        int mcnt;
@@ -7300,6 +7498,7 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_destroy_shost;
        }
 
+       shost = lpfc_shost_from_vport(vport); /* save shost for error cleanup */
        /* Now, trying to enable interrupt and bring up the device */
        cfg_mode = phba->cfg_use_msi;
        while (true) {
@@ -7313,6 +7512,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
                        error = -ENODEV;
                        goto out_free_sysfs_attr;
                }
+               /* Default to single FCP EQ for non-MSI-X */
+               if (phba->intr_type != MSIX)
+                       phba->cfg_fcp_eq_count = 1;
                /* Set up SLI-4 HBA */
                if (lpfc_sli4_hba_setup(phba)) {
                        lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -7347,6 +7549,9 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        /* Perform post initialization setup */
        lpfc_post_init_setup(phba);
 
+       /* Check if there are static vports to be created. */
+       lpfc_create_static_vport(phba);
+
        return 0;
 
 out_disable_intr:
@@ -7365,6 +7570,8 @@ out_unset_pci_mem_s4:
        lpfc_sli4_pci_mem_unset(phba);
 out_disable_pci_dev:
        lpfc_disable_pci_dev(phba);
+       if (shost)
+               scsi_host_put(shost);
 out_free_phba:
        lpfc_hba_free(phba);
        return error;
@@ -7636,19 +7843,17 @@ static int __devinit
 lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
 {
        int rc;
-       uint16_t dev_id;
+       struct lpfc_sli_intf intf;
 
-       if (pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id))
+       if (pci_read_config_dword(pdev, LPFC_SLIREV_CONF_WORD, &intf.word0))
                return -ENODEV;
 
-       switch (dev_id) {
-       case PCI_DEVICE_ID_TIGERSHARK:
+       if ((bf_get(lpfc_sli_intf_valid, &intf) == LPFC_SLI_INTF_VALID) &&
+               (bf_get(lpfc_sli_intf_rev, &intf) == LPFC_SLIREV_CONF_SLI4))
                rc = lpfc_pci_probe_one_s4(pdev, pid);
-               break;
-       default:
+       else
                rc = lpfc_pci_probe_one_s3(pdev, pid);
-               break;
-       }
+
        return rc;
 }
 
@@ -7941,6 +8146,10 @@ static struct pci_device_id lpfc_id_table[] = {
                PCI_ANY_ID, PCI_ANY_ID, },
        {PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TIGERSHARK,
                PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_SERVERENGINE, PCI_DEVICE_ID_TOMCAT,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_FALCON,
+               PCI_ANY_ID, PCI_ANY_ID, },
        { 0 }
 };
 
@@ -8023,15 +8232,15 @@ lpfc_exit(void)
        if (lpfc_enable_npiv)
                fc_release_transport(lpfc_vport_transport_template);
        if (_dump_buf_data) {
-               printk(KERN_ERR "BLKGRD freeing %lu pages for _dump_buf_data "
-                               "at 0x%p\n",
+               printk(KERN_ERR "9062 BLKGRD: freeing %lu pages for "
+                               "_dump_buf_data at 0x%p\n",
                                (1L << _dump_buf_data_order), _dump_buf_data);
                free_pages((unsigned long)_dump_buf_data, _dump_buf_data_order);
        }
 
        if (_dump_buf_dif) {
-               printk(KERN_ERR "BLKGRD freeing %lu pages for _dump_buf_dif "
-                               "at 0x%p\n",
+               printk(KERN_ERR "9049 BLKGRD: freeing %lu pages for "
+                               "_dump_buf_dif at 0x%p\n",
                                (1L << _dump_buf_dif_order), _dump_buf_dif);
                free_pages((unsigned long)_dump_buf_dif, _dump_buf_dif_order);
        }