aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/qlcnic
diff options
context:
space:
mode:
authorAmit Kumar Salecha <amit.salecha@qlogic.com>2010-06-21 23:19:03 -0400
committerDavid S. Miller <davem@davemloft.net>2010-06-23 16:16:31 -0400
commit68bf1c68a4b3d9ad0a98f3310f2f79dca075a035 (patch)
tree8e29abda3a579c252076eab1b79718d0702a008e /drivers/net/qlcnic
parent52486a3ac86eabe5a2f283eb9682a69c14347213 (diff)
qlcnic: offload tx timeout recovery
Offload tx timeout recovery to fw recovery func(check_health). In check_health, first check health of device, if it its ok, then do tx timeout recovery otherwise device 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/qlcnic')
-rw-r--r--drivers/net/qlcnic/qlcnic.h3
-rw-r--r--drivers/net/qlcnic/qlcnic_main.c65
2 files changed, 32 insertions, 36 deletions
diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h
index 5c7d474e560b..6ec34a7fba65 100644
--- a/drivers/net/qlcnic/qlcnic.h
+++ b/drivers/net/qlcnic/qlcnic.h
@@ -934,6 +934,7 @@ struct qlcnic_adapter {
934 u8 rx_csum; 934 u8 rx_csum;
935 u8 portnum; 935 u8 portnum;
936 u8 physical_port; 936 u8 physical_port;
937 u8 reset_context;
937 938
938 u8 mc_enabled; 939 u8 mc_enabled;
939 u8 max_mc_count; 940 u8 max_mc_count;
@@ -1001,8 +1002,6 @@ struct qlcnic_adapter {
1001 1002
1002 struct delayed_work fw_work; 1003 struct delayed_work fw_work;
1003 1004
1004 struct work_struct tx_timeout_task;
1005
1006 struct qlcnic_nic_intr_coalesce coal; 1005 struct qlcnic_nic_intr_coalesce coal;
1007 1006
1008 unsigned long state; 1007 unsigned long state;
diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c
index c4602fa866d4..3b71dfcd6d44 100644
--- a/drivers/net/qlcnic/qlcnic_main.c
+++ b/drivers/net/qlcnic/qlcnic_main.c
@@ -75,7 +75,6 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev);
75static int qlcnic_open(struct net_device *netdev); 75static int qlcnic_open(struct net_device *netdev);
76static int qlcnic_close(struct net_device *netdev); 76static int qlcnic_close(struct net_device *netdev);
77static void qlcnic_tx_timeout(struct net_device *netdev); 77static void qlcnic_tx_timeout(struct net_device *netdev);
78static void qlcnic_tx_timeout_task(struct work_struct *work);
79static void qlcnic_attach_work(struct work_struct *work); 78static void qlcnic_attach_work(struct work_struct *work);
80static void qlcnic_fwinit_work(struct work_struct *work); 79static void qlcnic_fwinit_work(struct work_struct *work);
81static void qlcnic_fw_poll_work(struct work_struct *work); 80static void qlcnic_fw_poll_work(struct work_struct *work);
@@ -911,6 +910,7 @@ __qlcnic_up(struct qlcnic_adapter *adapter, struct net_device *netdev)
911 910
912 qlcnic_linkevent_request(adapter, 1); 911 qlcnic_linkevent_request(adapter, 1);
913 912
913 adapter->reset_context = 0;
914 set_bit(__QLCNIC_DEV_UP, &adapter->state); 914 set_bit(__QLCNIC_DEV_UP, &adapter->state);
915 return 0; 915 return 0;
916} 916}
@@ -1110,6 +1110,27 @@ int qlcnic_diag_alloc_res(struct net_device *netdev, int test)
1110 return 0; 1110 return 0;
1111} 1111}
1112 1112
1113/* Reset context in hardware only */
1114static int
1115qlcnic_reset_hw_context(struct qlcnic_adapter *adapter)
1116{
1117 struct net_device *netdev = adapter->netdev;
1118
1119 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
1120 return -EBUSY;
1121
1122 netif_device_detach(netdev);
1123
1124 qlcnic_down(adapter, netdev);
1125
1126 qlcnic_up(adapter, netdev);
1127
1128 netif_device_attach(netdev);
1129
1130 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1131 return 0;
1132}
1133
1113int 1134int
1114qlcnic_reset_context(struct qlcnic_adapter *adapter) 1135qlcnic_reset_context(struct qlcnic_adapter *adapter)
1115{ 1136{
@@ -1178,8 +1199,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter,
1178 1199
1179 netdev->irq = adapter->msix_entries[0].vector; 1200 netdev->irq = adapter->msix_entries[0].vector;
1180 1201
1181 INIT_WORK(&adapter->tx_timeout_task, qlcnic_tx_timeout_task);
1182
1183 if (qlcnic_read_mac_addr(adapter)) 1202 if (qlcnic_read_mac_addr(adapter))
1184 dev_warn(&pdev->dev, "failed to read mac addr\n"); 1203 dev_warn(&pdev->dev, "failed to read mac addr\n");
1185 1204
@@ -1350,8 +1369,6 @@ static void __devexit qlcnic_remove(struct pci_dev *pdev)
1350 1369
1351 unregister_netdev(netdev); 1370 unregister_netdev(netdev);
1352 1371
1353 cancel_work_sync(&adapter->tx_timeout_task);
1354
1355 qlcnic_detach(adapter); 1372 qlcnic_detach(adapter);
1356 1373
1357 if (adapter->npars != NULL) 1374 if (adapter->npars != NULL)
@@ -1390,8 +1407,6 @@ static int __qlcnic_shutdown(struct pci_dev *pdev)
1390 if (netif_running(netdev)) 1407 if (netif_running(netdev))
1391 qlcnic_down(adapter, netdev); 1408 qlcnic_down(adapter, netdev);
1392 1409
1393 cancel_work_sync(&adapter->tx_timeout_task);
1394
1395 qlcnic_clr_all_drv_state(adapter); 1410 qlcnic_clr_all_drv_state(adapter);
1396 1411
1397 clear_bit(__QLCNIC_RESETTING, &adapter->state); 1412 clear_bit(__QLCNIC_RESETTING, &adapter->state);
@@ -1854,35 +1869,11 @@ static void qlcnic_tx_timeout(struct net_device *netdev)
1854 return; 1869 return;
1855 1870
1856 dev_err(&netdev->dev, "transmit timeout, resetting.\n"); 1871 dev_err(&netdev->dev, "transmit timeout, resetting.\n");
1857 schedule_work(&adapter->tx_timeout_task);
1858}
1859
1860static void qlcnic_tx_timeout_task(struct work_struct *work)
1861{
1862 struct qlcnic_adapter *adapter =
1863 container_of(work, struct qlcnic_adapter, tx_timeout_task);
1864
1865 if (!netif_running(adapter->netdev))
1866 return;
1867
1868 if (test_and_set_bit(__QLCNIC_RESETTING, &adapter->state))
1869 return;
1870 1872
1871 if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS) 1873 if (++adapter->tx_timeo_cnt >= QLCNIC_MAX_TX_TIMEOUTS)
1872 goto request_reset; 1874 adapter->need_fw_reset = 1;
1873 1875 else
1874 clear_bit(__QLCNIC_RESETTING, &adapter->state); 1876 adapter->reset_context = 1;
1875 if (!qlcnic_reset_context(adapter)) {
1876 adapter->netdev->trans_start = jiffies;
1877 return;
1878
1879 /* context reset failed, fall through for fw reset */
1880 }
1881
1882request_reset:
1883 adapter->need_fw_reset = 1;
1884 clear_bit(__QLCNIC_RESETTING, &adapter->state);
1885 QLCDB(adapter, DRV, "Resetting adapter\n");
1886} 1877}
1887 1878
1888static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev) 1879static struct net_device_stats *qlcnic_get_stats(struct net_device *netdev)
@@ -2540,6 +2531,12 @@ qlcnic_check_health(struct qlcnic_adapter *adapter)
2540 adapter->fw_fail_cnt = 0; 2531 adapter->fw_fail_cnt = 0;
2541 if (adapter->need_fw_reset) 2532 if (adapter->need_fw_reset)
2542 goto detach; 2533 goto detach;
2534
2535 if (adapter->reset_context) {
2536 qlcnic_reset_hw_context(adapter);
2537 adapter->netdev->trans_start = jiffies;
2538 }
2539
2543 return 0; 2540 return 0;
2544 } 2541 }
2545 2542