aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorAmit Kumar Salecha <amit.salecha@qlogic.com>2009-12-08 15:40:56 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-23 17:13:27 -0500
commite87ad5539343366e7c634c940a930157b6fa2aae (patch)
tree53eacf4e7a62498e76463adafd0e43f4808d188d /drivers/net
parent6a808c6c02fb9f0ffa24ac7cca6cfc323cf98b21 (diff)
netxen: support pci error handlers
o Support pci error detection and recovery. o Refactor suspend and resume code, to share with io_error_detected, and slot_reset callbacks o NX_NEED_AER device state added, to synchronize with firmware recovery. Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/netxen/netxen_nic_hdr.h3
-rw-r--r--drivers/net/netxen/netxen_nic_main.c193
2 files changed, 150 insertions, 46 deletions
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index d138fc22927a..638369024908 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -969,7 +969,8 @@ enum {
969#define NX_DEV_READY 3 969#define NX_DEV_READY 3
970#define NX_DEV_NEED_RESET 4 970#define NX_DEV_NEED_RESET 4
971#define NX_DEV_NEED_QUISCENT 5 971#define NX_DEV_NEED_QUISCENT 5
972#define NX_DEV_FAILED 6 972#define NX_DEV_NEED_AER 6
973#define NX_DEV_FAILED 7
973 974
974#define NX_RCODE_DRIVER_INFO 0x20000000 975#define NX_RCODE_DRIVER_INFO 0x20000000
975#define NX_RCODE_DRIVER_CAN_RELOAD 0x40000000 976#define NX_RCODE_DRIVER_CAN_RELOAD 0x40000000
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 1aca6260909a..f13a07f717c7 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -35,6 +35,7 @@
35#include <linux/ipv6.h> 35#include <linux/ipv6.h>
36#include <linux/inetdevice.h> 36#include <linux/inetdevice.h>
37#include <linux/sysfs.h> 37#include <linux/sysfs.h>
38#include <linux/aer.h>
38 39
39MODULE_DESCRIPTION("QLogic/NetXen (1/10) GbE Converged Ethernet Driver"); 40MODULE_DESCRIPTION("QLogic/NetXen (1/10) GbE Converged Ethernet Driver");
40MODULE_LICENSE("GPL"); 41MODULE_LICENSE("GPL");
@@ -84,6 +85,7 @@ static void netxen_remove_sysfs_entries(struct netxen_adapter *adapter);
84static void netxen_create_diag_entries(struct netxen_adapter *adapter); 85static void netxen_create_diag_entries(struct netxen_adapter *adapter);
85static void netxen_remove_diag_entries(struct netxen_adapter *adapter); 86static void netxen_remove_diag_entries(struct netxen_adapter *adapter);
86 87
88static int nx_dev_request_aer(struct netxen_adapter *adapter);
87static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter); 89static int nx_decr_dev_ref_cnt(struct netxen_adapter *adapter);
88static int netxen_can_start_firmware(struct netxen_adapter *adapter); 90static int netxen_can_start_firmware(struct netxen_adapter *adapter);
89 91
@@ -1262,6 +1264,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1262 if ((err = pci_request_regions(pdev, netxen_nic_driver_name))) 1264 if ((err = pci_request_regions(pdev, netxen_nic_driver_name)))
1263 goto err_out_disable_pdev; 1265 goto err_out_disable_pdev;
1264 1266
1267 if (NX_IS_REVISION_P3(pdev->revision))
1268 pci_enable_pcie_error_reporting(pdev);
1269
1265 pci_set_master(pdev); 1270 pci_set_master(pdev);
1266 1271
1267 netdev = alloc_etherdev(sizeof(struct netxen_adapter)); 1272 netdev = alloc_etherdev(sizeof(struct netxen_adapter));
@@ -1409,17 +1414,19 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev)
1409 1414
1410 netxen_release_firmware(adapter); 1415 netxen_release_firmware(adapter);
1411 1416
1417 if (NX_IS_REVISION_P3(pdev->revision))
1418 pci_disable_pcie_error_reporting(pdev);
1419
1412 pci_release_regions(pdev); 1420 pci_release_regions(pdev);
1413 pci_disable_device(pdev); 1421 pci_disable_device(pdev);
1414 pci_set_drvdata(pdev, NULL); 1422 pci_set_drvdata(pdev, NULL);
1415 1423
1416 free_netdev(netdev); 1424 free_netdev(netdev);
1417} 1425}
1418static int __netxen_nic_shutdown(struct pci_dev *pdev) 1426
1427static void netxen_nic_detach_func(struct netxen_adapter *adapter)
1419{ 1428{
1420 struct netxen_adapter *adapter = pci_get_drvdata(pdev);
1421 struct net_device *netdev = adapter->netdev; 1429 struct net_device *netdev = adapter->netdev;
1422 int retval;
1423 1430
1424 netif_device_detach(netdev); 1431 netif_device_detach(netdev);
1425 1432
@@ -1438,43 +1445,9 @@ static int __netxen_nic_shutdown(struct pci_dev *pdev)
1438 nx_decr_dev_ref_cnt(adapter); 1445 nx_decr_dev_ref_cnt(adapter);
1439 1446
1440 clear_bit(__NX_RESETTING, &adapter->state); 1447 clear_bit(__NX_RESETTING, &adapter->state);
1441
1442 retval = pci_save_state(pdev);
1443 if (retval)
1444 return retval;
1445
1446 if (netxen_nic_wol_supported(adapter)) {
1447 pci_enable_wake(pdev, PCI_D3cold, 1);
1448 pci_enable_wake(pdev, PCI_D3hot, 1);
1449 }
1450
1451 return 0;
1452}
1453static void netxen_nic_shutdown(struct pci_dev *pdev)
1454{
1455 if (__netxen_nic_shutdown(pdev))
1456 return;
1457
1458 pci_disable_device(pdev);
1459}
1460#ifdef CONFIG_PM
1461static int
1462netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state)
1463{
1464 int retval;
1465
1466 retval = __netxen_nic_shutdown(pdev);
1467 if (retval)
1468 return retval;
1469
1470 pci_set_power_state(pdev, pci_choose_state(pdev, state));
1471
1472 pci_disable_device(pdev);
1473 return 0;
1474} 1448}
1475 1449
1476static int 1450static int netxen_nic_attach_func(struct pci_dev *pdev)
1477netxen_nic_resume(struct pci_dev *pdev)
1478{ 1451{
1479 struct netxen_adapter *adapter = pci_get_drvdata(pdev); 1452 struct netxen_adapter *adapter = pci_get_drvdata(pdev);
1480 struct net_device *netdev = adapter->netdev; 1453 struct net_device *netdev = adapter->netdev;
@@ -1519,6 +1492,85 @@ err_out:
1519 nx_decr_dev_ref_cnt(adapter); 1492 nx_decr_dev_ref_cnt(adapter);
1520 return err; 1493 return err;
1521} 1494}
1495
1496static pci_ers_result_t netxen_io_error_detected(struct pci_dev *pdev,
1497 pci_channel_state_t state)
1498{
1499 struct netxen_adapter *adapter = pci_get_drvdata(pdev);
1500
1501 if (state == pci_channel_io_perm_failure)
1502 return PCI_ERS_RESULT_DISCONNECT;
1503
1504 if (nx_dev_request_aer(adapter))
1505 return PCI_ERS_RESULT_RECOVERED;
1506
1507 netxen_nic_detach_func(adapter);
1508
1509 pci_disable_device(pdev);
1510
1511 return PCI_ERS_RESULT_NEED_RESET;
1512}
1513
1514static pci_ers_result_t netxen_io_slot_reset(struct pci_dev *pdev)
1515{
1516 int err = 0;
1517
1518 err = netxen_nic_attach_func(pdev);
1519
1520 return err ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
1521}
1522
1523static void netxen_io_resume(struct pci_dev *pdev)
1524{
1525 pci_cleanup_aer_uncorrect_error_status(pdev);
1526}
1527
1528static void netxen_nic_shutdown(struct pci_dev *pdev)
1529{
1530 struct netxen_adapter *adapter = pci_get_drvdata(pdev);
1531
1532 netxen_nic_detach_func(adapter);
1533
1534 if (pci_save_state(pdev))
1535 return;
1536
1537 if (netxen_nic_wol_supported(adapter)) {
1538 pci_enable_wake(pdev, PCI_D3cold, 1);
1539 pci_enable_wake(pdev, PCI_D3hot, 1);
1540 }
1541
1542 pci_disable_device(pdev);
1543}
1544
1545#ifdef CONFIG_PM
1546static int
1547netxen_nic_suspend(struct pci_dev *pdev, pm_message_t state)
1548{
1549 struct netxen_adapter *adapter = pci_get_drvdata(pdev);
1550 int retval;
1551
1552 netxen_nic_detach_func(adapter);
1553
1554 retval = pci_save_state(pdev);
1555 if (retval)
1556 return retval;
1557
1558 if (netxen_nic_wol_supported(adapter)) {
1559 pci_enable_wake(pdev, PCI_D3cold, 1);
1560 pci_enable_wake(pdev, PCI_D3hot, 1);
1561 }
1562
1563 pci_disable_device(pdev);
1564 pci_set_power_state(pdev, pci_choose_state(pdev, state));
1565
1566 return 0;
1567}
1568
1569static int
1570netxen_nic_resume(struct pci_dev *pdev)
1571{
1572 return netxen_nic_attach_func(pdev);
1573}
1522#endif 1574#endif
1523 1575
1524static int netxen_nic_open(struct net_device *netdev) 1576static int netxen_nic_open(struct net_device *netdev)
@@ -2110,20 +2162,49 @@ nx_decr_dev_ref_cnt(struct netxen_adapter *adapter)
2110 return count; 2162 return count;
2111} 2163}
2112 2164
2113static void 2165static int
2166nx_dev_request_aer(struct netxen_adapter *adapter)
2167{
2168 u32 state;
2169 int ret = -EINVAL;
2170
2171 if (netxen_api_lock(adapter))
2172 return ret;
2173
2174 state = NXRD32(adapter, NX_CRB_DEV_STATE);
2175
2176 if (state == NX_DEV_NEED_AER)
2177 ret = 0;
2178 else if (state == NX_DEV_READY) {
2179 NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_AER);
2180 ret = 0;
2181 }
2182
2183 netxen_api_unlock(adapter);
2184 return ret;
2185}
2186
2187static int
2114nx_dev_request_reset(struct netxen_adapter *adapter) 2188nx_dev_request_reset(struct netxen_adapter *adapter)
2115{ 2189{
2116 u32 state; 2190 u32 state;
2191 int ret = -EINVAL;
2117 2192
2118 if (netxen_api_lock(adapter)) 2193 if (netxen_api_lock(adapter))
2119 return; 2194 return ret;
2120 2195
2121 state = NXRD32(adapter, NX_CRB_DEV_STATE); 2196 state = NXRD32(adapter, NX_CRB_DEV_STATE);
2122 2197
2123 if (state != NX_DEV_INITALIZING) 2198 if (state == NX_DEV_NEED_RESET)
2199 ret = 0;
2200 else if (state != NX_DEV_INITALIZING && state != NX_DEV_NEED_AER) {
2124 NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); 2201 NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET);
2202 ret = 0;
2203 }
2125 2204
2126 netxen_api_unlock(adapter); 2205 netxen_api_unlock(adapter);
2206
2207 return ret;
2127} 2208}
2128 2209
2129static int 2210static int
@@ -2275,18 +2356,28 @@ netxen_check_health(struct netxen_adapter *adapter)
2275 u32 state, heartbit; 2356 u32 state, heartbit;
2276 struct net_device *netdev = adapter->netdev; 2357 struct net_device *netdev = adapter->netdev;
2277 2358
2359 state = NXRD32(adapter, NX_CRB_DEV_STATE);
2360 if (state == NX_DEV_NEED_AER)
2361 return 0;
2362
2278 if (netxen_nic_check_temp(adapter)) 2363 if (netxen_nic_check_temp(adapter))
2279 goto detach; 2364 goto detach;
2280 2365
2281 if (adapter->need_fw_reset) { 2366 if (adapter->need_fw_reset) {
2282 nx_dev_request_reset(adapter); 2367 if (nx_dev_request_reset(adapter))
2368 return 0;
2283 goto detach; 2369 goto detach;
2284 } 2370 }
2285 2371
2286 state = NXRD32(adapter, NX_CRB_DEV_STATE); 2372 /* NX_DEV_NEED_RESET, this state can be marked in two cases
2373 * 1. Tx timeout 2. Fw hang
2374 * Send request to destroy context in case of tx timeout only
2375 * and doesn't required in case of Fw hang
2376 */
2287 if (state == NX_DEV_NEED_RESET) { 2377 if (state == NX_DEV_NEED_RESET) {
2288 adapter->need_fw_reset = 1; 2378 adapter->need_fw_reset = 1;
2289 goto detach; 2379 if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
2380 goto detach;
2290 } 2381 }
2291 2382
2292 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) 2383 if (NX_IS_REVISION_P2(adapter->ahw.revision_id))
@@ -2296,12 +2387,17 @@ netxen_check_health(struct netxen_adapter *adapter)
2296 if (heartbit != adapter->heartbit) { 2387 if (heartbit != adapter->heartbit) {
2297 adapter->heartbit = heartbit; 2388 adapter->heartbit = heartbit;
2298 adapter->fw_fail_cnt = 0; 2389 adapter->fw_fail_cnt = 0;
2390 if (adapter->need_fw_reset)
2391 goto detach;
2299 return 0; 2392 return 0;
2300 } 2393 }
2301 2394
2302 if (++adapter->fw_fail_cnt < FW_FAIL_THRESH) 2395 if (++adapter->fw_fail_cnt < FW_FAIL_THRESH)
2303 return 0; 2396 return 0;
2304 2397
2398 if (nx_dev_request_reset(adapter))
2399 return 0;
2400
2305 clear_bit(__NX_FW_ATTACHED, &adapter->state); 2401 clear_bit(__NX_FW_ATTACHED, &adapter->state);
2306 2402
2307 dev_info(&netdev->dev, "firmware hang detected\n"); 2403 dev_info(&netdev->dev, "firmware hang detected\n");
@@ -2731,6 +2827,12 @@ netxen_config_indev_addr(struct net_device *dev, unsigned long event)
2731{ } 2827{ }
2732#endif 2828#endif
2733 2829
2830static struct pci_error_handlers netxen_err_handler = {
2831 .error_detected = netxen_io_error_detected,
2832 .slot_reset = netxen_io_slot_reset,
2833 .resume = netxen_io_resume,
2834};
2835
2734static struct pci_driver netxen_driver = { 2836static struct pci_driver netxen_driver = {
2735 .name = netxen_nic_driver_name, 2837 .name = netxen_nic_driver_name,
2736 .id_table = netxen_pci_tbl, 2838 .id_table = netxen_pci_tbl,
@@ -2740,7 +2842,8 @@ static struct pci_driver netxen_driver = {
2740 .suspend = netxen_nic_suspend, 2842 .suspend = netxen_nic_suspend,
2741 .resume = netxen_nic_resume, 2843 .resume = netxen_nic_resume,
2742#endif 2844#endif
2743 .shutdown = netxen_nic_shutdown 2845 .shutdown = netxen_nic_shutdown,
2846 .err_handler = &netxen_err_handler
2744}; 2847};
2745 2848
2746static int __init netxen_init_module(void) 2849static int __init netxen_init_module(void)