diff options
-rw-r--r-- | drivers/scsi/lpfc/lpfc.h | 2 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 410 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_mbox.c | 6 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 38 |
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 | */ | ||
2389 | static int | ||
2390 | lpfc_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 | |||
2424 | static void | ||
2425 | lpfc_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 | */ | ||
2440 | static void | ||
2441 | lpfc_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 | |||
2464 | static void | ||
2465 | lpfc_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 | **/ | ||
2495 | static uint32_t | ||
2496 | lpfc_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 | **/ | ||
2547 | static void | ||
2548 | lpfc_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 | ||
2702 | out_remove_device: | 2885 | out_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); |
2707 | out_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) | 2892 | out_free_sysfs_attr: |
2712 | lpfc_disable_msix(phba); | 2893 | lpfc_free_sysfs_attr(vport); |
2713 | else | 2894 | out_destroy_port: |
2714 | free_irq(phba->pcidev->irq, phba); | ||
2715 | |||
2716 | out_disable_msi: | ||
2717 | if (phba->intr_type == MSI) | ||
2718 | pci_disable_msi(phba->pcidev); | ||
2719 | destroy_port(vport); | 2895 | destroy_port(vport); |
2720 | out_kthread_stop: | 2896 | out_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) | |||
1315 | void | 1315 | void |
1316 | lpfc_mbox_cmpl_put(struct lpfc_hba * phba, LPFC_MBOXQ_t * mbq) | 1316 | lpfc_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 | ||