Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] lpfc 8.3.0 : Add active interrupt test for enabling MSI/MSI-X/INTx

Per the recent discussions at the Linux Plumbers Conference, when
enabling MSI or MSI-X, generate a test interrupt to verify the
interrupt routing is working properly. If the test interrupt fails,
fall back to MSI first, and if that fails as well, to INTx. If the
interrupt test fails with INTx, log an error and fail the PCI probe.

Also changed the use of spin_(lock|unlock) to the _irq(save|restore)
variants in the interrupt handlers because with multi-message MSI-X,
both interrupt handlers can now run in parallel.

Signed-off-by: James Smart <James.Smart@emulex.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>

authored by

James Smart and committed by
James Bottomley
5b75da2f eaf15d5b

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