diff options
| author | Divy Le Ray <divy@chelsio.com> | 2007-11-16 14:21:55 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:04:08 -0500 |
| commit | 91a6b50cf680cd693ee0faaab18a0b7383814d6b (patch) | |
| tree | 4e3343116d476aab8de020a4008254dea4cb27d4 /drivers/net/cxgb3/cxgb3_main.c | |
| parent | 67d92ab765a29cd18674b2b87e9f931782a245e3 (diff) | |
cxgb3 - Add EEH support
Add PCI recovery support
Signed-off-by: Divy Le Ray <divy@chelsio.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/cxgb3/cxgb3_main.c')
| -rw-r--r-- | drivers/net/cxgb3/cxgb3_main.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 9d14652ffdc3..1b9a711beb85 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
| @@ -2316,6 +2316,112 @@ void t3_fatal_err(struct adapter *adapter) | |||
| 2316 | 2316 | ||
| 2317 | } | 2317 | } |
| 2318 | 2318 | ||
| 2319 | /** | ||
| 2320 | * t3_io_error_detected - called when PCI error is detected | ||
| 2321 | * @pdev: Pointer to PCI device | ||
| 2322 | * @state: The current pci connection state | ||
| 2323 | * | ||
| 2324 | * This function is called after a PCI bus error affecting | ||
| 2325 | * this device has been detected. | ||
| 2326 | */ | ||
| 2327 | static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev, | ||
| 2328 | pci_channel_state_t state) | ||
| 2329 | { | ||
| 2330 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 2331 | struct port_info *pi = netdev_priv(dev); | ||
| 2332 | struct adapter *adapter = pi->adapter; | ||
| 2333 | int i; | ||
| 2334 | |||
| 2335 | /* Stop all ports */ | ||
| 2336 | for_each_port(adapter, i) { | ||
| 2337 | struct net_device *netdev = adapter->port[i]; | ||
| 2338 | |||
| 2339 | if (netif_running(netdev)) | ||
| 2340 | cxgb_close(netdev); | ||
| 2341 | } | ||
| 2342 | |||
| 2343 | if (is_offload(adapter) && | ||
| 2344 | test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) | ||
| 2345 | offload_close(&adapter->tdev); | ||
| 2346 | |||
| 2347 | /* Free sge resources */ | ||
| 2348 | t3_free_sge_resources(adapter); | ||
| 2349 | |||
| 2350 | adapter->flags &= ~FULL_INIT_DONE; | ||
| 2351 | |||
| 2352 | pci_disable_device(pdev); | ||
| 2353 | |||
| 2354 | /* Request a slot slot reset. */ | ||
| 2355 | return PCI_ERS_RESULT_NEED_RESET; | ||
| 2356 | } | ||
| 2357 | |||
| 2358 | /** | ||
| 2359 | * t3_io_slot_reset - called after the pci bus has been reset. | ||
| 2360 | * @pdev: Pointer to PCI device | ||
| 2361 | * | ||
| 2362 | * Restart the card from scratch, as if from a cold-boot. | ||
| 2363 | */ | ||
| 2364 | static pci_ers_result_t t3_io_slot_reset(struct pci_dev *pdev) | ||
| 2365 | { | ||
| 2366 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 2367 | struct port_info *pi = netdev_priv(dev); | ||
| 2368 | struct adapter *adapter = pi->adapter; | ||
| 2369 | |||
| 2370 | if (pci_enable_device(pdev)) { | ||
| 2371 | dev_err(&pdev->dev, | ||
| 2372 | "Cannot re-enable PCI device after reset.\n"); | ||
| 2373 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 2374 | } | ||
| 2375 | pci_set_master(pdev); | ||
| 2376 | |||
| 2377 | t3_prep_adapter(adapter, adapter->params.info, 1); | ||
| 2378 | |||
| 2379 | return PCI_ERS_RESULT_RECOVERED; | ||
| 2380 | } | ||
| 2381 | |||
| 2382 | /** | ||
| 2383 | * t3_io_resume - called when traffic can start flowing again. | ||
| 2384 | * @pdev: Pointer to PCI device | ||
| 2385 | * | ||
| 2386 | * This callback is called when the error recovery driver tells us that | ||
| 2387 | * its OK to resume normal operation. | ||
| 2388 | */ | ||
| 2389 | static void t3_io_resume(struct pci_dev *pdev) | ||
| 2390 | { | ||
| 2391 | struct net_device *dev = pci_get_drvdata(pdev); | ||
| 2392 | struct port_info *pi = netdev_priv(dev); | ||
| 2393 | struct adapter *adapter = pi->adapter; | ||
| 2394 | int i; | ||
| 2395 | |||
| 2396 | /* Restart the ports */ | ||
| 2397 | for_each_port(adapter, i) { | ||
| 2398 | struct net_device *netdev = adapter->port[i]; | ||
| 2399 | |||
| 2400 | if (netif_running(netdev)) { | ||
| 2401 | if (cxgb_open(netdev)) { | ||
| 2402 | dev_err(&pdev->dev, | ||
| 2403 | "can't bring device back up" | ||
| 2404 | " after reset\n"); | ||
| 2405 | continue; | ||
| 2406 | } | ||
| 2407 | netif_device_attach(netdev); | ||
| 2408 | } | ||
| 2409 | } | ||
| 2410 | |||
| 2411 | if (is_offload(adapter)) { | ||
| 2412 | __set_bit(OFFLOAD_DEVMAP_BIT, &adapter->registered_device_map); | ||
| 2413 | if (offload_open(dev)) | ||
| 2414 | printk(KERN_WARNING | ||
| 2415 | "Could not bring back offload capabilities\n"); | ||
| 2416 | } | ||
| 2417 | } | ||
| 2418 | |||
| 2419 | static struct pci_error_handlers t3_err_handler = { | ||
| 2420 | .error_detected = t3_io_error_detected, | ||
| 2421 | .slot_reset = t3_io_slot_reset, | ||
| 2422 | .resume = t3_io_resume, | ||
| 2423 | }; | ||
| 2424 | |||
| 2319 | static int __devinit cxgb_enable_msix(struct adapter *adap) | 2425 | static int __devinit cxgb_enable_msix(struct adapter *adap) |
| 2320 | { | 2426 | { |
| 2321 | struct msix_entry entries[SGE_QSETS + 1]; | 2427 | struct msix_entry entries[SGE_QSETS + 1]; |
| @@ -2616,6 +2722,7 @@ static struct pci_driver driver = { | |||
| 2616 | .id_table = cxgb3_pci_tbl, | 2722 | .id_table = cxgb3_pci_tbl, |
| 2617 | .probe = init_one, | 2723 | .probe = init_one, |
| 2618 | .remove = __devexit_p(remove_one), | 2724 | .remove = __devexit_p(remove_one), |
| 2725 | .err_handler = &t3_err_handler, | ||
| 2619 | }; | 2726 | }; |
| 2620 | 2727 | ||
| 2621 | static int __init cxgb3_init_module(void) | 2728 | static int __init cxgb3_init_module(void) |
