diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 98 |
1 files changed, 43 insertions, 55 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 2284375..fa757b2 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -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[] = { |