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 22843751c2ca..fa757b251f82 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) | |||
559 | phba->pport->work_port_events |= WORKER_HB_TMO; | 559 | phba->pport->work_port_events |= WORKER_HB_TMO; |
560 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); | 560 | spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag); |
561 | 561 | ||
562 | spin_lock_irqsave(&phba->hbalock, iflag); | ||
562 | if (phba->work_wait) | 563 | if (phba->work_wait) |
563 | wake_up(phba->work_wait); | 564 | wake_up(phba->work_wait); |
565 | spin_unlock_irqrestore(&phba->hbalock, iflag); | ||
564 | return; | 566 | return; |
565 | } | 567 | } |
566 | 568 | ||
@@ -714,12 +716,10 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | |||
714 | struct lpfc_vport *vport = phba->pport; | 716 | struct lpfc_vport *vport = phba->pport; |
715 | struct lpfc_sli *psli = &phba->sli; | 717 | struct lpfc_sli *psli = &phba->sli; |
716 | struct lpfc_sli_ring *pring; | 718 | struct lpfc_sli_ring *pring; |
717 | struct lpfc_vport **vports; | ||
718 | uint32_t event_data; | 719 | uint32_t event_data; |
719 | unsigned long temperature; | 720 | unsigned long temperature; |
720 | struct temp_event temp_event_data; | 721 | struct temp_event temp_event_data; |
721 | struct Scsi_Host *shost; | 722 | struct Scsi_Host *shost; |
722 | int i; | ||
723 | 723 | ||
724 | /* If the pci channel is offline, ignore possible errors, | 724 | /* If the pci channel is offline, ignore possible errors, |
725 | * since we cannot communicate with the pci card anyway. */ | 725 | * since we cannot communicate with the pci card anyway. */ |
@@ -729,25 +729,14 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | |||
729 | if (!phba->cfg_enable_hba_reset) | 729 | if (!phba->cfg_enable_hba_reset) |
730 | return; | 730 | return; |
731 | 731 | ||
732 | if (phba->work_hs & HS_FFER6 || | 732 | if (phba->work_hs & HS_FFER6) { |
733 | phba->work_hs & HS_FFER5) { | ||
734 | /* Re-establishing Link */ | 733 | /* Re-establishing Link */ |
735 | lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, | 734 | lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT, |
736 | "1301 Re-establishing Link " | 735 | "1301 Re-establishing Link " |
737 | "Data: x%x x%x x%x\n", | 736 | "Data: x%x x%x x%x\n", |
738 | phba->work_hs, | 737 | phba->work_hs, |
739 | phba->work_status[0], phba->work_status[1]); | 738 | phba->work_status[0], phba->work_status[1]); |
740 | vports = lpfc_create_vport_work_array(phba); | 739 | |
741 | if (vports != NULL) | ||
742 | for(i = 0; | ||
743 | i <= phba->max_vpi && vports[i] != NULL; | ||
744 | i++){ | ||
745 | shost = lpfc_shost_from_vport(vports[i]); | ||
746 | spin_lock_irq(shost->host_lock); | ||
747 | vports[i]->fc_flag |= FC_ESTABLISH_LINK; | ||
748 | spin_unlock_irq(shost->host_lock); | ||
749 | } | ||
750 | lpfc_destroy_vport_work_array(phba, vports); | ||
751 | spin_lock_irq(&phba->hbalock); | 740 | spin_lock_irq(&phba->hbalock); |
752 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | 741 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; |
753 | spin_unlock_irq(&phba->hbalock); | 742 | spin_unlock_irq(&phba->hbalock); |
@@ -761,7 +750,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | |||
761 | pring = &psli->ring[psli->fcp_ring]; | 750 | pring = &psli->ring[psli->fcp_ring]; |
762 | lpfc_sli_abort_iocb_ring(phba, pring); | 751 | lpfc_sli_abort_iocb_ring(phba, pring); |
763 | 752 | ||
764 | |||
765 | /* | 753 | /* |
766 | * There was a firmware error. Take the hba offline and then | 754 | * There was a firmware error. Take the hba offline and then |
767 | * attempt to restart it. | 755 | * attempt to restart it. |
@@ -770,7 +758,6 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | |||
770 | lpfc_offline(phba); | 758 | lpfc_offline(phba); |
771 | lpfc_sli_brdrestart(phba); | 759 | lpfc_sli_brdrestart(phba); |
772 | if (lpfc_online(phba) == 0) { /* Initialize the HBA */ | 760 | if (lpfc_online(phba) == 0) { /* Initialize the HBA */ |
773 | mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); | ||
774 | lpfc_unblock_mgmt_io(phba); | 761 | lpfc_unblock_mgmt_io(phba); |
775 | return; | 762 | return; |
776 | } | 763 | } |
@@ -1454,6 +1441,13 @@ lpfc_cleanup(struct lpfc_vport *vport) | |||
1454 | NLP_SET_FREE_REQ(ndlp); | 1441 | NLP_SET_FREE_REQ(ndlp); |
1455 | spin_unlock_irq(&phba->ndlp_lock); | 1442 | spin_unlock_irq(&phba->ndlp_lock); |
1456 | 1443 | ||
1444 | if (vport->port_type != LPFC_PHYSICAL_PORT && | ||
1445 | ndlp->nlp_DID == Fabric_DID) { | ||
1446 | /* Just free up ndlp with Fabric_DID for vports */ | ||
1447 | lpfc_nlp_put(ndlp); | ||
1448 | continue; | ||
1449 | } | ||
1450 | |||
1457 | if (ndlp->nlp_type & NLP_FABRIC) | 1451 | if (ndlp->nlp_type & NLP_FABRIC) |
1458 | lpfc_disc_state_machine(vport, ndlp, NULL, | 1452 | lpfc_disc_state_machine(vport, ndlp, NULL, |
1459 | NLP_EVT_DEVICE_RECOVERY); | 1453 | NLP_EVT_DEVICE_RECOVERY); |
@@ -1491,31 +1485,6 @@ lpfc_cleanup(struct lpfc_vport *vport) | |||
1491 | return; | 1485 | return; |
1492 | } | 1486 | } |
1493 | 1487 | ||
1494 | static void | ||
1495 | lpfc_establish_link_tmo(unsigned long ptr) | ||
1496 | { | ||
1497 | struct lpfc_hba *phba = (struct lpfc_hba *) ptr; | ||
1498 | struct lpfc_vport **vports; | ||
1499 | unsigned long iflag; | ||
1500 | int i; | ||
1501 | |||
1502 | /* Re-establishing Link, timer expired */ | ||
1503 | lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT, | ||
1504 | "1300 Re-establishing Link, timer expired " | ||
1505 | "Data: x%x x%x\n", | ||
1506 | phba->pport->fc_flag, phba->pport->port_state); | ||
1507 | vports = lpfc_create_vport_work_array(phba); | ||
1508 | if (vports != NULL) | ||
1509 | for(i = 0; i <= phba->max_vpi && vports[i] != NULL; i++) { | ||
1510 | struct Scsi_Host *shost; | ||
1511 | shost = lpfc_shost_from_vport(vports[i]); | ||
1512 | spin_lock_irqsave(shost->host_lock, iflag); | ||
1513 | vports[i]->fc_flag &= ~FC_ESTABLISH_LINK; | ||
1514 | spin_unlock_irqrestore(shost->host_lock, iflag); | ||
1515 | } | ||
1516 | lpfc_destroy_vport_work_array(phba, vports); | ||
1517 | } | ||
1518 | |||
1519 | void | 1488 | void |
1520 | lpfc_stop_vport_timers(struct lpfc_vport *vport) | 1489 | lpfc_stop_vport_timers(struct lpfc_vport *vport) |
1521 | { | 1490 | { |
@@ -1529,7 +1498,6 @@ static void | |||
1529 | lpfc_stop_phba_timers(struct lpfc_hba *phba) | 1498 | lpfc_stop_phba_timers(struct lpfc_hba *phba) |
1530 | { | 1499 | { |
1531 | del_timer_sync(&phba->fcp_poll_timer); | 1500 | del_timer_sync(&phba->fcp_poll_timer); |
1532 | del_timer_sync(&phba->fc_estabtmo); | ||
1533 | lpfc_stop_vport_timers(phba->pport); | 1501 | lpfc_stop_vport_timers(phba->pport); |
1534 | del_timer_sync(&phba->sli.mbox_tmo); | 1502 | del_timer_sync(&phba->sli.mbox_tmo); |
1535 | del_timer_sync(&phba->fabric_block_timer); | 1503 | 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) | |||
2005 | phba->max_vpi = LPFC_MAX_VPI; | 1973 | phba->max_vpi = LPFC_MAX_VPI; |
2006 | 1974 | ||
2007 | /* Initialize timers used by driver */ | 1975 | /* Initialize timers used by driver */ |
2008 | init_timer(&phba->fc_estabtmo); | ||
2009 | phba->fc_estabtmo.function = lpfc_establish_link_tmo; | ||
2010 | phba->fc_estabtmo.data = (unsigned long)phba; | ||
2011 | |||
2012 | init_timer(&phba->hb_tmofunc); | 1976 | init_timer(&phba->hb_tmofunc); |
2013 | phba->hb_tmofunc.function = lpfc_hb_timeout; | 1977 | phba->hb_tmofunc.function = lpfc_hb_timeout; |
2014 | phba->hb_tmofunc.data = (unsigned long)phba; | 1978 | phba->hb_tmofunc.data = (unsigned long)phba; |
@@ -2406,6 +2370,7 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) | |||
2406 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 2370 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
2407 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; | 2371 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
2408 | struct lpfc_sli *psli = &phba->sli; | 2372 | struct lpfc_sli *psli = &phba->sli; |
2373 | int error, retval; | ||
2409 | 2374 | ||
2410 | dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n"); | 2375 | dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n"); |
2411 | if (pci_enable_device_mem(pdev)) { | 2376 | if (pci_enable_device_mem(pdev)) { |
@@ -2416,15 +2381,40 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) | |||
2416 | 2381 | ||
2417 | pci_set_master(pdev); | 2382 | pci_set_master(pdev); |
2418 | 2383 | ||
2419 | /* Re-establishing Link */ | ||
2420 | spin_lock_irq(shost->host_lock); | ||
2421 | phba->pport->fc_flag |= FC_ESTABLISH_LINK; | ||
2422 | spin_unlock_irq(shost->host_lock); | ||
2423 | |||
2424 | spin_lock_irq(&phba->hbalock); | 2384 | spin_lock_irq(&phba->hbalock); |
2425 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | 2385 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; |
2426 | spin_unlock_irq(&phba->hbalock); | 2386 | spin_unlock_irq(&phba->hbalock); |
2427 | 2387 | ||
2388 | /* Enable configured interrupt method */ | ||
2389 | phba->intr_type = NONE; | ||
2390 | if (phba->cfg_use_msi == 2) { | ||
2391 | error = lpfc_enable_msix(phba); | ||
2392 | if (!error) | ||
2393 | phba->intr_type = MSIX; | ||
2394 | } | ||
2395 | |||
2396 | /* Fallback to MSI if MSI-X initialization failed */ | ||
2397 | if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) { | ||
2398 | retval = pci_enable_msi(phba->pcidev); | ||
2399 | if (!retval) | ||
2400 | phba->intr_type = MSI; | ||
2401 | else | ||
2402 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2403 | "0470 Enable MSI failed, continuing " | ||
2404 | "with IRQ\n"); | ||
2405 | } | ||
2406 | |||
2407 | /* MSI-X is the only case the doesn't need to call request_irq */ | ||
2408 | if (phba->intr_type != MSIX) { | ||
2409 | retval = request_irq(phba->pcidev->irq, lpfc_intr_handler, | ||
2410 | IRQF_SHARED, LPFC_DRIVER_NAME, phba); | ||
2411 | if (retval) { | ||
2412 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
2413 | "0471 Enable interrupt handler " | ||
2414 | "failed\n"); | ||
2415 | } else if (phba->intr_type != MSI) | ||
2416 | phba->intr_type = INTx; | ||
2417 | } | ||
2428 | 2418 | ||
2429 | /* Take device offline; this will perform cleanup */ | 2419 | /* Take device offline; this will perform cleanup */ |
2430 | lpfc_offline(phba); | 2420 | lpfc_offline(phba); |
@@ -2445,9 +2435,7 @@ static void lpfc_io_resume(struct pci_dev *pdev) | |||
2445 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 2435 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
2446 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; | 2436 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
2447 | 2437 | ||
2448 | if (lpfc_online(phba) == 0) { | 2438 | lpfc_online(phba); |
2449 | mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60); | ||
2450 | } | ||
2451 | } | 2439 | } |
2452 | 2440 | ||
2453 | static struct pci_device_id lpfc_id_table[] = { | 2441 | static struct pci_device_id lpfc_id_table[] = { |