diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 685 |
1 files changed, 541 insertions, 144 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 909be3301bba..4c77038c8f1c 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -45,6 +45,12 @@ | |||
45 | #include "lpfc_vport.h" | 45 | #include "lpfc_vport.h" |
46 | #include "lpfc_version.h" | 46 | #include "lpfc_version.h" |
47 | 47 | ||
48 | char *_dump_buf_data; | ||
49 | unsigned long _dump_buf_data_order; | ||
50 | char *_dump_buf_dif; | ||
51 | unsigned long _dump_buf_dif_order; | ||
52 | spinlock_t _dump_buf_lock; | ||
53 | |||
48 | static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int); | 54 | static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int); |
49 | static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *); | 55 | static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *); |
50 | static int lpfc_post_rcv_buf(struct lpfc_hba *); | 56 | static int lpfc_post_rcv_buf(struct lpfc_hba *); |
@@ -236,6 +242,51 @@ lpfc_config_async_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq) | |||
236 | } | 242 | } |
237 | 243 | ||
238 | /** | 244 | /** |
245 | * lpfc_dump_wakeup_param_cmpl: Completion handler for dump memory mailbox | ||
246 | * command used for getting wake up parameters. | ||
247 | * @phba: pointer to lpfc hba data structure. | ||
248 | * @pmboxq: pointer to the driver internal queue element for mailbox command. | ||
249 | * | ||
250 | * This is the completion handler for dump mailbox command for getting | ||
251 | * wake up parameters. When this command complete, the response contain | ||
252 | * Option rom version of the HBA. This function translate the version number | ||
253 | * into a human readable string and store it in OptionROMVersion. | ||
254 | **/ | ||
255 | static void | ||
256 | lpfc_dump_wakeup_param_cmpl(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) | ||
257 | { | ||
258 | struct prog_id *prg; | ||
259 | uint32_t prog_id_word; | ||
260 | char dist = ' '; | ||
261 | /* character array used for decoding dist type. */ | ||
262 | char dist_char[] = "nabx"; | ||
263 | |||
264 | if (pmboxq->mb.mbxStatus != MBX_SUCCESS) { | ||
265 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
266 | return; | ||
267 | } | ||
268 | |||
269 | prg = (struct prog_id *) &prog_id_word; | ||
270 | |||
271 | /* word 7 contain option rom version */ | ||
272 | prog_id_word = pmboxq->mb.un.varWords[7]; | ||
273 | |||
274 | /* Decode the Option rom version word to a readable string */ | ||
275 | if (prg->dist < 4) | ||
276 | dist = dist_char[prg->dist]; | ||
277 | |||
278 | if ((prg->dist == 3) && (prg->num == 0)) | ||
279 | sprintf(phba->OptionROMVersion, "%d.%d%d", | ||
280 | prg->ver, prg->rev, prg->lev); | ||
281 | else | ||
282 | sprintf(phba->OptionROMVersion, "%d.%d%d%c%d", | ||
283 | prg->ver, prg->rev, prg->lev, | ||
284 | dist, prg->num); | ||
285 | mempool_free(pmboxq, phba->mbox_mem_pool); | ||
286 | return; | ||
287 | } | ||
288 | |||
289 | /** | ||
239 | * lpfc_config_port_post: Perform lpfc initialization after config port. | 290 | * lpfc_config_port_post: Perform lpfc initialization after config port. |
240 | * @phba: pointer to lpfc hba data structure. | 291 | * @phba: pointer to lpfc hba data structure. |
241 | * | 292 | * |
@@ -482,6 +533,20 @@ lpfc_config_port_post(struct lpfc_hba *phba) | |||
482 | rc); | 533 | rc); |
483 | mempool_free(pmb, phba->mbox_mem_pool); | 534 | mempool_free(pmb, phba->mbox_mem_pool); |
484 | } | 535 | } |
536 | |||
537 | /* Get Option rom version */ | ||
538 | pmb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); | ||
539 | lpfc_dump_wakeup_param(phba, pmb); | ||
540 | pmb->mbox_cmpl = lpfc_dump_wakeup_param_cmpl; | ||
541 | pmb->vport = phba->pport; | ||
542 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT); | ||
543 | |||
544 | if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) { | ||
545 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0435 Adapter failed " | ||
546 | "to get Option ROM version status x%x\n.", rc); | ||
547 | mempool_free(pmb, phba->mbox_mem_pool); | ||
548 | } | ||
549 | |||
485 | return 0; | 550 | return 0; |
486 | } | 551 | } |
487 | 552 | ||
@@ -686,11 +751,6 @@ lpfc_hb_timeout_handler(struct lpfc_hba *phba) | |||
686 | return; | 751 | return; |
687 | 752 | ||
688 | spin_lock_irq(&phba->pport->work_port_lock); | 753 | spin_lock_irq(&phba->pport->work_port_lock); |
689 | /* If the timer is already canceled do nothing */ | ||
690 | if (!(phba->pport->work_port_events & WORKER_HB_TMO)) { | ||
691 | spin_unlock_irq(&phba->pport->work_port_lock); | ||
692 | return; | ||
693 | } | ||
694 | 754 | ||
695 | if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ, | 755 | if (time_after(phba->last_completion_time + LPFC_HB_MBOX_INTERVAL * HZ, |
696 | jiffies)) { | 756 | jiffies)) { |
@@ -833,8 +893,7 @@ lpfc_handle_eratt(struct lpfc_hba *phba) | |||
833 | fc_host_post_vendor_event(shost, fc_get_event_number(), | 893 | fc_host_post_vendor_event(shost, fc_get_event_number(), |
834 | sizeof(board_event), | 894 | sizeof(board_event), |
835 | (char *) &board_event, | 895 | (char *) &board_event, |
836 | SCSI_NL_VID_TYPE_PCI | 896 | LPFC_NL_VENDOR_ID); |
837 | | PCI_VENDOR_ID_EMULEX); | ||
838 | 897 | ||
839 | if (phba->work_hs & HS_FFER6) { | 898 | if (phba->work_hs & HS_FFER6) { |
840 | /* Re-establishing Link */ | 899 | /* Re-establishing Link */ |
@@ -1984,6 +2043,7 @@ lpfc_create_port(struct lpfc_hba *phba, int instance, struct device *dev) | |||
1984 | shost->max_lun = vport->cfg_max_luns; | 2043 | shost->max_lun = vport->cfg_max_luns; |
1985 | shost->this_id = -1; | 2044 | shost->this_id = -1; |
1986 | shost->max_cmd_len = 16; | 2045 | shost->max_cmd_len = 16; |
2046 | |||
1987 | /* | 2047 | /* |
1988 | * Set initial can_queue value since 0 is no longer supported and | 2048 | * Set initial can_queue value since 0 is no longer supported and |
1989 | * scsi_add_host will fail. This will be adjusted later based on the | 2049 | * scsi_add_host will fail. This will be adjusted later based on the |
@@ -2042,8 +2102,6 @@ destroy_port(struct lpfc_vport *vport) | |||
2042 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); | 2102 | struct Scsi_Host *shost = lpfc_shost_from_vport(vport); |
2043 | struct lpfc_hba *phba = vport->phba; | 2103 | struct lpfc_hba *phba = vport->phba; |
2044 | 2104 | ||
2045 | kfree(vport->vname); | ||
2046 | |||
2047 | lpfc_debugfs_terminate(vport); | 2105 | lpfc_debugfs_terminate(vport); |
2048 | fc_remove_host(shost); | 2106 | fc_remove_host(shost); |
2049 | scsi_remove_host(shost); | 2107 | scsi_remove_host(shost); |
@@ -2226,8 +2284,7 @@ lpfc_enable_msix(struct lpfc_hba *phba) | |||
2226 | ARRAY_SIZE(phba->msix_entries)); | 2284 | ARRAY_SIZE(phba->msix_entries)); |
2227 | if (rc) { | 2285 | if (rc) { |
2228 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 2286 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
2229 | "0420 Enable MSI-X failed (%d), continuing " | 2287 | "0420 PCI enable MSI-X failed (%d)\n", rc); |
2230 | "with MSI\n", rc); | ||
2231 | goto msi_fail_out; | 2288 | goto msi_fail_out; |
2232 | } else | 2289 | } else |
2233 | for (i = 0; i < LPFC_MSIX_VECTORS; i++) | 2290 | for (i = 0; i < LPFC_MSIX_VECTORS; i++) |
@@ -2244,9 +2301,9 @@ lpfc_enable_msix(struct lpfc_hba *phba) | |||
2244 | rc = request_irq(phba->msix_entries[0].vector, &lpfc_sp_intr_handler, | 2301 | rc = request_irq(phba->msix_entries[0].vector, &lpfc_sp_intr_handler, |
2245 | IRQF_SHARED, LPFC_SP_DRIVER_HANDLER_NAME, phba); | 2302 | IRQF_SHARED, LPFC_SP_DRIVER_HANDLER_NAME, phba); |
2246 | if (rc) { | 2303 | if (rc) { |
2247 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 2304 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, |
2248 | "0421 MSI-X slow-path request_irq failed " | 2305 | "0421 MSI-X slow-path request_irq failed " |
2249 | "(%d), continuing with MSI\n", rc); | 2306 | "(%d)\n", rc); |
2250 | goto msi_fail_out; | 2307 | goto msi_fail_out; |
2251 | } | 2308 | } |
2252 | 2309 | ||
@@ -2255,9 +2312,9 @@ lpfc_enable_msix(struct lpfc_hba *phba) | |||
2255 | IRQF_SHARED, LPFC_FP_DRIVER_HANDLER_NAME, phba); | 2312 | IRQF_SHARED, LPFC_FP_DRIVER_HANDLER_NAME, phba); |
2256 | 2313 | ||
2257 | if (rc) { | 2314 | if (rc) { |
2258 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 2315 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, |
2259 | "0429 MSI-X fast-path request_irq failed " | 2316 | "0429 MSI-X fast-path request_irq failed " |
2260 | "(%d), continuing with MSI\n", rc); | 2317 | "(%d)\n", rc); |
2261 | goto irq_fail_out; | 2318 | goto irq_fail_out; |
2262 | } | 2319 | } |
2263 | 2320 | ||
@@ -2278,7 +2335,7 @@ lpfc_enable_msix(struct lpfc_hba *phba) | |||
2278 | goto mbx_fail_out; | 2335 | goto mbx_fail_out; |
2279 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); | 2336 | rc = lpfc_sli_issue_mbox(phba, pmb, MBX_POLL); |
2280 | if (rc != MBX_SUCCESS) { | 2337 | if (rc != MBX_SUCCESS) { |
2281 | lpfc_printf_log(phba, KERN_ERR, LOG_MBOX, | 2338 | lpfc_printf_log(phba, KERN_WARNING, LOG_MBOX, |
2282 | "0351 Config MSI mailbox command failed, " | 2339 | "0351 Config MSI mailbox command failed, " |
2283 | "mbxCmd x%x, mbxStatus x%x\n", | 2340 | "mbxCmd x%x, mbxStatus x%x\n", |
2284 | pmb->mb.mbxCommand, pmb->mb.mbxStatus); | 2341 | pmb->mb.mbxCommand, pmb->mb.mbxStatus); |
@@ -2327,6 +2384,195 @@ lpfc_disable_msix(struct lpfc_hba *phba) | |||
2327 | } | 2384 | } |
2328 | 2385 | ||
2329 | /** | 2386 | /** |
2387 | * lpfc_enable_msi: Enable MSI interrupt mode. | ||
2388 | * @phba: pointer to lpfc hba data structure. | ||
2389 | * | ||
2390 | * This routine is invoked to enable the MSI interrupt mode. The kernel | ||
2391 | * function pci_enable_msi() is called to enable the MSI vector. The | ||
2392 | * device driver is responsible for calling the request_irq() to register | ||
2393 | * MSI vector with a interrupt the handler, which is done in this function. | ||
2394 | * | ||
2395 | * Return codes | ||
2396 | * 0 - sucessful | ||
2397 | * other values - error | ||
2398 | */ | ||
2399 | static int | ||
2400 | lpfc_enable_msi(struct lpfc_hba *phba) | ||
2401 | { | ||
2402 | int rc; | ||
2403 | |||
2404 | rc = pci_enable_msi(phba->pcidev); | ||
2405 | if (!rc) | ||
2406 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2407 | "0462 PCI enable MSI mode success.\n"); | ||
2408 | else { | ||
2409 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2410 | "0471 PCI enable MSI mode failed (%d)\n", rc); | ||
2411 | return rc; | ||
2412 | } | ||
2413 | |||
2414 | rc = request_irq(phba->pcidev->irq, lpfc_intr_handler, | ||
2415 | IRQF_SHARED, LPFC_DRIVER_NAME, phba); | ||
2416 | if (rc) { | ||
2417 | pci_disable_msi(phba->pcidev); | ||
2418 | lpfc_printf_log(phba, KERN_WARNING, LOG_INIT, | ||
2419 | "0478 MSI request_irq failed (%d)\n", rc); | ||
2420 | } | ||
2421 | return rc; | ||
2422 | } | ||
2423 | |||
2424 | /** | ||
2425 | * lpfc_disable_msi: Disable MSI interrupt mode. | ||
2426 | * @phba: pointer to lpfc hba data structure. | ||
2427 | * | ||
2428 | * This routine is invoked to disable the MSI interrupt mode. The driver | ||
2429 | * calls free_irq() on MSI vector it has done request_irq() on before | ||
2430 | * calling pci_disable_msi(). Failure to do so results in a BUG_ON() and | ||
2431 | * a device will be left with MSI enabled and leaks its vector. | ||
2432 | */ | ||
2433 | |||
2434 | static void | ||
2435 | lpfc_disable_msi(struct lpfc_hba *phba) | ||
2436 | { | ||
2437 | free_irq(phba->pcidev->irq, phba); | ||
2438 | pci_disable_msi(phba->pcidev); | ||
2439 | return; | ||
2440 | } | ||
2441 | |||
2442 | /** | ||
2443 | * lpfc_log_intr_mode: Log the active interrupt mode | ||
2444 | * @phba: pointer to lpfc hba data structure. | ||
2445 | * @intr_mode: active interrupt mode adopted. | ||
2446 | * | ||
2447 | * This routine it invoked to log the currently used active interrupt mode | ||
2448 | * to the device. | ||
2449 | */ | ||
2450 | static void | ||
2451 | lpfc_log_intr_mode(struct lpfc_hba *phba, uint32_t intr_mode) | ||
2452 | { | ||
2453 | switch (intr_mode) { | ||
2454 | case 0: | ||
2455 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2456 | "0470 Enable INTx interrupt mode.\n"); | ||
2457 | break; | ||
2458 | case 1: | ||
2459 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2460 | "0481 Enabled MSI interrupt mode.\n"); | ||
2461 | break; | ||
2462 | case 2: | ||
2463 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2464 | "0480 Enabled MSI-X interrupt mode.\n"); | ||
2465 | break; | ||
2466 | default: | ||
2467 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
2468 | "0482 Illegal interrupt mode.\n"); | ||
2469 | break; | ||
2470 | } | ||
2471 | return; | ||
2472 | } | ||
2473 | |||
2474 | static void | ||
2475 | lpfc_stop_port(struct lpfc_hba *phba) | ||
2476 | { | ||
2477 | /* Clear all interrupt enable conditions */ | ||
2478 | writel(0, phba->HCregaddr); | ||
2479 | readl(phba->HCregaddr); /* flush */ | ||
2480 | /* Clear all pending interrupts */ | ||
2481 | writel(0xffffffff, phba->HAregaddr); | ||
2482 | readl(phba->HAregaddr); /* flush */ | ||
2483 | |||
2484 | /* Reset some HBA SLI setup states */ | ||
2485 | lpfc_stop_phba_timers(phba); | ||
2486 | phba->pport->work_port_events = 0; | ||
2487 | |||
2488 | return; | ||
2489 | } | ||
2490 | |||
2491 | /** | ||
2492 | * lpfc_enable_intr: Enable device interrupt. | ||
2493 | * @phba: pointer to lpfc hba data structure. | ||
2494 | * | ||
2495 | * This routine is invoked to enable device interrupt and associate driver's | ||
2496 | * interrupt handler(s) to interrupt vector(s). Depends on the interrupt | ||
2497 | * mode configured to the driver, the driver will try to fallback from the | ||
2498 | * configured interrupt mode to an interrupt mode which is supported by the | ||
2499 | * platform, kernel, and device in the order of: MSI-X -> MSI -> IRQ. | ||
2500 | * | ||
2501 | * Return codes | ||
2502 | * 0 - sucessful | ||
2503 | * other values - error | ||
2504 | **/ | ||
2505 | static uint32_t | ||
2506 | lpfc_enable_intr(struct lpfc_hba *phba, uint32_t cfg_mode) | ||
2507 | { | ||
2508 | uint32_t intr_mode = LPFC_INTR_ERROR; | ||
2509 | int retval; | ||
2510 | |||
2511 | if (cfg_mode == 2) { | ||
2512 | /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */ | ||
2513 | retval = lpfc_sli_config_port(phba, 3); | ||
2514 | if (!retval) { | ||
2515 | /* Now, try to enable MSI-X interrupt mode */ | ||
2516 | retval = lpfc_enable_msix(phba); | ||
2517 | if (!retval) { | ||
2518 | /* Indicate initialization to MSI-X mode */ | ||
2519 | phba->intr_type = MSIX; | ||
2520 | intr_mode = 2; | ||
2521 | } | ||
2522 | } | ||
2523 | } | ||
2524 | |||
2525 | /* Fallback to MSI if MSI-X initialization failed */ | ||
2526 | if (cfg_mode >= 1 && phba->intr_type == NONE) { | ||
2527 | retval = lpfc_enable_msi(phba); | ||
2528 | if (!retval) { | ||
2529 | /* Indicate initialization to MSI mode */ | ||
2530 | phba->intr_type = MSI; | ||
2531 | intr_mode = 1; | ||
2532 | } | ||
2533 | } | ||
2534 | |||
2535 | /* Fallback to INTx if both MSI-X/MSI initalization failed */ | ||
2536 | if (phba->intr_type == NONE) { | ||
2537 | retval = request_irq(phba->pcidev->irq, lpfc_intr_handler, | ||
2538 | IRQF_SHARED, LPFC_DRIVER_NAME, phba); | ||
2539 | if (!retval) { | ||
2540 | /* Indicate initialization to INTx mode */ | ||
2541 | phba->intr_type = INTx; | ||
2542 | intr_mode = 0; | ||
2543 | } | ||
2544 | } | ||
2545 | return intr_mode; | ||
2546 | } | ||
2547 | |||
2548 | /** | ||
2549 | * lpfc_disable_intr: Disable device interrupt. | ||
2550 | * @phba: pointer to lpfc hba data structure. | ||
2551 | * | ||
2552 | * This routine is invoked to disable device interrupt and disassociate the | ||
2553 | * driver's interrupt handler(s) from interrupt vector(s). Depending on the | ||
2554 | * interrupt mode, the driver will release the interrupt vector(s) for the | ||
2555 | * message signaled interrupt. | ||
2556 | **/ | ||
2557 | static void | ||
2558 | lpfc_disable_intr(struct lpfc_hba *phba) | ||
2559 | { | ||
2560 | /* Disable the currently initialized interrupt mode */ | ||
2561 | if (phba->intr_type == MSIX) | ||
2562 | lpfc_disable_msix(phba); | ||
2563 | else if (phba->intr_type == MSI) | ||
2564 | lpfc_disable_msi(phba); | ||
2565 | else if (phba->intr_type == INTx) | ||
2566 | free_irq(phba->pcidev->irq, phba); | ||
2567 | |||
2568 | /* Reset interrupt management states */ | ||
2569 | phba->intr_type = NONE; | ||
2570 | phba->sli.slistat.sli_intr = 0; | ||
2571 | |||
2572 | return; | ||
2573 | } | ||
2574 | |||
2575 | /** | ||
2330 | * lpfc_pci_probe_one: lpfc PCI probe func to register device to PCI subsystem. | 2576 | * lpfc_pci_probe_one: lpfc PCI probe func to register device to PCI subsystem. |
2331 | * @pdev: pointer to PCI device | 2577 | * @pdev: pointer to PCI device |
2332 | * @pid: pointer to PCI device identifier | 2578 | * @pid: pointer to PCI device identifier |
@@ -2356,6 +2602,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
2356 | int error = -ENODEV, retval; | 2602 | int error = -ENODEV, retval; |
2357 | int i, hbq_count; | 2603 | int i, hbq_count; |
2358 | uint16_t iotag; | 2604 | uint16_t iotag; |
2605 | uint32_t cfg_mode, intr_mode; | ||
2359 | int bars = pci_select_bars(pdev, IORESOURCE_MEM); | 2606 | int bars = pci_select_bars(pdev, IORESOURCE_MEM); |
2360 | struct lpfc_adapter_event_header adapter_event; | 2607 | struct lpfc_adapter_event_header adapter_event; |
2361 | 2608 | ||
@@ -2409,6 +2656,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
2409 | phba->eratt_poll.data = (unsigned long) phba; | 2656 | phba->eratt_poll.data = (unsigned long) phba; |
2410 | 2657 | ||
2411 | pci_set_master(pdev); | 2658 | pci_set_master(pdev); |
2659 | pci_save_state(pdev); | ||
2412 | pci_try_set_mwi(pdev); | 2660 | pci_try_set_mwi(pdev); |
2413 | 2661 | ||
2414 | if (pci_set_dma_mask(phba->pcidev, DMA_64BIT_MASK) != 0) | 2662 | if (pci_set_dma_mask(phba->pcidev, DMA_64BIT_MASK) != 0) |
@@ -2557,7 +2805,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
2557 | lpfc_debugfs_initialize(vport); | 2805 | lpfc_debugfs_initialize(vport); |
2558 | 2806 | ||
2559 | pci_set_drvdata(pdev, shost); | 2807 | pci_set_drvdata(pdev, shost); |
2560 | phba->intr_type = NONE; | ||
2561 | 2808 | ||
2562 | phba->MBslimaddr = phba->slim_memmap_p; | 2809 | phba->MBslimaddr = phba->slim_memmap_p; |
2563 | phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET; | 2810 | phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET; |
@@ -2565,63 +2812,58 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
2565 | phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET; | 2812 | phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET; |
2566 | phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET; | 2813 | phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET; |
2567 | 2814 | ||
2568 | /* Configure and enable interrupt */ | 2815 | /* Configure sysfs attributes */ |
2569 | if (phba->cfg_use_msi == 2) { | ||
2570 | /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */ | ||
2571 | error = lpfc_sli_config_port(phba, 3); | ||
2572 | if (error) | ||
2573 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2574 | "0427 Firmware not capable of SLI 3 mode.\n"); | ||
2575 | else { | ||
2576 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2577 | "0426 Firmware capable of SLI 3 mode.\n"); | ||
2578 | /* Now, try to enable MSI-X interrupt mode */ | ||
2579 | error = lpfc_enable_msix(phba); | ||
2580 | if (!error) { | ||
2581 | phba->intr_type = MSIX; | ||
2582 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2583 | "0430 enable MSI-X mode.\n"); | ||
2584 | } | ||
2585 | } | ||
2586 | } | ||
2587 | |||
2588 | /* Fallback to MSI if MSI-X initialization failed */ | ||
2589 | if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) { | ||
2590 | retval = pci_enable_msi(phba->pcidev); | ||
2591 | if (!retval) { | ||
2592 | phba->intr_type = MSI; | ||
2593 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2594 | "0473 enable MSI mode.\n"); | ||
2595 | } else | ||
2596 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2597 | "0452 enable IRQ mode.\n"); | ||
2598 | } | ||
2599 | |||
2600 | /* MSI-X is the only case the doesn't need to call request_irq */ | ||
2601 | if (phba->intr_type != MSIX) { | ||
2602 | retval = request_irq(phba->pcidev->irq, lpfc_intr_handler, | ||
2603 | IRQF_SHARED, LPFC_DRIVER_NAME, phba); | ||
2604 | if (retval) { | ||
2605 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0451 Enable " | ||
2606 | "interrupt handler failed\n"); | ||
2607 | error = retval; | ||
2608 | goto out_disable_msi; | ||
2609 | } else if (phba->intr_type != MSI) | ||
2610 | phba->intr_type = INTx; | ||
2611 | } | ||
2612 | |||
2613 | if (lpfc_alloc_sysfs_attr(vport)) { | 2816 | if (lpfc_alloc_sysfs_attr(vport)) { |
2614 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 2817 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
2615 | "1476 Failed to allocate sysfs attr\n"); | 2818 | "1476 Failed to allocate sysfs attr\n"); |
2616 | error = -ENOMEM; | 2819 | error = -ENOMEM; |
2617 | goto out_free_irq; | 2820 | goto out_destroy_port; |
2618 | } | 2821 | } |
2619 | 2822 | ||
2620 | if (lpfc_sli_hba_setup(phba)) { | 2823 | cfg_mode = phba->cfg_use_msi; |
2621 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 2824 | while (true) { |
2622 | "1477 Failed to set up hba\n"); | 2825 | /* Configure and enable interrupt */ |
2623 | error = -ENODEV; | 2826 | intr_mode = lpfc_enable_intr(phba, cfg_mode); |
2624 | goto out_remove_device; | 2827 | if (intr_mode == LPFC_INTR_ERROR) { |
2828 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
2829 | "0426 Failed to enable interrupt.\n"); | ||
2830 | goto out_free_sysfs_attr; | ||
2831 | } | ||
2832 | /* HBA SLI setup */ | ||
2833 | if (lpfc_sli_hba_setup(phba)) { | ||
2834 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
2835 | "1477 Failed to set up hba\n"); | ||
2836 | error = -ENODEV; | ||
2837 | goto out_remove_device; | ||
2838 | } | ||
2839 | |||
2840 | /* Wait 50ms for the interrupts of previous mailbox commands */ | ||
2841 | msleep(50); | ||
2842 | /* Check active interrupts received */ | ||
2843 | if (phba->sli.slistat.sli_intr > LPFC_MSIX_VECTORS) { | ||
2844 | /* Log the current active interrupt mode */ | ||
2845 | phba->intr_mode = intr_mode; | ||
2846 | lpfc_log_intr_mode(phba, intr_mode); | ||
2847 | break; | ||
2848 | } else { | ||
2849 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2850 | "0451 Configure interrupt mode (%d) " | ||
2851 | "failed active interrupt test.\n", | ||
2852 | intr_mode); | ||
2853 | if (intr_mode == 0) { | ||
2854 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
2855 | "0479 Failed to enable " | ||
2856 | "interrupt.\n"); | ||
2857 | error = -ENODEV; | ||
2858 | goto out_remove_device; | ||
2859 | } | ||
2860 | /* Stop HBA SLI setups */ | ||
2861 | lpfc_stop_port(phba); | ||
2862 | /* Disable the current interrupt mode */ | ||
2863 | lpfc_disable_intr(phba); | ||
2864 | /* Try next level of interrupt mode */ | ||
2865 | cfg_mode = --intr_mode; | ||
2866 | } | ||
2625 | } | 2867 | } |
2626 | 2868 | ||
2627 | /* | 2869 | /* |
@@ -2629,6 +2871,75 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
2629 | * the value of can_queue. | 2871 | * the value of can_queue. |
2630 | */ | 2872 | */ |
2631 | shost->can_queue = phba->cfg_hba_queue_depth - 10; | 2873 | shost->can_queue = phba->cfg_hba_queue_depth - 10; |
2874 | if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) { | ||
2875 | |||
2876 | if (lpfc_prot_mask && lpfc_prot_guard) { | ||
2877 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2878 | "1478 Registering BlockGuard with the " | ||
2879 | "SCSI layer\n"); | ||
2880 | |||
2881 | scsi_host_set_prot(shost, lpfc_prot_mask); | ||
2882 | scsi_host_set_guard(shost, lpfc_prot_guard); | ||
2883 | } | ||
2884 | } | ||
2885 | |||
2886 | if (!_dump_buf_data) { | ||
2887 | int pagecnt = 10; | ||
2888 | while (pagecnt) { | ||
2889 | spin_lock_init(&_dump_buf_lock); | ||
2890 | _dump_buf_data = | ||
2891 | (char *) __get_free_pages(GFP_KERNEL, pagecnt); | ||
2892 | if (_dump_buf_data) { | ||
2893 | printk(KERN_ERR "BLKGRD allocated %d pages for " | ||
2894 | "_dump_buf_data at 0x%p\n", | ||
2895 | (1 << pagecnt), _dump_buf_data); | ||
2896 | _dump_buf_data_order = pagecnt; | ||
2897 | memset(_dump_buf_data, 0, ((1 << PAGE_SHIFT) | ||
2898 | << pagecnt)); | ||
2899 | break; | ||
2900 | } else { | ||
2901 | --pagecnt; | ||
2902 | } | ||
2903 | |||
2904 | } | ||
2905 | |||
2906 | if (!_dump_buf_data_order) | ||
2907 | printk(KERN_ERR "BLKGRD ERROR unable to allocate " | ||
2908 | "memory for hexdump\n"); | ||
2909 | |||
2910 | } else { | ||
2911 | printk(KERN_ERR "BLKGRD already allocated _dump_buf_data=0x%p" | ||
2912 | "\n", _dump_buf_data); | ||
2913 | } | ||
2914 | |||
2915 | |||
2916 | if (!_dump_buf_dif) { | ||
2917 | int pagecnt = 10; | ||
2918 | while (pagecnt) { | ||
2919 | _dump_buf_dif = | ||
2920 | (char *) __get_free_pages(GFP_KERNEL, pagecnt); | ||
2921 | if (_dump_buf_dif) { | ||
2922 | printk(KERN_ERR "BLKGRD allocated %d pages for " | ||
2923 | "_dump_buf_dif at 0x%p\n", | ||
2924 | (1 << pagecnt), _dump_buf_dif); | ||
2925 | _dump_buf_dif_order = pagecnt; | ||
2926 | memset(_dump_buf_dif, 0, ((1 << PAGE_SHIFT) | ||
2927 | << pagecnt)); | ||
2928 | break; | ||
2929 | } else { | ||
2930 | --pagecnt; | ||
2931 | } | ||
2932 | |||
2933 | } | ||
2934 | |||
2935 | if (!_dump_buf_dif_order) | ||
2936 | printk(KERN_ERR "BLKGRD ERROR unable to allocate " | ||
2937 | "memory for hexdump\n"); | ||
2938 | |||
2939 | } else { | ||
2940 | printk(KERN_ERR "BLKGRD already allocated _dump_buf_dif=0x%p\n", | ||
2941 | _dump_buf_dif); | ||
2942 | } | ||
2632 | 2943 | ||
2633 | lpfc_host_attrib_init(shost); | 2944 | lpfc_host_attrib_init(shost); |
2634 | 2945 | ||
@@ -2646,29 +2957,22 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
2646 | fc_host_post_vendor_event(shost, fc_get_event_number(), | 2957 | fc_host_post_vendor_event(shost, fc_get_event_number(), |
2647 | sizeof(adapter_event), | 2958 | sizeof(adapter_event), |
2648 | (char *) &adapter_event, | 2959 | (char *) &adapter_event, |
2649 | SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX); | 2960 | LPFC_NL_VENDOR_ID); |
2650 | |||
2651 | scsi_scan_host(shost); | ||
2652 | 2961 | ||
2653 | return 0; | 2962 | return 0; |
2654 | 2963 | ||
2655 | out_remove_device: | 2964 | out_remove_device: |
2656 | lpfc_free_sysfs_attr(vport); | ||
2657 | spin_lock_irq(shost->host_lock); | 2965 | spin_lock_irq(shost->host_lock); |
2658 | vport->load_flag |= FC_UNLOADING; | 2966 | vport->load_flag |= FC_UNLOADING; |
2659 | spin_unlock_irq(shost->host_lock); | 2967 | spin_unlock_irq(shost->host_lock); |
2660 | out_free_irq: | ||
2661 | lpfc_stop_phba_timers(phba); | 2968 | lpfc_stop_phba_timers(phba); |
2662 | phba->pport->work_port_events = 0; | 2969 | phba->pport->work_port_events = 0; |
2663 | 2970 | lpfc_disable_intr(phba); | |
2664 | if (phba->intr_type == MSIX) | 2971 | lpfc_sli_hba_down(phba); |
2665 | lpfc_disable_msix(phba); | 2972 | lpfc_sli_brdrestart(phba); |
2666 | else | 2973 | out_free_sysfs_attr: |
2667 | free_irq(phba->pcidev->irq, phba); | 2974 | lpfc_free_sysfs_attr(vport); |
2668 | 2975 | out_destroy_port: | |
2669 | out_disable_msi: | ||
2670 | if (phba->intr_type == MSI) | ||
2671 | pci_disable_msi(phba->pcidev); | ||
2672 | destroy_port(vport); | 2976 | destroy_port(vport); |
2673 | out_kthread_stop: | 2977 | out_kthread_stop: |
2674 | kthread_stop(phba->worker_thread); | 2978 | kthread_stop(phba->worker_thread); |
@@ -2709,7 +3013,7 @@ out: | |||
2709 | * @pdev: pointer to PCI device | 3013 | * @pdev: pointer to PCI device |
2710 | * | 3014 | * |
2711 | * This routine is to be registered to the kernel's PCI subsystem. When an | 3015 | * This routine is to be registered to the kernel's PCI subsystem. When an |
2712 | * Emulex HBA is removed from PCI bus. It perform all the necessary cleanup | 3016 | * Emulex HBA is removed from PCI bus, it performs all the necessary cleanup |
2713 | * for the HBA device to be removed from the PCI subsystem properly. | 3017 | * for the HBA device to be removed from the PCI subsystem properly. |
2714 | **/ | 3018 | **/ |
2715 | static void __devexit | 3019 | static void __devexit |
@@ -2717,18 +3021,27 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
2717 | { | 3021 | { |
2718 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 3022 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
2719 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; | 3023 | struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata; |
3024 | struct lpfc_vport **vports; | ||
2720 | struct lpfc_hba *phba = vport->phba; | 3025 | struct lpfc_hba *phba = vport->phba; |
3026 | int i; | ||
2721 | int bars = pci_select_bars(pdev, IORESOURCE_MEM); | 3027 | int bars = pci_select_bars(pdev, IORESOURCE_MEM); |
2722 | 3028 | ||
2723 | spin_lock_irq(&phba->hbalock); | 3029 | spin_lock_irq(&phba->hbalock); |
2724 | vport->load_flag |= FC_UNLOADING; | 3030 | vport->load_flag |= FC_UNLOADING; |
2725 | spin_unlock_irq(&phba->hbalock); | 3031 | spin_unlock_irq(&phba->hbalock); |
2726 | 3032 | ||
2727 | kfree(vport->vname); | ||
2728 | lpfc_free_sysfs_attr(vport); | 3033 | lpfc_free_sysfs_attr(vport); |
2729 | 3034 | ||
2730 | kthread_stop(phba->worker_thread); | 3035 | kthread_stop(phba->worker_thread); |
2731 | 3036 | ||
3037 | /* Release all the vports against this physical port */ | ||
3038 | vports = lpfc_create_vport_work_array(phba); | ||
3039 | if (vports != NULL) | ||
3040 | for (i = 1; i <= phba->max_vpi && vports[i] != NULL; i++) | ||
3041 | fc_vport_terminate(vports[i]->fc_vport); | ||
3042 | lpfc_destroy_vport_work_array(phba, vports); | ||
3043 | |||
3044 | /* Remove FC host and then SCSI host with the physical port */ | ||
2732 | fc_remove_host(shost); | 3045 | fc_remove_host(shost); |
2733 | scsi_remove_host(shost); | 3046 | scsi_remove_host(shost); |
2734 | lpfc_cleanup(vport); | 3047 | lpfc_cleanup(vport); |
@@ -2748,13 +3061,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
2748 | 3061 | ||
2749 | lpfc_debugfs_terminate(vport); | 3062 | lpfc_debugfs_terminate(vport); |
2750 | 3063 | ||
2751 | if (phba->intr_type == MSIX) | 3064 | /* Disable interrupt */ |
2752 | lpfc_disable_msix(phba); | 3065 | lpfc_disable_intr(phba); |
2753 | else { | ||
2754 | free_irq(phba->pcidev->irq, phba); | ||
2755 | if (phba->intr_type == MSI) | ||
2756 | pci_disable_msi(phba->pcidev); | ||
2757 | } | ||
2758 | 3066 | ||
2759 | pci_set_drvdata(pdev, NULL); | 3067 | pci_set_drvdata(pdev, NULL); |
2760 | scsi_host_put(shost); | 3068 | scsi_host_put(shost); |
@@ -2786,6 +3094,115 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
2786 | } | 3094 | } |
2787 | 3095 | ||
2788 | /** | 3096 | /** |
3097 | * lpfc_pci_suspend_one: lpfc PCI func to suspend device for power management. | ||
3098 | * @pdev: pointer to PCI device | ||
3099 | * @msg: power management message | ||
3100 | * | ||
3101 | * This routine is to be registered to the kernel's PCI subsystem to support | ||
3102 | * system Power Management (PM). When PM invokes this method, it quiesces the | ||
3103 | * device by stopping the driver's worker thread for the device, turning off | ||
3104 | * device's interrupt and DMA, and bring the device offline. Note that as the | ||
3105 | * driver implements the minimum PM requirements to a power-aware driver's PM | ||
3106 | * support for suspend/resume -- all the possible PM messages (SUSPEND, | ||
3107 | * HIBERNATE, FREEZE) to the suspend() method call will be treated as SUSPEND | ||
3108 | * and the driver will fully reinitialize its device during resume() method | ||
3109 | * call, the driver will set device to PCI_D3hot state in PCI config space | ||
3110 | * instead of setting it according to the @msg provided by the PM. | ||
3111 | * | ||
3112 | * Return code | ||
3113 | * 0 - driver suspended the device | ||
3114 | * Error otherwise | ||
3115 | **/ | ||
3116 | static int | ||
3117 | lpfc_pci_suspend_one(struct pci_dev *pdev, pm_message_t msg) | ||
3118 | { | ||
3119 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
3120 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; | ||
3121 | |||
3122 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
3123 | "0473 PCI device Power Management suspend.\n"); | ||
3124 | |||
3125 | /* Bring down the device */ | ||
3126 | lpfc_offline_prep(phba); | ||
3127 | lpfc_offline(phba); | ||
3128 | kthread_stop(phba->worker_thread); | ||
3129 | |||
3130 | /* Disable interrupt from device */ | ||
3131 | lpfc_disable_intr(phba); | ||
3132 | |||
3133 | /* Save device state to PCI config space */ | ||
3134 | pci_save_state(pdev); | ||
3135 | pci_set_power_state(pdev, PCI_D3hot); | ||
3136 | |||
3137 | return 0; | ||
3138 | } | ||
3139 | |||
3140 | /** | ||
3141 | * lpfc_pci_resume_one: lpfc PCI func to resume device for power management. | ||
3142 | * @pdev: pointer to PCI device | ||
3143 | * | ||
3144 | * This routine is to be registered to the kernel's PCI subsystem to support | ||
3145 | * system Power Management (PM). When PM invokes this method, it restores | ||
3146 | * the device's PCI config space state and fully reinitializes the device | ||
3147 | * and brings it online. Note that as the driver implements the minimum PM | ||
3148 | * requirements to a power-aware driver's PM for suspend/resume -- all | ||
3149 | * the possible PM messages (SUSPEND, HIBERNATE, FREEZE) to the suspend() | ||
3150 | * method call will be treated as SUSPEND and the driver will fully | ||
3151 | * reinitialize its device during resume() method call, the device will be | ||
3152 | * set to PCI_D0 directly in PCI config space before restoring the state. | ||
3153 | * | ||
3154 | * Return code | ||
3155 | * 0 - driver suspended the device | ||
3156 | * Error otherwise | ||
3157 | **/ | ||
3158 | static int | ||
3159 | lpfc_pci_resume_one(struct pci_dev *pdev) | ||
3160 | { | ||
3161 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | ||
3162 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; | ||
3163 | uint32_t intr_mode; | ||
3164 | int error; | ||
3165 | |||
3166 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
3167 | "0452 PCI device Power Management resume.\n"); | ||
3168 | |||
3169 | /* Restore device state from PCI config space */ | ||
3170 | pci_set_power_state(pdev, PCI_D0); | ||
3171 | pci_restore_state(pdev); | ||
3172 | if (pdev->is_busmaster) | ||
3173 | pci_set_master(pdev); | ||
3174 | |||
3175 | /* Startup the kernel thread for this host adapter. */ | ||
3176 | phba->worker_thread = kthread_run(lpfc_do_work, phba, | ||
3177 | "lpfc_worker_%d", phba->brd_no); | ||
3178 | if (IS_ERR(phba->worker_thread)) { | ||
3179 | error = PTR_ERR(phba->worker_thread); | ||
3180 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
3181 | "0434 PM resume failed to start worker " | ||
3182 | "thread: error=x%x.\n", error); | ||
3183 | return error; | ||
3184 | } | ||
3185 | |||
3186 | /* Configure and enable interrupt */ | ||
3187 | intr_mode = lpfc_enable_intr(phba, phba->intr_mode); | ||
3188 | if (intr_mode == LPFC_INTR_ERROR) { | ||
3189 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
3190 | "0430 PM resume Failed to enable interrupt\n"); | ||
3191 | return -EIO; | ||
3192 | } else | ||
3193 | phba->intr_mode = intr_mode; | ||
3194 | |||
3195 | /* Restart HBA and bring it online */ | ||
3196 | lpfc_sli_brdrestart(phba); | ||
3197 | lpfc_online(phba); | ||
3198 | |||
3199 | /* Log the current active interrupt mode */ | ||
3200 | lpfc_log_intr_mode(phba, phba->intr_mode); | ||
3201 | |||
3202 | return 0; | ||
3203 | } | ||
3204 | |||
3205 | /** | ||
2789 | * lpfc_io_error_detected: Driver method for handling PCI I/O error detected. | 3206 | * lpfc_io_error_detected: Driver method for handling PCI I/O error detected. |
2790 | * @pdev: pointer to PCI device. | 3207 | * @pdev: pointer to PCI device. |
2791 | * @state: the current PCI connection state. | 3208 | * @state: the current PCI connection state. |
@@ -2828,13 +3245,8 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, | |||
2828 | pring = &psli->ring[psli->fcp_ring]; | 3245 | pring = &psli->ring[psli->fcp_ring]; |
2829 | lpfc_sli_abort_iocb_ring(phba, pring); | 3246 | lpfc_sli_abort_iocb_ring(phba, pring); |
2830 | 3247 | ||
2831 | if (phba->intr_type == MSIX) | 3248 | /* Disable interrupt */ |
2832 | lpfc_disable_msix(phba); | 3249 | lpfc_disable_intr(phba); |
2833 | else { | ||
2834 | free_irq(phba->pcidev->irq, phba); | ||
2835 | if (phba->intr_type == MSI) | ||
2836 | pci_disable_msi(phba->pcidev); | ||
2837 | } | ||
2838 | 3250 | ||
2839 | /* Request a slot reset. */ | 3251 | /* Request a slot reset. */ |
2840 | return PCI_ERS_RESULT_NEED_RESET; | 3252 | return PCI_ERS_RESULT_NEED_RESET; |
@@ -2862,7 +3274,7 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) | |||
2862 | struct Scsi_Host *shost = pci_get_drvdata(pdev); | 3274 | struct Scsi_Host *shost = pci_get_drvdata(pdev); |
2863 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; | 3275 | struct lpfc_hba *phba = ((struct lpfc_vport *)shost->hostdata)->phba; |
2864 | struct lpfc_sli *psli = &phba->sli; | 3276 | struct lpfc_sli *psli = &phba->sli; |
2865 | int error, retval; | 3277 | uint32_t intr_mode; |
2866 | 3278 | ||
2867 | dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n"); | 3279 | dev_printk(KERN_INFO, &pdev->dev, "recovering from a slot reset.\n"); |
2868 | if (pci_enable_device_mem(pdev)) { | 3280 | if (pci_enable_device_mem(pdev)) { |
@@ -2871,61 +3283,31 @@ static pci_ers_result_t lpfc_io_slot_reset(struct pci_dev *pdev) | |||
2871 | return PCI_ERS_RESULT_DISCONNECT; | 3283 | return PCI_ERS_RESULT_DISCONNECT; |
2872 | } | 3284 | } |
2873 | 3285 | ||
2874 | pci_set_master(pdev); | 3286 | pci_restore_state(pdev); |
3287 | if (pdev->is_busmaster) | ||
3288 | pci_set_master(pdev); | ||
2875 | 3289 | ||
2876 | spin_lock_irq(&phba->hbalock); | 3290 | spin_lock_irq(&phba->hbalock); |
2877 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; | 3291 | psli->sli_flag &= ~LPFC_SLI2_ACTIVE; |
2878 | spin_unlock_irq(&phba->hbalock); | 3292 | spin_unlock_irq(&phba->hbalock); |
2879 | 3293 | ||
2880 | /* Enable configured interrupt method */ | 3294 | /* Configure and enable interrupt */ |
2881 | phba->intr_type = NONE; | 3295 | intr_mode = lpfc_enable_intr(phba, phba->intr_mode); |
2882 | if (phba->cfg_use_msi == 2) { | 3296 | if (intr_mode == LPFC_INTR_ERROR) { |
2883 | /* Need to issue conf_port mbox cmd before conf_msi mbox cmd */ | 3297 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, |
2884 | error = lpfc_sli_config_port(phba, 3); | 3298 | "0427 Cannot re-enable interrupt after " |
2885 | if (error) | 3299 | "slot reset.\n"); |
2886 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 3300 | return PCI_ERS_RESULT_DISCONNECT; |
2887 | "0478 Firmware not capable of SLI 3 mode.\n"); | 3301 | } else |
2888 | else { | 3302 | phba->intr_mode = intr_mode; |
2889 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2890 | "0479 Firmware capable of SLI 3 mode.\n"); | ||
2891 | /* Now, try to enable MSI-X interrupt mode */ | ||
2892 | error = lpfc_enable_msix(phba); | ||
2893 | if (!error) { | ||
2894 | phba->intr_type = MSIX; | ||
2895 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2896 | "0480 enable MSI-X mode.\n"); | ||
2897 | } | ||
2898 | } | ||
2899 | } | ||
2900 | |||
2901 | /* Fallback to MSI if MSI-X initialization failed */ | ||
2902 | if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) { | ||
2903 | retval = pci_enable_msi(phba->pcidev); | ||
2904 | if (!retval) { | ||
2905 | phba->intr_type = MSI; | ||
2906 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2907 | "0481 enable MSI mode.\n"); | ||
2908 | } else | ||
2909 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
2910 | "0470 enable IRQ mode.\n"); | ||
2911 | } | ||
2912 | |||
2913 | /* MSI-X is the only case the doesn't need to call request_irq */ | ||
2914 | if (phba->intr_type != MSIX) { | ||
2915 | retval = request_irq(phba->pcidev->irq, lpfc_intr_handler, | ||
2916 | IRQF_SHARED, LPFC_DRIVER_NAME, phba); | ||
2917 | if (retval) { | ||
2918 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
2919 | "0471 Enable interrupt handler " | ||
2920 | "failed\n"); | ||
2921 | } else if (phba->intr_type != MSI) | ||
2922 | phba->intr_type = INTx; | ||
2923 | } | ||
2924 | 3303 | ||
2925 | /* Take device offline; this will perform cleanup */ | 3304 | /* Take device offline; this will perform cleanup */ |
2926 | lpfc_offline(phba); | 3305 | lpfc_offline(phba); |
2927 | lpfc_sli_brdrestart(phba); | 3306 | lpfc_sli_brdrestart(phba); |
2928 | 3307 | ||
3308 | /* Log the current active interrupt mode */ | ||
3309 | lpfc_log_intr_mode(phba, phba->intr_mode); | ||
3310 | |||
2929 | return PCI_ERS_RESULT_RECOVERED; | 3311 | return PCI_ERS_RESULT_RECOVERED; |
2930 | } | 3312 | } |
2931 | 3313 | ||
@@ -3037,6 +3419,8 @@ static struct pci_driver lpfc_driver = { | |||
3037 | .id_table = lpfc_id_table, | 3419 | .id_table = lpfc_id_table, |
3038 | .probe = lpfc_pci_probe_one, | 3420 | .probe = lpfc_pci_probe_one, |
3039 | .remove = __devexit_p(lpfc_pci_remove_one), | 3421 | .remove = __devexit_p(lpfc_pci_remove_one), |
3422 | .suspend = lpfc_pci_suspend_one, | ||
3423 | .resume = lpfc_pci_resume_one, | ||
3040 | .err_handler = &lpfc_err_handler, | 3424 | .err_handler = &lpfc_err_handler, |
3041 | }; | 3425 | }; |
3042 | 3426 | ||
@@ -3100,6 +3484,19 @@ lpfc_exit(void) | |||
3100 | fc_release_transport(lpfc_transport_template); | 3484 | fc_release_transport(lpfc_transport_template); |
3101 | if (lpfc_enable_npiv) | 3485 | if (lpfc_enable_npiv) |
3102 | fc_release_transport(lpfc_vport_transport_template); | 3486 | fc_release_transport(lpfc_vport_transport_template); |
3487 | if (_dump_buf_data) { | ||
3488 | printk(KERN_ERR "BLKGRD freeing %lu pages for _dump_buf_data " | ||
3489 | "at 0x%p\n", | ||
3490 | (1L << _dump_buf_data_order), _dump_buf_data); | ||
3491 | free_pages((unsigned long)_dump_buf_data, _dump_buf_data_order); | ||
3492 | } | ||
3493 | |||
3494 | if (_dump_buf_dif) { | ||
3495 | printk(KERN_ERR "BLKGRD freeing %lu pages for _dump_buf_dif " | ||
3496 | "at 0x%p\n", | ||
3497 | (1L << _dump_buf_dif_order), _dump_buf_dif); | ||
3498 | free_pages((unsigned long)_dump_buf_dif, _dump_buf_dif_order); | ||
3499 | } | ||
3103 | } | 3500 | } |
3104 | 3501 | ||
3105 | module_init(lpfc_init); | 3502 | module_init(lpfc_init); |