]> err.no Git - linux-2.6/blobdiff - drivers/scsi/lpfc/lpfc_init.c
Merge branch 'kvm-updates-2.6.26' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6] / drivers / scsi / lpfc / lpfc_init.c
index 22843751c2caf1897bd240d514d5e85e3abf0d0d..fa757b251f8287505a21f271897598ae0141d3ea 100644 (file)
@@ -559,8 +559,10 @@ lpfc_hb_timeout(unsigned long ptr)
                phba->pport->work_port_events |= WORKER_HB_TMO;
        spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
 
+       spin_lock_irqsave(&phba->hbalock, iflag);
        if (phba->work_wait)
                wake_up(phba->work_wait);
+       spin_unlock_irqrestore(&phba->hbalock, iflag);
        return;
 }
 
@@ -714,12 +716,10 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
        struct lpfc_vport *vport = phba->pport;
        struct lpfc_sli   *psli = &phba->sli;
        struct lpfc_sli_ring  *pring;
-       struct lpfc_vport **vports;
        uint32_t event_data;
        unsigned long temperature;
        struct temp_event temp_event_data;
        struct Scsi_Host  *shost;
-       int i;
 
        /* If the pci channel is offline, ignore possible errors,
         * since we cannot communicate with the pci card anyway. */
@@ -729,25 +729,14 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
        if (!phba->cfg_enable_hba_reset)
                return;
 
-       if (phba->work_hs & HS_FFER6 ||
-           phba->work_hs & HS_FFER5) {
+       if (phba->work_hs & HS_FFER6) {
                /* Re-establishing Link */
                lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
                                "1301 Re-establishing Link "
                                "Data: x%x x%x x%x\n",
                                phba->work_hs,
                                phba->work_status[0], phba->work_status[1]);
-               vports = lpfc_create_vport_work_array(phba);
-               if (vports != NULL)
-                       for(i = 0;
-                           i <= phba->max_vpi && vports[i] != NULL;
-                           i++){
-                               shost = lpfc_shost_from_vport(vports[i]);
-                               spin_lock_irq(shost->host_lock);
-                               vports[i]->fc_flag |= FC_ESTABLISH_LINK;
-                               spin_unlock_irq(shost->host_lock);
-                       }
-               lpfc_destroy_vport_work_array(phba, vports);
+
                spin_lock_irq(&phba->hbalock);
                psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
                spin_unlock_irq(&phba->hbalock);
@@ -761,7 +750,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
                pring = &psli->ring[psli->fcp_ring];
                lpfc_sli_abort_iocb_ring(phba, pring);
 
-
                /*
                 * There was a firmware error.  Take the hba offline and then
                 * attempt to restart it.
@@ -770,7 +758,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba)
                lpfc_offline(phba);
                lpfc_sli_brdrestart(phba);
                if (lpfc_online(phba) == 0) {   /* Initialize the HBA */
-                       mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
                        lpfc_unblock_mgmt_io(phba);
                        return;
                }
@@ -1454,6 +1441,13 @@ lpfc_cleanup(struct lpfc_vport *vport)
                        NLP_SET_FREE_REQ(ndlp);
                spin_unlock_irq(&phba->ndlp_lock);
 
+               if (vport->port_type != LPFC_PHYSICAL_PORT &&
+                   ndlp->nlp_DID == Fabric_DID) {
+                       /* Just free up ndlp with Fabric_DID for vports */
+                       lpfc_nlp_put(ndlp);
+                       continue;
+               }
+
                if (ndlp->nlp_type & NLP_FABRIC)
                        lpfc_disc_state_machine(vport, ndlp, NULL,
                                        NLP_EVT_DEVICE_RECOVERY);
@@ -1491,31 +1485,6 @@ lpfc_cleanup(struct lpfc_vport *vport)
        return;
 }
 
-static void
-lpfc_establish_link_tmo(unsigned long ptr)
-{
-       struct lpfc_hba   *phba = (struct lpfc_hba *) ptr;
-       struct lpfc_vport **vports;
-       unsigned long iflag;
-       int i;
-
-       /* Re-establishing Link, timer expired */
-       lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
-                       "1300 Re-establishing Link, timer expired "
-                       "Data: x%x x%x\n",
-                       phba->pport->fc_flag, phba->pport->port_state);
-       vports = lpfc_create_vport_work_array(phba);
-       if (vports != NULL)
-               for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) {
-                       struct Scsi_Host *shost;
-                       shost = lpfc_shost_from_vport(vports[i]);
-                       spin_lock_irqsave(shost->host_lock, iflag);
-                       vports[i]->fc_flag &= ~FC_ESTABLISH_LINK;
-                       spin_unlock_irqrestore(shost->host_lock, iflag);
-               }
-       lpfc_destroy_vport_work_array(phba, vports);
-}
-
 void
 lpfc_stop_vport_timers(struct lpfc_vport *vport)
 {
@@ -1529,7 +1498,6 @@ static void
 lpfc_stop_phba_timers(struct lpfc_hba *phba)
 {
        del_timer_sync(&phba->fcp_poll_timer);
-       del_timer_sync(&phba->fc_estabtmo);
        lpfc_stop_vport_timers(phba->pport);
        del_timer_sync(&phba->sli.mbox_tmo);
        del_timer_sync(&phba->fabric_block_timer);
@@ -2005,10 +1973,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
        phba->max_vpi = LPFC_MAX_VPI;
 
        /* Initialize timers used by driver */
-       init_timer(&phba->fc_estabtmo);
-       phba->fc_estabtmo.function = lpfc_establish_link_tmo;
-       phba->fc_estabtmo.data = (unsigned long)phba;
-
        init_timer(&phba->hb_tmofunc);
        phba->hb_tmofunc.function = lpfc_hb_timeout;
        phba->hb_tmofunc.data = (unsigned long)phba;
@@ -2406,6 +2370,7 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
        struct lpfc_sli *psli = &phba->sli;
+       int error, retval;
 
        dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
        if (pci_enable_device_mem(pdev)) {
@@ -2416,15 +2381,40 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
 
        pci_set_master(pdev);
 
-       /* Re-establishing Link */
-       spin_lock_irq(shost->host_lock);
-       phba->pport->fc_flag |= FC_ESTABLISH_LINK;
-       spin_unlock_irq(shost->host_lock);
-
        spin_lock_irq(&phba->hbalock);
        psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
        spin_unlock_irq(&phba->hbalock);
 
+       /* 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;
+       }
+
+       /* 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)
+                       phba->intr_type = MSI;
+               else
+                       lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
+                                       "0470 Enable MSI failed, continuing "
+                                       "with IRQ\n");
+       }
+
+       /* MSI-X is the only case the doesn't need to call request_irq */
+       if (phba->intr_type != MSIX) {
+               retval = request_irq(phba->pcidev->irq, lpfc_intr_handler,
+                                    IRQF_SHARED, LPFC_DRIVER_NAME, phba);
+               if (retval) {
+                       lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+                                       "0471 Enable interrupt handler "
+                                       "failed\n");
+               } else if (phba->intr_type != MSI)
+                       phba->intr_type = INTx;
+       }
 
        /* Take device offline; this will perform cleanup */
        lpfc_offline(phba);
@@ -2445,9 +2435,7 @@ static void lpfc_io_resume(struct pci_dev *pdev)
        struct Scsi_Host *shost = pci_get_drvdata(pdev);
        struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
 
-       if (lpfc_online(phba) == 0) {
-               mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
-       }
+       lpfc_online(phba);
 }
 
 static struct pci_device_id lpfc_id_table[] = {