aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/benet
diff options
context:
space:
mode:
authorSathya Perla <sathyap@serverengines.com>2010-02-14 16:22:01 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-16 00:49:51 -0500
commitcf588477a3fbf085426e5c0b6205984ebb7e2187 (patch)
tree3c5cf63269e443fa5c0518581526017774fa5888 /drivers/net/benet
parent0dca3a843632c2fbb6e358734fb08fc23e800f50 (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')
-rw-r--r--drivers/net/benet/be.h1
-rw-r--r--drivers/net/benet/be_cmds.c23
-rw-r--r--drivers/net/benet/be_main.c103
3 files changed, 125 insertions, 2 deletions
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h
index b39b38542623..5038c16bfe9b 100644
--- a/drivers/net/benet/be.h
+++ b/drivers/net/benet/be.h
@@ -265,6 +265,7 @@ struct be_adapter {
265 u32 if_handle; /* Used to configure filtering */ 265 u32 if_handle; /* Used to configure filtering */
266 u32 pmac_id; /* MAC addr handle used by BE card */ 266 u32 pmac_id; /* MAC addr handle used by BE card */
267 267
268 bool eeh_err;
268 bool link_up; 269 bool link_up;
269 u32 port_num; 270 u32 port_num;
270 bool promiscuous; 271 bool promiscuous;
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index d1a0e5ede4b3..3397ee327e1f 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -167,7 +167,14 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
167 u32 ready; 167 u32 ready;
168 168
169 do { 169 do {
170 ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; 170 ready = ioread32(db);
171 if (ready == 0xffffffff) {
172 dev_err(&adapter->pdev->dev,
173 "pci slot disconnected\n");
174 return -1;
175 }
176
177 ready &= MPU_MAILBOX_DB_RDY_MASK;
171 if (ready) 178 if (ready)
172 break; 179 break;
173 180
@@ -198,6 +205,11 @@ static int be_mbox_notify_wait(struct be_adapter *adapter)
198 struct be_mcc_mailbox *mbox = mbox_mem->va; 205 struct be_mcc_mailbox *mbox = mbox_mem->va;
199 struct be_mcc_compl *compl = &mbox->compl; 206 struct be_mcc_compl *compl = &mbox->compl;
200 207
208 /* wait for ready to be set */
209 status = be_mbox_db_ready_wait(adapter, db);
210 if (status != 0)
211 return status;
212
201 val |= MPU_MAILBOX_DB_HI_MASK; 213 val |= MPU_MAILBOX_DB_HI_MASK;
202 /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ 214 /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */
203 val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; 215 val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2;
@@ -396,6 +408,9 @@ int be_cmd_fw_clean(struct be_adapter *adapter)
396 u8 *wrb; 408 u8 *wrb;
397 int status; 409 int status;
398 410
411 if (adapter->eeh_err)
412 return -EIO;
413
399 spin_lock(&adapter->mbox_lock); 414 spin_lock(&adapter->mbox_lock);
400 415
401 wrb = (u8 *)wrb_from_mbox(adapter); 416 wrb = (u8 *)wrb_from_mbox(adapter);
@@ -768,6 +783,9 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
768 u8 subsys = 0, opcode = 0; 783 u8 subsys = 0, opcode = 0;
769 int status; 784 int status;
770 785
786 if (adapter->eeh_err)
787 return -EIO;
788
771 spin_lock(&adapter->mbox_lock); 789 spin_lock(&adapter->mbox_lock);
772 790
773 wrb = wrb_from_mbox(adapter); 791 wrb = wrb_from_mbox(adapter);
@@ -856,6 +874,9 @@ int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
856 struct be_cmd_req_if_destroy *req; 874 struct be_cmd_req_if_destroy *req;
857 int status; 875 int status;
858 876
877 if (adapter->eeh_err)
878 return -EIO;
879
859 spin_lock(&adapter->mbox_lock); 880 spin_lock(&adapter->mbox_lock);
860 881
861 wrb = wrb_from_mbox(adapter); 882 wrb = wrb_from_mbox(adapter);
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
2159free_mbox: 2171free_mbox:
@@ -2417,13 +2429,102 @@ static int be_resume(struct pci_dev *pdev)
2417 return 0; 2429 return 0;
2418} 2430}
2419 2431
2432static 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
2459static 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
2483static 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;
2509err:
2510 dev_err(&adapter->pdev->dev, "EEH resume failed\n");
2511 return;
2512}
2513
2514static 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
2420static struct pci_driver be_driver = { 2520static 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
2429static int __init be_init_module(void) 2530static int __init be_init_module(void)