]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/lpfc/lpfc_init.c
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
[linux-2.6-omap-h63xx.git] / drivers / scsi / lpfc / lpfc_init.c
index 6a7a039e8904371e62f03244547f6b1ee1c5ff44..909be3301bba7d74b824319397aae90a14593566 100644 (file)
@@ -36,6 +36,7 @@
 
 #include "lpfc_hw.h"
 #include "lpfc_sli.h"
+#include "lpfc_nl.h"
 #include "lpfc_disc.h"
 #include "lpfc_scsi.h"
 #include "lpfc.h"
@@ -183,12 +184,9 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
                                                sizeof (phba->RandomData));
 
        /* Get adapter VPD information */
-       pmb->context2 = kmalloc(DMP_RSP_SIZE, GFP_KERNEL);
-       if (!pmb->context2)
-               goto out_free_mbox;
        lpfc_vpd_data = kmalloc(DMP_VPD_SIZE, GFP_KERNEL);
        if (!lpfc_vpd_data)
-               goto out_free_context2;
+               goto out_free_mbox;
 
        do {
                lpfc_dump_mem(phba, pmb, offset);
@@ -203,15 +201,14 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
                }
                if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset)
                        mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset;
-               lpfc_sli_pcimem_bcopy(pmb->context2, lpfc_vpd_data + offset,
+               lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
+                                     lpfc_vpd_data + offset,
                                      mb->un.varDmp.word_cnt);
                offset += mb->un.varDmp.word_cnt;
        } while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE);
        lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
 
        kfree(lpfc_vpd_data);
-out_free_context2:
-       kfree(pmb->context2);
 out_free_mbox:
        mempool_free(pmb, phba->mbox_mem_pool);
        return 0;
@@ -393,6 +390,29 @@ lpfc_config_port_post(struct lpfc_hba *phba)
        if (phba->sli_rev != 3)
                lpfc_post_rcv_buf(phba);
 
+       /*
+        * Configure HBA MSI-X attention conditions to messages if MSI-X mode
+        */
+       if (phba->intr_type == MSIX) {
+               rc = lpfc_config_msi(phba, pmb);
+               if (rc) {
+                       mempool_free(pmb, phba->mbox_mem_pool);
+                       return -EIO;
+               }
+               rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
+               if (rc != MBX_SUCCESS) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+                                       "0352 Config MSI mailbox command "
+                                       "failed, mbxCmd x%x, mbxStatus x%x\n",
+                                       pmb->mb.mbxCommand, pmb->mb.mbxStatus);
+                       mempool_free(pmb, phba->mbox_mem_pool);
+                       return -EIO;
+               }
+       }
+
+       /* Initialize ERATT handling flag */
+       phba->hba_flag &= ~HBA_ERATT_HANDLED;
+
        /* Enable appropriate host interrupts */
        spin_lock_irq(&phba->hbalock);
        status = readl(phba->HCregaddr);
@@ -408,26 +428,26 @@ lpfc_config_port_post(struct lpfc_hba *phba)
 
        if ((phba->cfg_poll & ENABLE_FCP_RING_POLLING) &&
            (phba->cfg_poll & DISABLE_FCP_RING_INT))
-               status &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
+               status &= ~(HC_R0INT_ENA);
 
        writel(status, phba->HCregaddr);
        readl(phba->HCregaddr); /* flush */
        spin_unlock_irq(&phba->hbalock);
 
-       /*
-        * Setup the ring 0 (els)  timeout handler
-        */
-       timeout = phba->fc_ratov << 1;
+       /* Set up ring-0 (ELS) timer */
+       timeout = phba->fc_ratov * 2;
        mod_timer(&vport->els_tmofunc, jiffies + HZ * timeout);
+       /* Set up heart beat (HB) timer */
        mod_timer(&phba->hb_tmofunc, jiffies + HZ * LPFC_HB_MBOX_INTERVAL);
        phba->hb_outstanding = 0;
        phba->last_completion_time = jiffies;
+       /* 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;
-       pmb->vport = vport;
-       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
        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 "
@@ -462,7 +482,7 @@ lpfc_config_port_post(struct lpfc_hba *phba)
                                rc);
                mempool_free(pmb, phba->mbox_mem_pool);
        }
-       return (0);
+       return 0;
 }
 
 /**
@@ -586,12 +606,15 @@ lpfc_hb_timeout(unsigned long ptr)
        unsigned long iflag;
 
        phba = (struct lpfc_hba *)ptr;
+
+       /* Check for heart beat timeout conditions */
        spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
        tmo_posted = phba->pport->work_port_events & WORKER_HB_TMO;
        if (!tmo_posted)
                phba->pport->work_port_events |= WORKER_HB_TMO;
        spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
 
+       /* Tell the worker thread there is work to do */
        if (!tmo_posted)
                lpfc_worker_wake_up(phba);
        return;
@@ -622,6 +645,7 @@ lpfc_hb_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
        phba->hb_outstanding = 0;
        spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
 
+       /* Check and reset heart-beat timer is necessary */
        mempool_free(pmboxq, phba->mbox_mem_pool);
        if (!(phba->pport->fc_flag & FC_OFFLINE_MODE) &&
                !(phba->link_state == LPFC_HBA_ERROR) &&
@@ -792,6 +816,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
        unsigned long temperature;
        struct temp_event temp_event_data;
        struct Scsi_Host  *shost;
+       struct lpfc_board_event_header board_event;
 
        /* If the pci channel is offline, ignore possible errors,
         * since we cannot communicate with the pci card anyway. */
@@ -801,6 +826,16 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
        if (!phba->cfg_enable_hba_reset)
                return;
 
+       /* Send an internal error event to mgmt application */
+       board_event.event_type = FC_REG_BOARD_EVENT;
+       board_event.subcategory = LPFC_EVENT_PORTINTERR;
+       shost = lpfc_shost_from_vport(phba->pport);
+       fc_host_post_vendor_event(shost, fc_get_event_number(),
+                                 sizeof(board_event),
+                                 (char *) &board_event,
+                                 SCSI_NL_VID_TYPE_PCI
+                                 | PCI_VENDOR_ID_EMULEX);
+
        if (phba->work_hs & HS_FFER6) {
                /* Re-establishing Link */
                lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
@@ -841,7 +876,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
                temp_event_data.data = (uint32_t)temperature;
 
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "0459 Adapter maximum temperature exceeded "
+                               "0406 Adapter maximum temperature exceeded "
                                "(%ld), taking this port offline "
                                "Data: x%x x%x x%x\n",
                                temperature, phba->work_hs,
@@ -861,8 +896,8 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
 
        } else {
                /* The if clause above forces this code path when the status
-                * failure is a value other than FFER6.  Do not call the offline
-                *  twice. This is the adapter hardware error path.
+                * failure is a value other than FFER6. Do not call the offline
+                * twice. This is the adapter hardware error path.
                 */
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
                                "0457 Adapter Hardware Error "
@@ -878,6 +913,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
 
                lpfc_offline_eratt(phba);
        }
+       return;
 }
 
 /**
@@ -1135,6 +1171,7 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
        lpfc_vpd_t *vp;
        uint16_t dev_id = phba->pcidev->device;
        int max_speed;
+       int GE = 0;
        struct {
                char * name;
                int    max_speed;
@@ -1266,6 +1303,19 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
        case PCI_DEVICE_ID_SAT_S:
                m = (typeof(m)){"LPe12000-S", max_speed, "PCIe"};
                break;
+       case PCI_DEVICE_ID_HORNET:
+               m = (typeof(m)){"LP21000", max_speed, "PCIe"};
+               GE = 1;
+               break;
+       case PCI_DEVICE_ID_PROTEUS_VF:
+               m = (typeof(m)) {"LPev12000", max_speed, "PCIe IOV"};
+               break;
+       case PCI_DEVICE_ID_PROTEUS_PF:
+               m = (typeof(m)) {"LPev12000", max_speed, "PCIe IOV"};
+               break;
+       case PCI_DEVICE_ID_PROTEUS_S:
+               m = (typeof(m)) {"LPemv12002-S", max_speed, "PCIe IOV"};
+               break;
        default:
                m = (typeof(m)){ NULL };
                break;
@@ -1275,8 +1325,11 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t *mdp, uint8_t *descp)
                snprintf(mdp, 79,"%s", m.name);
        if (descp && descp[0] == '\0')
                snprintf(descp, 255,
-                        "Emulex %s %dGb %s Fibre Channel Adapter",
-                        m.name, m.max_speed, m.bus);
+                       "Emulex %s %d%s %s %s",
+                       m.name, m.max_speed,
+                       (GE) ? "GE" : "Gb",
+                       m.bus,
+                       (GE) ? "FCoE Adapter" : "Fibre Channel Adapter");
 }
 
 /**
@@ -1595,7 +1648,7 @@ lpfc_cleanup(struct lpfc_vport *vport)
                                                &vport->fc_nodes, nlp_listp) {
                                lpfc_printf_vlog(ndlp->vport, KERN_ERR,
                                                LOG_NODE,
-                                               "0282: did:x%x ndlp:x%p "
+                                               "0282 did:x%x ndlp:x%p "
                                                "usgmap:x%x refcnt:%d\n",
                                                ndlp->nlp_DID, (void *)ndlp,
                                                ndlp->nlp_usg_map,
@@ -1644,6 +1697,7 @@ lpfc_stop_phba_timers(struct lpfc_hba *phba)
        del_timer_sync(&phba->fabric_block_timer);
        phba->hb_outstanding = 0;
        del_timer_sync(&phba->hb_tmofunc);
+       del_timer_sync(&phba->eratt_poll);
        return;
 }
 
@@ -2160,30 +2214,97 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost)
 static int
 lpfc_enable_msix(struct lpfc_hba *phba)
 {
-       int error;
+       int rc, i;
+       LPFC_MBOXQ_t *pmb;
 
-       phba->msix_entries[0].entry = 0;
-       phba->msix_entries[0].vector = 0;
+       /* Set up MSI-X multi-message vectors */
+       for (i = 0; i < LPFC_MSIX_VECTORS; i++)
+               phba->msix_entries[i].entry = i;
 
-       error = pci_enable_msix(phba->pcidev, phba->msix_entries,
+       /* Configure MSI-X capability structure */
+       rc = pci_enable_msix(phba->pcidev, phba->msix_entries,
                                ARRAY_SIZE(phba->msix_entries));
-       if (error) {
+       if (rc) {
                lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
                                "0420 Enable MSI-X failed (%d), continuing "
-                               "with MSI\n", error);
-               pci_disable_msix(phba->pcidev);
-               return error;
+                               "with MSI\n", rc);
+               goto msi_fail_out;
+       } else
+               for (i = 0; i < LPFC_MSIX_VECTORS; i++)
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                       "0477 MSI-X entry[%d]: vector=x%x "
+                                       "message=%d\n", i,
+                                       phba->msix_entries[i].vector,
+                                       phba->msix_entries[i].entry);
+       /*
+        * Assign MSI-X vectors to interrupt handlers
+        */
+
+       /* vector-0 is associated to slow-path handler */
+       rc = request_irq(phba->msix_entries[0].vector, &lpfc_sp_intr_handler,
+                        IRQF_SHARED, LPFC_SP_DRIVER_HANDLER_NAME, phba);
+       if (rc) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "0421 MSI-X slow-path request_irq failed "
+                               "(%d), continuing with MSI\n", rc);
+               goto msi_fail_out;
        }
 
-       error = request_irq(phba->msix_entries[0].vector, lpfc_intr_handler, 0,
-                           LPFC_DRIVER_NAME, phba);
-       if (error) {
+       /* vector-1 is associated to fast-path handler */
+       rc = request_irq(phba->msix_entries[1].vector, &lpfc_fp_intr_handler,
+                        IRQF_SHARED, LPFC_FP_DRIVER_HANDLER_NAME, phba);
+
+       if (rc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                               "0421 MSI-X request_irq failed (%d), "
-                               "continuing with MSI\n", error);
-               pci_disable_msix(phba->pcidev);
+                               "0429 MSI-X fast-path request_irq failed "
+                               "(%d), continuing with MSI\n", rc);
+               goto irq_fail_out;
        }
-       return error;
+
+       /*
+        * Configure HBA MSI-X attention conditions to messages
+        */
+       pmb = (LPFC_MBOXQ_t *) mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+
+       if (!pmb) {
+               rc = -ENOMEM;
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "0474 Unable to allocate memory for issuing "
+                               "MBOX_CONFIG_MSI command\n");
+               goto mem_fail_out;
+       }
+       rc = lpfc_config_msi(phba, pmb);
+       if (rc)
+               goto mbx_fail_out;
+       rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
+       if (rc != MBX_SUCCESS) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_MBOX,
+                               "0351 Config MSI mailbox command failed, "
+                               "mbxCmd x%x, mbxStatus x%x\n",
+                               pmb->mb.mbxCommand, pmb->mb.mbxStatus);
+               goto mbx_fail_out;
+       }
+
+       /* Free memory allocated for mailbox command */
+       mempool_free(pmb, phba->mbox_mem_pool);
+       return rc;
+
+mbx_fail_out:
+       /* Free memory allocated for mailbox command */
+       mempool_free(pmb, phba->mbox_mem_pool);
+
+mem_fail_out:
+       /* free the irq already requested */
+       free_irq(phba->msix_entries[1].vector, phba);
+
+irq_fail_out:
+       /* free the irq already requested */
+       free_irq(phba->msix_entries[0].vector, phba);
+
+msi_fail_out:
+       /* Unconfigure MSI-X capability structure */
+       pci_disable_msix(phba->pcidev);
+       return rc;
 }
 
 /**
@@ -2196,7 +2317,12 @@ lpfc_enable_msix(struct lpfc_hba *phba)
 static void
 lpfc_disable_msix(struct lpfc_hba *phba)
 {
-       free_irq(phba->msix_entries[0].vector, phba);
+       int i;
+
+       /* Free up MSI-X multi-message vectors */
+       for (i = 0; i < LPFC_MSIX_VECTORS; i++)
+               free_irq(phba->msix_entries[i].vector, phba);
+       /* Disable MSI-X */
        pci_disable_msix(phba->pcidev);
 }
 
@@ -2231,6 +2357,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        int  i, hbq_count;
        uint16_t iotag;
        int bars = pci_select_bars(pdev, IORESOURCE_MEM);
+       struct lpfc_adapter_event_header adapter_event;
 
        if (pci_enable_device_mem(pdev))
                goto out;
@@ -2241,6 +2368,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        if (!phba)
                goto out_release_regions;
 
+       atomic_set(&phba->fast_event_count, 0);
        spin_lock_init(&phba->hbalock);
 
        /* Initialize ndlp management spinlock */
@@ -2253,6 +2381,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_free_phba;
 
        INIT_LIST_HEAD(&phba->port_list);
+       init_waitqueue_head(&phba->wait_4_mlo_m_q);
        /*
         * Get all the module params for configuring this host and then
         * establish the host.
@@ -2275,6 +2404,9 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        init_timer(&phba->fabric_block_timer);
        phba->fabric_block_timer.function = lpfc_fabric_block_timeout;
        phba->fabric_block_timer.data = (unsigned long) phba;
+       init_timer(&phba->eratt_poll);
+       phba->eratt_poll.function = lpfc_poll_eratt;
+       phba->eratt_poll.data = (unsigned long) phba;
 
        pci_set_master(pdev);
        pci_try_set_mwi(pdev);
@@ -2294,7 +2426,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        bar2map_len        = pci_resource_len(phba->pcidev, 2);
 
        /* Map HBA SLIM to a kernel virtual address. */
-       phba->slim_memmap_p      = ioremap(phba->pci_bar0_map, bar0map_len);
+       phba->slim_memmap_p = ioremap(phba->pci_bar0_map, bar0map_len);
        if (!phba->slim_memmap_p) {
                error = -ENODEV;
                dev_printk(KERN_ERR, &pdev->dev,
@@ -2320,10 +2452,10 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
                goto out_iounmap;
 
        memset(phba->slim2p.virt, 0, SLI2_SLIM_SIZE);
-       phba->mbox = phba->slim2p.virt;
-       phba->pcb = (phba->slim2p.virt + sizeof(MAILBOX_t));
-       phba->IOCBs = (phba->slim2p.virt + sizeof(MAILBOX_t) +
-                      sizeof(struct _PCB));
+       phba->mbox = phba->slim2p.virt + offsetof(struct lpfc_sli2_slim, mbx);
+       phba->pcb = (phba->slim2p.virt + offsetof(struct lpfc_sli2_slim, pcb));
+       phba->IOCBs = (phba->slim2p.virt +
+                      offsetof(struct lpfc_sli2_slim, IOCBs));
 
        phba->hbqslimp.virt = dma_alloc_coherent(&phba->pcidev->dev,
                                                 lpfc_sli_hbq_size(),
@@ -2392,7 +2524,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        phba->fc_arbtov = FF_DEF_ARBTOV;
 
        INIT_LIST_HEAD(&phba->work_list);
-       phba->work_ha_mask = (HA_ERATT|HA_MBATT|HA_LATT);
+       phba->work_ha_mask = (HA_ERATT | HA_MBATT | HA_LATT);
        phba->work_ha_mask |= (HA_RXMASK << (LPFC_ELS_RING * 4));
 
        /* Initialize the wait queue head for the kernel thread */
@@ -2427,21 +2559,42 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        pci_set_drvdata(pdev, shost);
        phba->intr_type = NONE;
 
+       phba->MBslimaddr = phba->slim_memmap_p;
+       phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
+       phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
+       phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
+       phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
+
+       /* Configure and enable interrupt */
        if (phba->cfg_use_msi == 2) {
-               error = lpfc_enable_msix(phba);
-               if (!error)
-                       phba->intr_type = MSIX;
+               /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */
+               error = lpfc_sli_config_port(phba, 3);
+               if (error)
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                               "0427 Firmware not capable of SLI 3 mode.\n");
+               else {
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                               "0426 Firmware capable of SLI 3 mode.\n");
+                       /* Now, try to enable MSI-X interrupt mode */
+                       error = lpfc_enable_msix(phba);
+                       if (!error) {
+                               phba->intr_type = MSIX;
+                               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                               "0430 enable MSI-X mode.\n");
+                       }
+               }
        }
 
        /* Fallback to MSI if MSI-X initialization failed */
        if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
                retval = pci_enable_msi(phba->pcidev);
-               if (!retval)
+               if (!retval) {
                        phba->intr_type = MSI;
-               else
                        lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                                       "0452 Enable MSI failed, continuing "
-                                       "with IRQ\n");
+                                       "0473 enable MSI mode.\n");
+               } else
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                       "0452 enable IRQ mode.\n");
        }
 
        /* MSI-X is the only case the doesn't need to call request_irq */
@@ -2457,18 +2610,16 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
                        phba->intr_type = INTx;
        }
 
-       phba->MBslimaddr = phba->slim_memmap_p;
-       phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
-       phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
-       phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
-       phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
-
        if (lpfc_alloc_sysfs_attr(vport)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "1476 Failed to allocate sysfs attr\n");
                error = -ENOMEM;
                goto out_free_irq;
        }
 
        if (lpfc_sli_hba_setup(phba)) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "1477 Failed to set up hba\n");
                error = -ENODEV;
                goto out_remove_device;
        }
@@ -2487,6 +2638,16 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
                spin_unlock_irq(shost->host_lock);
        }
 
+       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                       "0428 Perform SCSI scan\n");
+       /* Send board arrival event to upper layer */
+       adapter_event.event_type = FC_REG_ADAPTER_EVENT;
+       adapter_event.subcategory = LPFC_EVENT_ARRIVAL;
+       fc_host_post_vendor_event(shost, fc_get_event_number(),
+               sizeof(adapter_event),
+               (char *) &adapter_event,
+               SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
+
        scsi_scan_host(shost);
 
        return 0;
@@ -2648,8 +2809,15 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
        struct lpfc_sli *psli = &phba->sli;
        struct lpfc_sli_ring  *pring;
 
-       if (state == pci_channel_io_perm_failure)
+       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);
                return PCI_ERS_RESULT_DISCONNECT;
+       }
 
        pci_disable_device(pdev);
        /*
@@ -2712,20 +2880,34 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
        /* Enable configured interrupt method */
        phba->intr_type = NONE;
        if (phba->cfg_use_msi == 2) {
-               error = lpfc_enable_msix(phba);
-               if (!error)
-                       phba->intr_type = MSIX;
+               /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */
+               error = lpfc_sli_config_port(phba, 3);
+               if (error)
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                               "0478 Firmware not capable of SLI 3 mode.\n");
+               else {
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                               "0479 Firmware capable of SLI 3 mode.\n");
+                       /* Now, try to enable MSI-X interrupt mode */
+                       error = lpfc_enable_msix(phba);
+                       if (!error) {
+                               phba->intr_type = MSIX;
+                               lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                               "0480 enable MSI-X mode.\n");
+                       }
+               }
        }
 
        /* Fallback to MSI if MSI-X initialization failed */
        if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
                retval = pci_enable_msi(phba->pcidev);
-               if (!retval)
+               if (!retval) {
                        phba->intr_type = MSI;
-               else
                        lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
-                                       "0470 Enable MSI failed, continuing "
-                                       "with IRQ\n");
+                                       "0481 enable MSI mode.\n");
+               } else
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                       "0470 enable IRQ mode.\n");
        }
 
        /* MSI-X is the only case the doesn't need to call request_irq */
@@ -2801,6 +2983,8 @@ static struct pci_device_id lpfc_id_table[] = {
                PCI_ANY_ID, PCI_ANY_ID, },
        {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR,
                PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HORNET,
+               PCI_ANY_ID, PCI_ANY_ID, },
        {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_SCSP,
                PCI_ANY_ID, PCI_ANY_ID, },
        {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZEPHYR_DCSP,
@@ -2831,6 +3015,12 @@ static struct pci_device_id lpfc_id_table[] = {
                PCI_ANY_ID, PCI_ANY_ID, },
        {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_S,
                PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_VF,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_PF,
+               PCI_ANY_ID, PCI_ANY_ID, },
+       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PROTEUS_S,
+               PCI_ANY_ID, PCI_ANY_ID, },
        { 0 }
 };
 
@@ -2889,7 +3079,8 @@ lpfc_init(void)
        error = pci_register_driver(&lpfc_driver);
        if (error) {
                fc_release_transport(lpfc_transport_template);
-               fc_release_transport(lpfc_vport_transport_template);
+               if (lpfc_enable_npiv)
+                       fc_release_transport(lpfc_vport_transport_template);
        }
 
        return error;