aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/lpfc/lpfc.h2
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c410
-rw-r--r--drivers/scsi/lpfc/lpfc_mbox.c6
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c38
4 files changed, 302 insertions, 154 deletions
diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 030f9eb46f2a..fee14ae9353d 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -592,6 +592,8 @@ struct lpfc_hba {
592 592
593 struct fc_host_statistics link_stats; 593 struct fc_host_statistics link_stats;
594 enum intr_type_t intr_type; 594 enum intr_type_t intr_type;
595 uint32_t intr_mode;
596#define LPFC_INTR_ERROR 0xFFFFFFFF
595 struct msix_entry msix_entries[LPFC_MSIX_VECTORS]; 597 struct msix_entry msix_entries[LPFC_MSIX_VECTORS];
596 598
597 struct list_head port_list; 599 struct list_head port_list;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 4516d627deb9..e07f12a0871b 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2274,8 +2274,7 @@ lpfc_enable_msix(struct lpfc_hba *phba)
2274 ARRAY_SIZE(phba->msix_entries)); 2274 ARRAY_SIZE(phba->msix_entries));
2275 if (rc) { 2275 if (rc) {
2276 lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 2276 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2277 "0420 Enable MSI-X failed (%d), continuing " 2277 "0420 PCI enable MSI-X failed (%d)\n", rc);
2278 "with MSI\n", rc);
2279 goto msi_fail_out; 2278 goto msi_fail_out;
2280 } else 2279 } else
2281 for (i = 0; i < LPFC_MSIX_VECTORS; i++) 2280 for (i = 0; i < LPFC_MSIX_VECTORS; i++)
@@ -2292,9 +2291,9 @@ lpfc_enable_msix(struct lpfc_hba *phba)
2292 rc = request_irq(phba->msix_entries[0].vector, &lpfc_sp_intr_handler, 2291 rc = request_irq(phba->msix_entries[0].vector, &lpfc_sp_intr_handler,
2293 IRQF_SHARED, LPFC_SP_DRIVER_HANDLER_NAME, phba); 2292 IRQF_SHARED, LPFC_SP_DRIVER_HANDLER_NAME, phba);
2294 if (rc) { 2293 if (rc) {
2295 lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 2294 lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
2296 "0421 MSI-X slow-path request_irq failed " 2295 "0421 MSI-X slow-path request_irq failed "
2297 "(%d), continuing with MSI\n", rc); 2296 "(%d)\n", rc);
2298 goto msi_fail_out; 2297 goto msi_fail_out;
2299 } 2298 }
2300 2299
@@ -2303,9 +2302,9 @@ lpfc_enable_msix(struct lpfc_hba *phba)
2303 IRQF_SHARED, LPFC_FP_DRIVER_HANDLER_NAME, phba); 2302 IRQF_SHARED, LPFC_FP_DRIVER_HANDLER_NAME, phba);
2304 2303
2305 if (rc) { 2304 if (rc) {
2306 lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 2305 lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
2307 "0429 MSI-X fast-path request_irq failed " 2306 "0429 MSI-X fast-path request_irq failed "
2308 "(%d), continuing with MSI\n", rc); 2307 "(%d)\n", rc);
2309 goto irq_fail_out; 2308 goto irq_fail_out;
2310 } 2309 }
2311 2310
@@ -2326,7 +2325,7 @@ lpfc_enable_msix(struct lpfc_hba *phba)
2326 goto mbx_fail_out; 2325 goto mbx_fail_out;
2327 rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); 2326 rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL);
2328 if (rc != MBX_SUCCESS) { 2327 if (rc != MBX_SUCCESS) {
2329 lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, 2328 lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX,
2330 "0351 Config MSI mailbox command failed, " 2329 "0351 Config MSI mailbox command failed, "
2331 "mbxCmd x%x, mbxStatus x%x\n", 2330 "mbxCmd x%x, mbxStatus x%x\n",
2332 pmb->mb.mbxCommand, pmb->mb.mbxStatus); 2331 pmb->mb.mbxCommand, pmb->mb.mbxStatus);
@@ -2375,6 +2374,195 @@ lpfc_disable_msix(struct lpfc_hba *phba)
2375} 2374}
2376 2375
2377/** 2376/**
2377 * lpfc_enable_msi: Enable MSI interrupt mode.
2378 * @phba: pointer to lpfc hba data structure.
2379 *
2380 * This routine is invoked to enable the MSI interrupt mode. The kernel
2381 * function pci_enable_msi() is called to enable the MSI vector. The
2382 * device driver is responsible for calling the request_irq() to register
2383 * MSI vector with a interrupt the handler, which is done in this function.
2384 *
2385 * Return codes
2386 * 0 - sucessful
2387 * other values - error
2388 */
2389static int
2390lpfc_enable_msi(struct lpfc_hba *phba)
2391{
2392 int rc;
2393
2394 rc = pci_enable_msi(phba->pcidev);
2395 if (!rc)
2396 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2397 "0462 PCI enable MSI mode success.\n");
2398 else {
2399 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2400 "0471 PCI enable MSI mode failed (%d)\n", rc);
2401 return rc;
2402 }
2403
2404 rc = request_irq(phba->pcidev->irq, lpfc_intr_handler,
2405 IRQF_SHARED, LPFC_DRIVER_NAME, phba);
2406 if (rc) {
2407 pci_disable_msi(phba->pcidev);
2408 lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
2409 "0478 MSI request_irq failed (%d)\n", rc);
2410 }
2411 return rc;
2412}
2413
2414/**
2415 * lpfc_disable_msi: Disable MSI interrupt mode.
2416 * @phba: pointer to lpfc hba data structure.
2417 *
2418 * This routine is invoked to disable the MSI interrupt mode. The driver
2419 * calls free_irq() on MSI vector it has done request_irq() on before
2420 * calling pci_disable_msi(). Failure to do so results in a BUG_ON() and
2421 * a device will be left with MSI enabled and leaks its vector.
2422 */
2423
2424static void
2425lpfc_disable_msi(struct lpfc_hba *phba)
2426{
2427 free_irq(phba->pcidev->irq, phba);
2428 pci_disable_msi(phba->pcidev);
2429 return;
2430}
2431
2432/**
2433 * lpfc_log_intr_mode: Log the active interrupt mode
2434 * @phba: pointer to lpfc hba data structure.
2435 * @intr_mode: active interrupt mode adopted.
2436 *
2437 * This routine it invoked to log the currently used active interrupt mode
2438 * to the device.
2439 */
2440static void
2441lpfc_log_intr_mode(struct lpfc_hba *phba, uint32_t intr_mode)
2442{
2443 switch (intr_mode) {
2444 case 0:
2445 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2446 "0470 Enable INTx interrupt mode.\n");
2447 break;
2448 case 1:
2449 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2450 "0481 Enabled MSI interrupt mode.\n");
2451 break;
2452 case 2:
2453 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2454 "0480 Enabled MSI-X interrupt mode.\n");
2455 break;
2456 default:
2457 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2458 "0482 Illegal interrupt mode.\n");
2459 break;
2460 }
2461 return;
2462}
2463
2464static void
2465lpfc_stop_port(struct lpfc_hba *phba)
2466{
2467 /* Clear all interrupt enable conditions */
2468 writel(0, phba->HCregaddr);
2469 readl(phba->HCregaddr); /* flush */
2470 /* Clear all pending interrupts */
2471 writel(0xffffffff, phba->HAregaddr);
2472 readl(phba->HAregaddr); /* flush */
2473
2474 /* Reset some HBA SLI setup states */
2475 lpfc_stop_phba_timers(phba);
2476 phba->pport->work_port_events = 0;
2477
2478 return;
2479}
2480
2481/**
2482 * lpfc_enable_intr: Enable device interrupt.
2483 * @phba: pointer to lpfc hba data structure.
2484 *
2485 * This routine is invoked to enable device interrupt and associate driver's
2486 * interrupt handler(s) to interrupt vector(s). Depends on the interrupt
2487 * mode configured to the driver, the driver will try to fallback from the
2488 * configured interrupt mode to an interrupt mode which is supported by the
2489 * platform, kernel, and device in the order of: MSI-X -> MSI -> IRQ.
2490 *
2491 * Return codes
2492 * 0 - sucessful
2493 * other values - error
2494 **/
2495static uint32_t
2496lpfc_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode)
2497{
2498 uint32_t intr_mode = LPFC_INTR_ERROR;
2499 int retval;
2500
2501 if (cfg_mode == 2) {
2502 /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */
2503 retval = lpfc_sli_config_port(phba, 3);
2504 if (!retval) {
2505 /* Now, try to enable MSI-X interrupt mode */
2506 retval = lpfc_enable_msix(phba);
2507 if (!retval) {
2508 /* Indicate initialization to MSI-X mode */
2509 phba->intr_type = MSIX;
2510 intr_mode = 2;
2511 }
2512 }
2513 }
2514
2515 /* Fallback to MSI if MSI-X initialization failed */
2516 if (cfg_mode >= 1 && phba->intr_type == NONE) {
2517 retval = lpfc_enable_msi(phba);
2518 if (!retval) {
2519 /* Indicate initialization to MSI mode */
2520 phba->intr_type = MSI;
2521 intr_mode = 1;
2522 }
2523 }
2524
2525 /* Fallback to INTx if both MSI-X/MSI initalization failed */
2526 if (phba->intr_type == NONE) {
2527 retval = request_irq(phba->pcidev->irq, lpfc_intr_handler,
2528 IRQF_SHARED, LPFC_DRIVER_NAME, phba);
2529 if (!retval) {
2530 /* Indicate initialization to INTx mode */
2531 phba->intr_type = INTx;
2532 intr_mode = 0;
2533 }
2534 }
2535 return intr_mode;
2536}
2537
2538/**
2539 * lpfc_disable_intr: Disable device interrupt.
2540 * @phba: pointer to lpfc hba data structure.
2541 *
2542 * This routine is invoked to disable device interrupt and disassociate the
2543 * driver's interrupt handler(s) from interrupt vector(s). Depending on the
2544 * interrupt mode, the driver will release the interrupt vector(s) for the
2545 * message signaled interrupt.
2546 **/
2547static void
2548lpfc_disable_intr(struct lpfc_hba *phba)
2549{
2550 /* Disable the currently initialized interrupt mode */
2551 if (phba->intr_type == MSIX)
2552 lpfc_disable_msix(phba);
2553 else if (phba->intr_type == MSI)
2554 lpfc_disable_msi(phba);
2555 else if (phba->intr_type == INTx)
2556 free_irq(phba->pcidev->irq, phba);
2557
2558 /* Reset interrupt management states */
2559 phba->intr_type = NONE;
2560 phba->sli.slistat.sli_intr = 0;
2561
2562 return;
2563}
2564
2565/**
2378 * lpfc_pci_probe_one: lpfc PCI probe func to register device to PCI subsystem. 2566 * lpfc_pci_probe_one: lpfc PCI probe func to register device to PCI subsystem.
2379 * @pdev: pointer to PCI device 2567 * @pdev: pointer to PCI device
2380 * @pid: pointer to PCI device identifier 2568 * @pid: pointer to PCI device identifier
@@ -2404,6 +2592,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
2404 int error = -ENODEV, retval; 2592 int error = -ENODEV, retval;
2405 int i, hbq_count; 2593 int i, hbq_count;
2406 uint16_t iotag; 2594 uint16_t iotag;
2595 uint32_t cfg_mode, intr_mode;
2407 int bars = pci_select_bars(pdev, IORESOURCE_MEM); 2596 int bars = pci_select_bars(pdev, IORESOURCE_MEM);
2408 struct lpfc_adapter_event_header adapter_event; 2597 struct lpfc_adapter_event_header adapter_event;
2409 2598
@@ -2606,7 +2795,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
2606 lpfc_debugfs_initialize(vport); 2795 lpfc_debugfs_initialize(vport);
2607 2796
2608 pci_set_drvdata(pdev, shost); 2797 pci_set_drvdata(pdev, shost);
2609 phba->intr_type = NONE;
2610 2798
2611 phba->MBslimaddr = phba->slim_memmap_p; 2799 phba->MBslimaddr = phba->slim_memmap_p;
2612 phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET; 2800 phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
@@ -2614,63 +2802,58 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
2614 phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET; 2802 phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
2615 phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET; 2803 phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
2616 2804
2617 /* Configure and enable interrupt */ 2805 /* Configure sysfs attributes */
2618 if (phba->cfg_use_msi == 2) {
2619 /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */
2620 error = lpfc_sli_config_port(phba, 3);
2621 if (error)
2622 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2623 "0427 Firmware not capable of SLI 3 mode.\n");
2624 else {
2625 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2626 "0426 Firmware capable of SLI 3 mode.\n");
2627 /* Now, try to enable MSI-X interrupt mode */
2628 error = lpfc_enable_msix(phba);
2629 if (!error) {
2630 phba->intr_type = MSIX;
2631 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2632 "0430 enable MSI-X mode.\n");
2633 }
2634 }
2635 }
2636
2637 /* Fallback to MSI if MSI-X initialization failed */
2638 if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
2639 retval = pci_enable_msi(phba->pcidev);
2640 if (!retval) {
2641 phba->intr_type = MSI;
2642 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2643 "0473 enable MSI mode.\n");
2644 } else
2645 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2646 "0452 enable IRQ mode.\n");
2647 }
2648
2649 /* MSI-X is the only case the doesn't need to call request_irq */
2650 if (phba->intr_type != MSIX) {
2651 retval = request_irq(phba->pcidev->irq, lpfc_intr_handler,
2652 IRQF_SHARED, LPFC_DRIVER_NAME, phba);
2653 if (retval) {
2654 lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0451 Enable "
2655 "interrupt handler failed\n");
2656 error = retval;
2657 goto out_disable_msi;
2658 } else if (phba->intr_type != MSI)
2659 phba->intr_type = INTx;
2660 }
2661
2662 if (lpfc_alloc_sysfs_attr(vport)) { 2806 if (lpfc_alloc_sysfs_attr(vport)) {
2663 lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 2807 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2664 "1476 Failed to allocate sysfs attr\n"); 2808 "1476 Failed to allocate sysfs attr\n");
2665 error = -ENOMEM; 2809 error = -ENOMEM;
2666 goto out_free_irq; 2810 goto out_destroy_port;
2667 } 2811 }
2668 2812
2669 if (lpfc_sli_hba_setup(phba)) { 2813 cfg_mode = phba->cfg_use_msi;
2670 lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 2814 while (true) {
2671 "1477 Failed to set up hba\n"); 2815 /* Configure and enable interrupt */
2672 error = -ENODEV; 2816 intr_mode = lpfc_enable_intr(phba, cfg_mode);
2673 goto out_remove_device; 2817 if (intr_mode == LPFC_INTR_ERROR) {
2818 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2819 "0426 Failed to enable interrupt.\n");
2820 goto out_free_sysfs_attr;
2821 }
2822 /* HBA SLI setup */
2823 if (lpfc_sli_hba_setup(phba)) {
2824 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2825 "1477 Failed to set up hba\n");
2826 error = -ENODEV;
2827 goto out_remove_device;
2828 }
2829
2830 /* Wait 50ms for the interrupts of previous mailbox commands */
2831 msleep(50);
2832 /* Check active interrupts received */
2833 if (phba->sli.slistat.sli_intr > LPFC_MSIX_VECTORS) {
2834 /* Log the current active interrupt mode */
2835 phba->intr_mode = intr_mode;
2836 lpfc_log_intr_mode(phba, intr_mode);
2837 break;
2838 } else {
2839 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
2840 "0451 Configure interrupt mode (%d) "
2841 "failed active interrupt test.\n",
2842 intr_mode);
2843 if (intr_mode == 0) {
2844 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2845 "0479 Failed to enable "
2846 "interrupt.\n");
2847 error = -ENODEV;
2848 goto out_remove_device;
2849 }
2850 /* Stop HBA SLI setups */
2851 lpfc_stop_port(phba);
2852 /* Disable the current interrupt mode */
2853 lpfc_disable_intr(phba);
2854 /* Try next level of interrupt mode */
2855 cfg_mode = --intr_mode;
2856 }
2674 } 2857 }
2675 2858
2676 /* 2859 /*
@@ -2700,22 +2883,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
2700 return 0; 2883 return 0;
2701 2884
2702out_remove_device: 2885out_remove_device:
2703 lpfc_free_sysfs_attr(vport);
2704 spin_lock_irq(shost->host_lock); 2886 spin_lock_irq(shost->host_lock);
2705 vport->load_flag |= FC_UNLOADING; 2887 vport->load_flag |= FC_UNLOADING;
2706 spin_unlock_irq(shost->host_lock); 2888 spin_unlock_irq(shost->host_lock);
2707out_free_irq:
2708 lpfc_stop_phba_timers(phba); 2889 lpfc_stop_phba_timers(phba);
2709 phba->pport->work_port_events = 0; 2890 phba->pport->work_port_events = 0;
2710 2891 lpfc_disable_intr(phba);
2711 if (phba->intr_type == MSIX) 2892out_free_sysfs_attr:
2712 lpfc_disable_msix(phba); 2893 lpfc_free_sysfs_attr(vport);
2713 else 2894out_destroy_port:
2714 free_irq(phba->pcidev->irq, phba);
2715
2716out_disable_msi:
2717 if (phba->intr_type == MSI)
2718 pci_disable_msi(phba->pcidev);
2719 destroy_port(vport); 2895 destroy_port(vport);
2720out_kthread_stop: 2896out_kthread_stop:
2721 kthread_stop(phba->worker_thread); 2897 kthread_stop(phba->worker_thread);
@@ -2804,13 +2980,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
2804 2980
2805 lpfc_debugfs_terminate(vport); 2981 lpfc_debugfs_terminate(vport);
2806 2982
2807 if (phba->intr_type == MSIX) 2983 /* Disable interrupt */
2808 lpfc_disable_msix(phba); 2984 lpfc_disable_intr(phba);
2809 else {
2810 free_irq(phba->pcidev->irq, phba);
2811 if (phba->intr_type == MSI)
2812 pci_disable_msi(phba->pcidev);
2813 }
2814 2985
2815 pci_set_drvdata(pdev, NULL); 2986 pci_set_drvdata(pdev, NULL);
2816 scsi_host_put(shost); 2987 scsi_host_put(shost);
@@ -2908,6 +3079,7 @@ lpfc_pci_resume_one(struct pci_dev *pdev)
2908{ 3079{
2909 struct Scsi_Host *shost = pci_get_drvdata(pdev); 3080 struct Scsi_Host *shost = pci_get_drvdata(pdev);
2910 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 3081 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3082 uint32_t intr_mode;
2911 int error; 3083 int error;
2912 3084
2913 lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 3085 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
@@ -2930,19 +3102,22 @@ lpfc_pci_resume_one(struct pci_dev *pdev)
2930 return error; 3102 return error;
2931 } 3103 }
2932 3104
2933 /* Enable interrupt from device */ 3105 /* Configure and enable interrupt */
2934 error = lpfc_enable_intr(phba); 3106 intr_mode = lpfc_enable_intr(phba, phba->intr_mode);
2935 if (error) { 3107 if (intr_mode == LPFC_INTR_ERROR) {
2936 lpfc_printf_log(phba, KERN_ERR, LOG_INIT, 3108 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
2937 "0430 PM resume Failed to enable interrupt: " 3109 "0430 PM resume Failed to enable interrupt\n");
2938 "error=x%x.\n", error); 3110 return -EIO;
2939 return error; 3111 } else
2940 } 3112 phba->intr_mode = intr_mode;
2941 3113
2942 /* Restart HBA and bring it online */ 3114 /* Restart HBA and bring it online */
2943 lpfc_sli_brdrestart(phba); 3115 lpfc_sli_brdrestart(phba);
2944 lpfc_online(phba); 3116 lpfc_online(phba);
2945 3117
3118 /* Log the current active interrupt mode */
3119 lpfc_log_intr_mode(phba, phba->intr_mode);
3120
2946 return 0; 3121 return 0;
2947} 3122}
2948 3123
@@ -2989,13 +3164,8 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev,
2989 pring = &psli->ring[psli->fcp_ring]; 3164 pring = &psli->ring[psli->fcp_ring];
2990 lpfc_sli_abort_iocb_ring(phba, pring); 3165 lpfc_sli_abort_iocb_ring(phba, pring);
2991 3166
2992 if (phba->intr_type == MSIX) 3167 /* Disable interrupt */
2993 lpfc_disable_msix(phba); 3168 lpfc_disable_intr(phba);
2994 else {
2995 free_irq(phba->pcidev->irq, phba);
2996 if (phba->intr_type == MSI)
2997 pci_disable_msi(phba->pcidev);
2998 }
2999 3169
3000 /* Request a slot reset. */ 3170 /* Request a slot reset. */
3001 return PCI_ERS_RESULT_NEED_RESET; 3171 return PCI_ERS_RESULT_NEED_RESET;
@@ -3023,7 +3193,7 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
3023 struct Scsi_Host *shost = pci_get_drvdata(pdev); 3193 struct Scsi_Host *shost = pci_get_drvdata(pdev);
3024 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; 3194 struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba;
3025 struct lpfc_sli *psli = &phba->sli; 3195 struct lpfc_sli *psli = &phba->sli;
3026 int error, retval; 3196 uint32_t intr_mode;
3027 3197
3028 dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n"); 3198 dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n");
3029 if (pci_enable_device_mem(pdev)) { 3199 if (pci_enable_device_mem(pdev)) {
@@ -3040,55 +3210,23 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev)
3040 psli->sli_flag &= ~LPFC_SLI2_ACTIVE; 3210 psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
3041 spin_unlock_irq(&phba->hbalock); 3211 spin_unlock_irq(&phba->hbalock);
3042 3212
3043 /* Enable configured interrupt method */ 3213 /* Configure and enable interrupt */
3044 phba->intr_type = NONE; 3214 intr_mode = lpfc_enable_intr(phba, phba->intr_mode);
3045 if (phba->cfg_use_msi == 2) { 3215 if (intr_mode == LPFC_INTR_ERROR) {
3046 /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */ 3216 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
3047 error = lpfc_sli_config_port(phba, 3); 3217 "0427 Cannot re-enable interrupt after "
3048 if (error) 3218 "slot reset.\n");
3049 lpfc_printf_log(phba, KERN_INFO, LOG_INIT, 3219 return PCI_ERS_RESULT_DISCONNECT;
3050 "0478 Firmware not capable of SLI 3 mode.\n"); 3220 } else
3051 else { 3221 phba->intr_mode = intr_mode;
3052 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
3053 "0479 Firmware capable of SLI 3 mode.\n");
3054 /* Now, try to enable MSI-X interrupt mode */
3055 error = lpfc_enable_msix(phba);
3056 if (!error) {
3057 phba->intr_type = MSIX;
3058 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
3059 "0480 enable MSI-X mode.\n");
3060 }
3061 }
3062 }
3063
3064 /* Fallback to MSI if MSI-X initialization failed */
3065 if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) {
3066 retval = pci_enable_msi(phba->pcidev);
3067 if (!retval) {
3068 phba->intr_type = MSI;
3069 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
3070 "0481 enable MSI mode.\n");
3071 } else
3072 lpfc_printf_log(phba, KERN_INFO, LOG_INIT,
3073 "0470 enable IRQ mode.\n");
3074 }
3075
3076 /* MSI-X is the only case the doesn't need to call request_irq */
3077 if (phba->intr_type != MSIX) {
3078 retval = request_irq(phba->pcidev->irq, lpfc_intr_handler,
3079 IRQF_SHARED, LPFC_DRIVER_NAME, phba);
3080 if (retval) {
3081 lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
3082 "0471 Enable interrupt handler "
3083 "failed\n");
3084 } else if (phba->intr_type != MSI)
3085 phba->intr_type = INTx;
3086 }
3087 3222
3088 /* Take device offline; this will perform cleanup */ 3223 /* Take device offline; this will perform cleanup */
3089 lpfc_offline(phba); 3224 lpfc_offline(phba);
3090 lpfc_sli_brdrestart(phba); 3225 lpfc_sli_brdrestart(phba);
3091 3226
3227 /* Log the current active interrupt mode */
3228 lpfc_log_intr_mode(phba, phba->intr_mode);
3229
3092 return PCI_ERS_RESULT_RECOVERED; 3230 return PCI_ERS_RESULT_RECOVERED;
3093} 3231}
3094 3232
diff --git a/drivers/scsi/lpfc/lpfc_mbox.c b/drivers/scsi/lpfc/lpfc_mbox.c
index 5bb376baba62..7c02a6c3b699 100644
--- a/drivers/scsi/lpfc/lpfc_mbox.c
+++ b/drivers/scsi/lpfc/lpfc_mbox.c
@@ -1315,10 +1315,12 @@ lpfc_mbox_get(struct lpfc_hba * phba)
1315void 1315void
1316lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) 1316lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq)
1317{ 1317{
1318 unsigned long iflag;
1319
1318 /* This function expects to be called from interrupt context */ 1320 /* This function expects to be called from interrupt context */
1319 spin_lock(&phba->hbalock); 1321 spin_lock_irqsave(&phba->hbalock, iflag);
1320 list_add_tail(&mbq->list, &phba->sli.mboxq_cmpl); 1322 list_add_tail(&mbq->list, &phba->sli.mboxq_cmpl);
1321 spin_unlock(&phba->hbalock); 1323 spin_unlock_irqrestore(&phba->hbalock, iflag);
1322 return; 1324 return;
1323} 1325}
1324 1326
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index eadc19346408..4e5b4ee121f1 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5238,6 +5238,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5238 uint32_t ha_copy; 5238 uint32_t ha_copy;
5239 uint32_t work_ha_copy; 5239 uint32_t work_ha_copy;
5240 unsigned long status; 5240 unsigned long status;
5241 unsigned long iflag;
5241 uint32_t control; 5242 uint32_t control;
5242 5243
5243 MAILBOX_t *mbox, *pmbox; 5244 MAILBOX_t *mbox, *pmbox;
@@ -5270,7 +5271,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5270 if (unlikely(phba->link_state < LPFC_LINK_DOWN)) 5271 if (unlikely(phba->link_state < LPFC_LINK_DOWN))
5271 return IRQ_NONE; 5272 return IRQ_NONE;
5272 /* Need to read HA REG for slow-path events */ 5273 /* Need to read HA REG for slow-path events */
5273 spin_lock(&phba->hbalock); 5274 spin_lock_irqsave(&phba->hbalock, iflag);
5274 ha_copy = readl(phba->HAregaddr); 5275 ha_copy = readl(phba->HAregaddr);
5275 /* If somebody is waiting to handle an eratt don't process it 5276 /* If somebody is waiting to handle an eratt don't process it
5276 * here. The brdkill function will do this. 5277 * here. The brdkill function will do this.
@@ -5290,7 +5291,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5290 writel((ha_copy & (HA_MBATT | HA_R2_CLR_MSK)), 5291 writel((ha_copy & (HA_MBATT | HA_R2_CLR_MSK)),
5291 phba->HAregaddr); 5292 phba->HAregaddr);
5292 readl(phba->HAregaddr); /* flush */ 5293 readl(phba->HAregaddr); /* flush */
5293 spin_unlock(&phba->hbalock); 5294 spin_unlock_irqrestore(&phba->hbalock, iflag);
5294 } else 5295 } else
5295 ha_copy = phba->ha_copy; 5296 ha_copy = phba->ha_copy;
5296 5297
@@ -5303,13 +5304,13 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5303 * Turn off Link Attention interrupts 5304 * Turn off Link Attention interrupts
5304 * until CLEAR_LA done 5305 * until CLEAR_LA done
5305 */ 5306 */
5306 spin_lock(&phba->hbalock); 5307 spin_lock_irqsave(&phba->hbalock, iflag);
5307 phba->sli.sli_flag &= ~LPFC_PROCESS_LA; 5308 phba->sli.sli_flag &= ~LPFC_PROCESS_LA;
5308 control = readl(phba->HCregaddr); 5309 control = readl(phba->HCregaddr);
5309 control &= ~HC_LAINT_ENA; 5310 control &= ~HC_LAINT_ENA;
5310 writel(control, phba->HCregaddr); 5311 writel(control, phba->HCregaddr);
5311 readl(phba->HCregaddr); /* flush */ 5312 readl(phba->HCregaddr); /* flush */
5312 spin_unlock(&phba->hbalock); 5313 spin_unlock_irqrestore(&phba->hbalock, iflag);
5313 } 5314 }
5314 else 5315 else
5315 work_ha_copy &= ~HA_LATT; 5316 work_ha_copy &= ~HA_LATT;
@@ -5324,7 +5325,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5324 (HA_RXMASK << (4*LPFC_ELS_RING))); 5325 (HA_RXMASK << (4*LPFC_ELS_RING)));
5325 status >>= (4*LPFC_ELS_RING); 5326 status >>= (4*LPFC_ELS_RING);
5326 if (status & HA_RXMASK) { 5327 if (status & HA_RXMASK) {
5327 spin_lock(&phba->hbalock); 5328 spin_lock_irqsave(&phba->hbalock, iflag);
5328 control = readl(phba->HCregaddr); 5329 control = readl(phba->HCregaddr);
5329 5330
5330 lpfc_debugfs_slow_ring_trc(phba, 5331 lpfc_debugfs_slow_ring_trc(phba,
@@ -5353,10 +5354,10 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5353 (uint32_t)((unsigned long) 5354 (uint32_t)((unsigned long)
5354 &phba->work_waitq)); 5355 &phba->work_waitq));
5355 } 5356 }
5356 spin_unlock(&phba->hbalock); 5357 spin_unlock_irqrestore(&phba->hbalock, iflag);
5357 } 5358 }
5358 } 5359 }
5359 spin_lock(&phba->hbalock); 5360 spin_lock_irqsave(&phba->hbalock, iflag);
5360 if (work_ha_copy & HA_ERATT) 5361 if (work_ha_copy & HA_ERATT)
5361 lpfc_sli_read_hs(phba); 5362 lpfc_sli_read_hs(phba);
5362 if ((work_ha_copy & HA_MBATT) && (phba->sli.mbox_active)) { 5363 if ((work_ha_copy & HA_MBATT) && (phba->sli.mbox_active)) {
@@ -5368,7 +5369,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5368 /* First check out the status word */ 5369 /* First check out the status word */
5369 lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t)); 5370 lpfc_sli_pcimem_bcopy(mbox, pmbox, sizeof(uint32_t));
5370 if (pmbox->mbxOwner != OWN_HOST) { 5371 if (pmbox->mbxOwner != OWN_HOST) {
5371 spin_unlock(&phba->hbalock); 5372 spin_unlock_irqrestore(&phba->hbalock, iflag);
5372 /* 5373 /*
5373 * Stray Mailbox Interrupt, mbxCommand <cmd> 5374 * Stray Mailbox Interrupt, mbxCommand <cmd>
5374 * mbxStatus <status> 5375 * mbxStatus <status>
@@ -5385,7 +5386,7 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5385 work_ha_copy &= ~HA_MBATT; 5386 work_ha_copy &= ~HA_MBATT;
5386 } else { 5387 } else {
5387 phba->sli.mbox_active = NULL; 5388 phba->sli.mbox_active = NULL;
5388 spin_unlock(&phba->hbalock); 5389 spin_unlock_irqrestore(&phba->hbalock, iflag);
5389 phba->last_completion_time = jiffies; 5390 phba->last_completion_time = jiffies;
5390 del_timer(&phba->sli.mbox_tmo); 5391 del_timer(&phba->sli.mbox_tmo);
5391 if (pmb->mbox_cmpl) { 5392 if (pmb->mbox_cmpl) {
@@ -5434,14 +5435,18 @@ lpfc_sp_intr_handler(int irq, void *dev_id)
5434 goto send_current_mbox; 5435 goto send_current_mbox;
5435 } 5436 }
5436 } 5437 }
5437 spin_lock(&phba->pport->work_port_lock); 5438 spin_lock_irqsave(
5439 &phba->pport->work_port_lock,
5440 iflag);
5438 phba->pport->work_port_events &= 5441 phba->pport->work_port_events &=
5439 ~WORKER_MBOX_TMO; 5442 ~WORKER_MBOX_TMO;
5440 spin_unlock(&phba->pport->work_port_lock); 5443 spin_unlock_irqrestore(
5444 &phba->pport->work_port_lock,
5445 iflag);
5441 lpfc_mbox_cmpl_put(phba, pmb); 5446 lpfc_mbox_cmpl_put(phba, pmb);
5442 } 5447 }
5443 } else 5448 } else
5444 spin_unlock(&phba->hbalock); 5449 spin_unlock_irqrestore(&phba->hbalock, iflag);
5445 5450
5446 if ((work_ha_copy & HA_MBATT) && 5451 if ((work_ha_copy & HA_MBATT) &&
5447 (phba->sli.mbox_active == NULL)) { 5452 (phba->sli.mbox_active == NULL)) {
@@ -5457,9 +5462,9 @@ send_current_mbox:
5457 "MBX_SUCCESS"); 5462 "MBX_SUCCESS");
5458 } 5463 }
5459 5464
5460 spin_lock(&phba->hbalock); 5465 spin_lock_irqsave(&phba->hbalock, iflag);
5461 phba->work_ha |= work_ha_copy; 5466 phba->work_ha |= work_ha_copy;
5462 spin_unlock(&phba->hbalock); 5467 spin_unlock_irqrestore(&phba->hbalock, iflag);
5463 lpfc_worker_wake_up(phba); 5468 lpfc_worker_wake_up(phba);
5464 } 5469 }
5465 return IRQ_HANDLED; 5470 return IRQ_HANDLED;
@@ -5491,6 +5496,7 @@ lpfc_fp_intr_handler(int irq, void *dev_id)
5491 struct lpfc_hba *phba; 5496 struct lpfc_hba *phba;
5492 uint32_t ha_copy; 5497 uint32_t ha_copy;
5493 unsigned long status; 5498 unsigned long status;
5499 unsigned long iflag;
5494 5500
5495 /* Get the driver's phba structure from the dev_id and 5501 /* Get the driver's phba structure from the dev_id and
5496 * assume the HBA is not interrupting. 5502 * assume the HBA is not interrupting.
@@ -5516,11 +5522,11 @@ lpfc_fp_intr_handler(int irq, void *dev_id)
5516 /* Need to read HA REG for FCP ring and other ring events */ 5522 /* Need to read HA REG for FCP ring and other ring events */
5517 ha_copy = readl(phba->HAregaddr); 5523 ha_copy = readl(phba->HAregaddr);
5518 /* Clear up only attention source related to fast-path */ 5524 /* Clear up only attention source related to fast-path */
5519 spin_lock(&phba->hbalock); 5525 spin_lock_irqsave(&phba->hbalock, iflag);
5520 writel((ha_copy & (HA_R0_CLR_MSK | HA_R1_CLR_MSK)), 5526 writel((ha_copy & (HA_R0_CLR_MSK | HA_R1_CLR_MSK)),
5521 phba->HAregaddr); 5527 phba->HAregaddr);
5522 readl(phba->HAregaddr); /* flush */ 5528 readl(phba->HAregaddr); /* flush */
5523 spin_unlock(&phba->hbalock); 5529 spin_unlock_irqrestore(&phba->hbalock, iflag);
5524 } else 5530 } else
5525 ha_copy = phba->ha_copy; 5531 ha_copy = phba->ha_copy;
5526 5532