Merge tag 'pci-v4.8-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci
[cascardo/linux.git] / drivers / scsi / lpfc / lpfc_init.c
index 3a0f3a4..734a042 100644 (file)
@@ -52,6 +52,7 @@
 #include "lpfc_crtn.h"
 #include "lpfc_vport.h"
 #include "lpfc_version.h"
+#include "lpfc_ids.h"
 
 char *_dump_buf_data;
 unsigned long _dump_buf_data_order;
@@ -568,7 +569,7 @@ lpfc_config_port_post(struct lpfc_hba *phba)
        phba->last_completion_time = jiffies;
        /* Set up error attention (ERATT) polling timer */
        mod_timer(&phba->eratt_poll,
-                 jiffies + msecs_to_jiffies(1000 * LPFC_ERATT_POLL_INTERVAL));
+                 jiffies + msecs_to_jiffies(1000 * phba->eratt_poll_interval));
 
        if (phba->hba_flag & LINK_DISABLED) {
                lpfc_printf_log(phba,
@@ -1587,35 +1588,39 @@ lpfc_sli4_port_sta_fn_reset(struct lpfc_hba *phba, int mbx_action,
        int rc;
        uint32_t intr_mode;
 
-       /*
-        * On error status condition, driver need to wait for port
-        * ready before performing reset.
-        */
-       rc = lpfc_sli4_pdev_status_reg_wait(phba);
-       if (!rc) {
-               /* need reset: attempt for port recovery */
-               if (en_rn_msg)
-                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                                       "2887 Reset Needed: Attempting Port "
-                                       "Recovery...\n");
-               lpfc_offline_prep(phba, mbx_action);
-               lpfc_offline(phba);
-               /* release interrupt for possible resource change */
-               lpfc_sli4_disable_intr(phba);
-               lpfc_sli_brdrestart(phba);
-               /* request and enable interrupt */
-               intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode);
-               if (intr_mode == LPFC_INTR_ERROR) {
-                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-                                       "3175 Failed to enable interrupt\n");
-                       return -EIO;
-               } else {
-                       phba->intr_mode = intr_mode;
-               }
-               rc = lpfc_online(phba);
-               if (rc == 0)
-                       lpfc_unblock_mgmt_io(phba);
+       if (bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf) ==
+           LPFC_SLI_INTF_IF_TYPE_2) {
+               /*
+                * On error status condition, driver need to wait for port
+                * ready before performing reset.
+                */
+               rc = lpfc_sli4_pdev_status_reg_wait(phba);
+               if (rc)
+                       return rc;
        }
+
+       /* need reset: attempt for port recovery */
+       if (en_rn_msg)
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "2887 Reset Needed: Attempting Port "
+                               "Recovery...\n");
+       lpfc_offline_prep(phba, mbx_action);
+       lpfc_offline(phba);
+       /* release interrupt for possible resource change */
+       lpfc_sli4_disable_intr(phba);
+       lpfc_sli_brdrestart(phba);
+       /* request and enable interrupt */
+       intr_mode = lpfc_sli4_enable_intr(phba, phba->intr_mode);
+       if (intr_mode == LPFC_INTR_ERROR) {
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "3175 Failed to enable interrupt\n");
+               return -EIO;
+       }
+       phba->intr_mode = intr_mode;
+       rc = lpfc_online(phba);
+       if (rc == 0)
+               lpfc_unblock_mgmt_io(phba);
+
        return rc;
 }
 
@@ -1636,10 +1641,11 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
        struct lpfc_register portstat_reg = {0};
        uint32_t reg_err1, reg_err2;
        uint32_t uerrlo_reg, uemasklo_reg;
-       uint32_t pci_rd_rc1, pci_rd_rc2;
+       uint32_t smphr_port_status = 0, pci_rd_rc1, pci_rd_rc2;
        bool en_rn_msg = true;
        struct temp_event temp_event_data;
-       int rc;
+       struct lpfc_register portsmphr_reg;
+       int rc, i;
 
        /* If the pci channel is offline, ignore possible errors, since
         * we cannot communicate with the pci card anyway.
@@ -1647,6 +1653,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
        if (pci_channel_offline(phba->pcidev))
                return;
 
+       memset(&portsmphr_reg, 0, sizeof(portsmphr_reg));
        if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
        switch (if_type) {
        case LPFC_SLI_INTF_IF_TYPE_0:
@@ -1659,6 +1666,55 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
                /* consider PCI bus read error as pci_channel_offline */
                if (pci_rd_rc1 == -EIO && pci_rd_rc2 == -EIO)
                        return;
+               if (!(phba->hba_flag & HBA_RECOVERABLE_UE)) {
+                       lpfc_sli4_offline_eratt(phba);
+                       return;
+               }
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "7623 Checking UE recoverable");
+
+               for (i = 0; i < phba->sli4_hba.ue_to_sr / 1000; i++) {
+                       if (lpfc_readl(phba->sli4_hba.PSMPHRregaddr,
+                                      &portsmphr_reg.word0))
+                               continue;
+
+                       smphr_port_status = bf_get(lpfc_port_smphr_port_status,
+                                                  &portsmphr_reg);
+                       if ((smphr_port_status & LPFC_PORT_SEM_MASK) ==
+                           LPFC_PORT_SEM_UE_RECOVERABLE)
+                               break;
+                       /*Sleep for 1Sec, before checking SEMAPHORE */
+                       msleep(1000);
+               }
+
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "4827 smphr_port_status x%x : Waited %dSec",
+                               smphr_port_status, i);
+
+               /* Recoverable UE, reset the HBA device */
+               if ((smphr_port_status & LPFC_PORT_SEM_MASK) ==
+                   LPFC_PORT_SEM_UE_RECOVERABLE) {
+                       for (i = 0; i < 20; i++) {
+                               msleep(1000);
+                               if (!lpfc_readl(phba->sli4_hba.PSMPHRregaddr,
+                                   &portsmphr_reg.word0) &&
+                                   (LPFC_POST_STAGE_PORT_READY ==
+                                    bf_get(lpfc_port_smphr_port_status,
+                                    &portsmphr_reg))) {
+                                       rc = lpfc_sli4_port_sta_fn_reset(phba,
+                                               LPFC_MBX_NO_WAIT, en_rn_msg);
+                                       if (rc == 0)
+                                               return;
+                                       lpfc_printf_log(phba,
+                                               KERN_ERR, LOG_INIT,
+                                               "4215 Failed to recover UE");
+                                       break;
+                               }
+                       }
+               }
+               lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                               "7624 Firmware not ready: Failing UE recovery,"
+                               " waited %dSec", i);
                lpfc_sli4_offline_eratt(phba);
                break;
 
@@ -1681,6 +1737,7 @@ lpfc_handle_eratt_s4(struct lpfc_hba *phba)
                                "taking port offline Data: x%x x%x\n",
                                reg_err1, reg_err2);
 
+                       phba->sfp_alarm |= LPFC_TRANSGRESSION_HIGH_TEMPERATURE;
                        temp_event_data.event_type = FC_REG_TEMPERATURE_EVENT;
                        temp_event_data.event_code = LPFC_CRIT_TEMP;
                        temp_event_data.data = 0xFFFFFFFF;
@@ -3985,6 +4042,8 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
 {
        struct lpfc_dmabuf *mp;
        LPFC_MBOXQ_t *pmb;
+       MAILBOX_t *mb;
+       struct lpfc_mbx_read_top *la;
        int rc;
 
        if (bf_get(lpfc_trailer_type, acqe_fc) !=
@@ -4055,6 +4114,24 @@ lpfc_sli4_async_fc_evt(struct lpfc_hba *phba, struct lpfc_acqe_fc_la *acqe_fc)
        pmb->mbox_cmpl = lpfc_mbx_cmpl_read_topology;
        pmb->vport = phba->pport;
 
+       if (phba->sli4_hba.link_state.status != LPFC_FC_LA_TYPE_LINK_UP) {
+               /* Parse and translate status field */
+               mb = &pmb->u.mb;
+               mb->mbxStatus = lpfc_sli4_parse_latt_fault(phba,
+                                                          (void *)acqe_fc);
+
+               /* Parse and translate link attention fields */
+               la = (struct lpfc_mbx_read_top *)&pmb->u.mb.un.varReadTop;
+               la->eventTag = acqe_fc->event_tag;
+               bf_set(lpfc_mbx_read_top_att_type, la,
+                      LPFC_FC_LA_TYPE_LINK_DOWN);
+
+               /* Invoke the mailbox command callback function */
+               lpfc_mbx_cmpl_read_topology(phba, pmb);
+
+               return;
+       }
+
        rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
        if (rc == MBX_NOT_FINISHED)
                goto out_free_dmabuf;
@@ -4107,6 +4184,7 @@ lpfc_sli4_async_sli_evt(struct lpfc_hba *phba, struct lpfc_acqe_sli *acqe_sli)
                                "3190 Over Temperature:%d Celsius- Port Name %c\n",
                                acqe_sli->event_data1, port_name);
 
+               phba->sfp_warning |= LPFC_TRANSGRESSION_HIGH_TEMPERATURE;
                shost = lpfc_shost_from_vport(phba->pport);
                fc_host_post_vendor_event(shost, fc_get_event_number(),
                                          sizeof(temp_event_data),
@@ -4408,7 +4486,8 @@ lpfc_sli4_async_fip_evt(struct lpfc_hba *phba,
                 * the corresponding FCF bit in the roundrobin bitmap.
                 */
                spin_lock_irq(&phba->hbalock);
-               if (phba->fcf.fcf_flag & FCF_DISCOVERY) {
+               if ((phba->fcf.fcf_flag & FCF_DISCOVERY) &&
+                   (phba->fcf.current_rec.fcf_indx != acqe_fip->index)) {
                        spin_unlock_irq(&phba->hbalock);
                        /* Update FLOGI FCF failover eligible FCF bmask */
                        lpfc_sli4_fcf_rr_index_clear(phba, acqe_fip->index);
@@ -5357,6 +5436,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
                        goto out_free_bsmbx;
                }
        }
+
        /*
         * Get sli4 parameters that override parameters from Port capabilities.
         * If this call fails, it isn't critical unless the SLI4 parameters come
@@ -6085,6 +6165,7 @@ lpfc_hba_alloc(struct pci_dev *pdev)
                kfree(phba);
                return NULL;
        }
+       phba->eratt_poll_interval = LPFC_ERATT_POLL_INTERVAL;
 
        spin_lock_init(&phba->ct_ev_lock);
        INIT_LIST_HEAD(&phba->ct_ev_waiters);
@@ -9521,6 +9602,14 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
                phba->fcp_embed_io = 1;
        else
                phba->fcp_embed_io = 0;
+
+       /*
+        * Check if the SLI port supports MDS Diagnostics
+        */
+       if (bf_get(cfg_mds_diags, mbx_sli4_parameters))
+               phba->mds_diags_support = 1;
+       else
+               phba->mds_diags_support = 0;
        return 0;
 }
 
@@ -11291,106 +11380,6 @@ lpfc_fof_queue_destroy(struct lpfc_hba *phba)
        return 0;
 }
 
-static struct pci_device_id lpfc_id_table[] = {
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_VIPER,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_FIREFLY,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_THOR,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PEGASUS,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_CENTAUR,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_DRAGONFLY,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SUPERFLY,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_RFLY,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_PFLY,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_SCSP,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_NEPTUNE_DCSP,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_SCSP,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_HELIOS_DCSP,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BMID,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BSMB,
-               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,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZMID,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_ZSMB,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_TFLY,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP101,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP10000S,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LP11000S,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_MID,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SMB,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_DCSP,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SCSP,
-               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, },
-       {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, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_BALIUS,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FC_VF,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_FCOE_VF,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G6_FC,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK_VF,
-               PCI_ANY_ID, PCI_ANY_ID, },
-       { 0 }
-};
-
 MODULE_DEVICE_TABLE(pci, lpfc_id_table);
 
 static const struct pci_error_handlers lpfc_err_handler = {
@@ -11445,21 +11434,17 @@ lpfc_init(void)
                printk(KERN_ERR "Could not register lpfcmgmt device, "
                        "misc_register returned with status %d", error);
 
-       if (lpfc_enable_npiv) {
-               lpfc_transport_functions.vport_create = lpfc_vport_create;
-               lpfc_transport_functions.vport_delete = lpfc_vport_delete;
-       }
+       lpfc_transport_functions.vport_create = lpfc_vport_create;
+       lpfc_transport_functions.vport_delete = lpfc_vport_delete;
        lpfc_transport_template =
                                fc_attach_transport(&lpfc_transport_functions);
        if (lpfc_transport_template == NULL)
                return -ENOMEM;
-       if (lpfc_enable_npiv) {
-               lpfc_vport_transport_template =
-                       fc_attach_transport(&lpfc_vport_transport_functions);
-               if (lpfc_vport_transport_template == NULL) {
-                       fc_release_transport(lpfc_transport_template);
-                       return -ENOMEM;
-               }
+       lpfc_vport_transport_template =
+               fc_attach_transport(&lpfc_vport_transport_functions);
+       if (lpfc_vport_transport_template == NULL) {
+               fc_release_transport(lpfc_transport_template);
+               return -ENOMEM;
        }
 
        /* Initialize in case vector mapping is needed */
@@ -11471,8 +11456,7 @@ lpfc_init(void)
        error = pci_register_driver(&lpfc_driver);
        if (error) {
                fc_release_transport(lpfc_transport_template);
-               if (lpfc_enable_npiv)
-                       fc_release_transport(lpfc_vport_transport_template);
+               fc_release_transport(lpfc_vport_transport_template);
        }
 
        return error;
@@ -11491,8 +11475,7 @@ lpfc_exit(void)
        misc_deregister(&lpfc_mgmt_dev);
        pci_unregister_driver(&lpfc_driver);
        fc_release_transport(lpfc_transport_template);
-       if (lpfc_enable_npiv)
-               fc_release_transport(lpfc_vport_transport_template);
+       fc_release_transport(lpfc_vport_transport_template);
        if (_dump_buf_data) {
                printk(KERN_ERR "9062 BLKGRD: freeing %lu pages for "
                                "_dump_buf_data at 0x%p\n",