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 | |
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>
-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) |