diff options
author | Sathya Perla <sathyap@serverengines.com> | 2010-02-14 16:22:01 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-02-16 00:49:51 -0500 |
commit | cf588477a3fbf085426e5c0b6205984ebb7e2187 (patch) | |
tree | 3c5cf63269e443fa5c0518581526017774fa5888 /drivers/net/benet/be_main.c | |
parent | 0dca3a843632c2fbb6e358734fb08fc23e800f50 (diff) |
be2net: implement EEH pci error recovery handlers
The code has been tested on IBM pSeries server.
Signed-off-by: Sathya Perla <sathyap@serverengines.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/benet/be_main.c')
-rw-r--r-- | drivers/net/benet/be_main.c | 103 |
1 files changed, 102 insertions, 1 deletions
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 92c55f679466..cbfaa3feb7c4 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -68,6 +68,9 @@ static void be_intr_set(struct be_adapter *adapter, bool enable) | |||
68 | u32 reg = ioread32(addr); | 68 | u32 reg = ioread32(addr); |
69 | u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; | 69 | u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; |
70 | 70 | ||
71 | if (adapter->eeh_err) | ||
72 | return; | ||
73 | |||
71 | if (!enabled && enable) | 74 | if (!enabled && enable) |
72 | reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; | 75 | reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; |
73 | else if (enabled && !enable) | 76 | else if (enabled && !enable) |
@@ -99,6 +102,10 @@ static void be_eq_notify(struct be_adapter *adapter, u16 qid, | |||
99 | { | 102 | { |
100 | u32 val = 0; | 103 | u32 val = 0; |
101 | val |= qid & DB_EQ_RING_ID_MASK; | 104 | val |= qid & DB_EQ_RING_ID_MASK; |
105 | |||
106 | if (adapter->eeh_err) | ||
107 | return; | ||
108 | |||
102 | if (arm) | 109 | if (arm) |
103 | val |= 1 << DB_EQ_REARM_SHIFT; | 110 | val |= 1 << DB_EQ_REARM_SHIFT; |
104 | if (clear_int) | 111 | if (clear_int) |
@@ -112,6 +119,10 @@ void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm, u16 num_popped) | |||
112 | { | 119 | { |
113 | u32 val = 0; | 120 | u32 val = 0; |
114 | val |= qid & DB_CQ_RING_ID_MASK; | 121 | val |= qid & DB_CQ_RING_ID_MASK; |
122 | |||
123 | if (adapter->eeh_err) | ||
124 | return; | ||
125 | |||
115 | if (arm) | 126 | if (arm) |
116 | val |= 1 << DB_CQ_REARM_SHIFT; | 127 | val |= 1 << DB_CQ_REARM_SHIFT; |
117 | val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; | 128 | val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; |
@@ -2154,6 +2165,7 @@ static int be_ctrl_init(struct be_adapter *adapter) | |||
2154 | spin_lock_init(&adapter->mcc_lock); | 2165 | spin_lock_init(&adapter->mcc_lock); |
2155 | spin_lock_init(&adapter->mcc_cq_lock); | 2166 | spin_lock_init(&adapter->mcc_cq_lock); |
2156 | 2167 | ||
2168 | pci_save_state(adapter->pdev); | ||
2157 | return 0; | 2169 | return 0; |
2158 | 2170 | ||
2159 | free_mbox: | 2171 | free_mbox: |
@@ -2417,13 +2429,102 @@ static int be_resume(struct pci_dev *pdev) | |||
2417 | return 0; | 2429 | return 0; |
2418 | } | 2430 | } |
2419 | 2431 | ||
2432 | static pci_ers_result_t be_eeh_err_detected(struct pci_dev *pdev, | ||
2433 | pci_channel_state_t state) | ||
2434 | { | ||
2435 | struct be_adapter *adapter = pci_get_drvdata(pdev); | ||
2436 | struct net_device *netdev = adapter->netdev; | ||
2437 | |||
2438 | dev_err(&adapter->pdev->dev, "EEH error detected\n"); | ||
2439 | |||
2440 | adapter->eeh_err = true; | ||
2441 | |||
2442 | netif_device_detach(netdev); | ||
2443 | |||
2444 | if (netif_running(netdev)) { | ||
2445 | rtnl_lock(); | ||
2446 | be_close(netdev); | ||
2447 | rtnl_unlock(); | ||
2448 | } | ||
2449 | be_clear(adapter); | ||
2450 | |||
2451 | if (state == pci_channel_io_perm_failure) | ||
2452 | return PCI_ERS_RESULT_DISCONNECT; | ||
2453 | |||
2454 | pci_disable_device(pdev); | ||
2455 | |||
2456 | return PCI_ERS_RESULT_NEED_RESET; | ||
2457 | } | ||
2458 | |||
2459 | static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) | ||
2460 | { | ||
2461 | struct be_adapter *adapter = pci_get_drvdata(pdev); | ||
2462 | int status; | ||
2463 | |||
2464 | dev_info(&adapter->pdev->dev, "EEH reset\n"); | ||
2465 | adapter->eeh_err = false; | ||
2466 | |||
2467 | status = pci_enable_device(pdev); | ||
2468 | if (status) | ||
2469 | return PCI_ERS_RESULT_DISCONNECT; | ||
2470 | |||
2471 | pci_set_master(pdev); | ||
2472 | pci_set_power_state(pdev, 0); | ||
2473 | pci_restore_state(pdev); | ||
2474 | |||
2475 | /* Check if card is ok and fw is ready */ | ||
2476 | status = be_cmd_POST(adapter); | ||
2477 | if (status) | ||
2478 | return PCI_ERS_RESULT_DISCONNECT; | ||
2479 | |||
2480 | return PCI_ERS_RESULT_RECOVERED; | ||
2481 | } | ||
2482 | |||
2483 | static void be_eeh_resume(struct pci_dev *pdev) | ||
2484 | { | ||
2485 | int status = 0; | ||
2486 | struct be_adapter *adapter = pci_get_drvdata(pdev); | ||
2487 | struct net_device *netdev = adapter->netdev; | ||
2488 | |||
2489 | dev_info(&adapter->pdev->dev, "EEH resume\n"); | ||
2490 | |||
2491 | pci_save_state(pdev); | ||
2492 | |||
2493 | /* tell fw we're ready to fire cmds */ | ||
2494 | status = be_cmd_fw_init(adapter); | ||
2495 | if (status) | ||
2496 | goto err; | ||
2497 | |||
2498 | status = be_setup(adapter); | ||
2499 | if (status) | ||
2500 | goto err; | ||
2501 | |||
2502 | if (netif_running(netdev)) { | ||
2503 | status = be_open(netdev); | ||
2504 | if (status) | ||
2505 | goto err; | ||
2506 | } | ||
2507 | netif_device_attach(netdev); | ||
2508 | return; | ||
2509 | err: | ||
2510 | dev_err(&adapter->pdev->dev, "EEH resume failed\n"); | ||
2511 | return; | ||
2512 | } | ||
2513 | |||
2514 | static struct pci_error_handlers be_eeh_handlers = { | ||
2515 | .error_detected = be_eeh_err_detected, | ||
2516 | .slot_reset = be_eeh_reset, | ||
2517 | .resume = be_eeh_resume, | ||
2518 | }; | ||
2519 | |||
2420 | static struct pci_driver be_driver = { | 2520 | static struct pci_driver be_driver = { |
2421 | .name = DRV_NAME, | 2521 | .name = DRV_NAME, |
2422 | .id_table = be_dev_ids, | 2522 | .id_table = be_dev_ids, |
2423 | .probe = be_probe, | 2523 | .probe = be_probe, |
2424 | .remove = be_remove, | 2524 | .remove = be_remove, |
2425 | .suspend = be_suspend, | 2525 | .suspend = be_suspend, |
2426 | .resume = be_resume | 2526 | .resume = be_resume, |
2527 | .err_handler = &be_eeh_handlers | ||
2427 | }; | 2528 | }; |
2428 | 2529 | ||
2429 | static int __init be_init_module(void) | 2530 | static int __init be_init_module(void) |