diff options
author | Amit Kumar Salecha <amit@qlogic.com> | 2009-09-11 07:28:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-09-11 19:58:48 -0400 |
commit | 74c520da5414d15b0ab2839d67efab2e7227be75 (patch) | |
tree | d079968ab0f36d4cf7521763ef64d165976537e7 /drivers | |
parent | ec5c50cb93c446a4686863df74e4b7a547628115 (diff) |
netxen: fix tx timeout recovery
Redesign tx timeout handling in line with new firmware
reset design that co-ordinates with other PCI function
drivers.
o For NX3031, first try to reset PCI function's own
context before requesting firmware reset.
o For NX2031, since firmware heartbit is not supported
directly request firmware reset.
Signed-off-by: Amit Kumar Salecha <amit@netxen.com>
Signed-off-by: Dhananjay Phadke <dhananjay@netxen.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/netxen/netxen_nic.h | 4 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_init.c | 4 | ||||
-rw-r--r-- | drivers/net/netxen/netxen_nic_main.c | 69 |
3 files changed, 64 insertions, 13 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 7e3d2b932790..1ae46e8c2dc7 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h | |||
@@ -178,6 +178,7 @@ | |||
178 | 178 | ||
179 | #define MAX_BUFFERS_PER_CMD 32 | 179 | #define MAX_BUFFERS_PER_CMD 32 |
180 | #define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + 4) | 180 | #define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + 4) |
181 | #define NX_MAX_TX_TIMEOUTS 2 | ||
181 | 182 | ||
182 | /* | 183 | /* |
183 | * Following are the states of the Phantom. Phantom will set them and | 184 | * Following are the states of the Phantom. Phantom will set them and |
@@ -1145,7 +1146,8 @@ struct netxen_adapter { | |||
1145 | u8 link_changed; | 1146 | u8 link_changed; |
1146 | u8 fw_wait_cnt; | 1147 | u8 fw_wait_cnt; |
1147 | u8 fw_fail_cnt; | 1148 | u8 fw_fail_cnt; |
1148 | u16 resv4; | 1149 | u8 tx_timeo_cnt; |
1150 | u8 need_fw_reset; | ||
1149 | 1151 | ||
1150 | u8 has_link_events; | 1152 | u8 has_link_events; |
1151 | u8 fw_type; | 1153 | u8 fw_type; |
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 8926b0e0c8bc..128d1b65402d 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c | |||
@@ -1434,8 +1434,10 @@ int netxen_process_cmd_ring(struct netxen_adapter *adapter) | |||
1434 | 1434 | ||
1435 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { | 1435 | if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { |
1436 | __netif_tx_lock(tx_ring->txq, smp_processor_id()); | 1436 | __netif_tx_lock(tx_ring->txq, smp_processor_id()); |
1437 | if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) | 1437 | if (netxen_tx_avail(tx_ring) > TX_STOP_THRESH) { |
1438 | netif_wake_queue(netdev); | 1438 | netif_wake_queue(netdev); |
1439 | adapter->tx_timeo_cnt = 0; | ||
1440 | } | ||
1439 | __netif_tx_unlock(tx_ring->txq); | 1441 | __netif_tx_unlock(tx_ring->txq); |
1440 | } | 1442 | } |
1441 | } | 1443 | } |
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index e8574eeae58f..53bd44e808eb 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c | |||
@@ -66,7 +66,7 @@ static int netxen_nic_close(struct net_device *netdev); | |||
66 | static netdev_tx_t netxen_nic_xmit_frame(struct sk_buff *, | 66 | static netdev_tx_t netxen_nic_xmit_frame(struct sk_buff *, |
67 | struct net_device *); | 67 | struct net_device *); |
68 | static void netxen_tx_timeout(struct net_device *netdev); | 68 | static void netxen_tx_timeout(struct net_device *netdev); |
69 | static void netxen_reset_task(struct work_struct *work); | 69 | static void netxen_tx_timeout_task(struct work_struct *work); |
70 | static void netxen_fw_poll_work(struct work_struct *work); | 70 | static void netxen_fw_poll_work(struct work_struct *work); |
71 | static void netxen_schedule_work(struct netxen_adapter *adapter, | 71 | static void netxen_schedule_work(struct netxen_adapter *adapter, |
72 | work_func_t func, int delay); | 72 | work_func_t func, int delay); |
@@ -875,6 +875,8 @@ wait_init: | |||
875 | 875 | ||
876 | netxen_check_options(adapter); | 876 | netxen_check_options(adapter); |
877 | 877 | ||
878 | adapter->need_fw_reset = 0; | ||
879 | |||
878 | /* fall through and release firmware */ | 880 | /* fall through and release firmware */ |
879 | 881 | ||
880 | err_out: | 882 | err_out: |
@@ -1183,7 +1185,7 @@ netxen_setup_netdev(struct netxen_adapter *adapter, | |||
1183 | 1185 | ||
1184 | netdev->irq = adapter->msix_entries[0].vector; | 1186 | netdev->irq = adapter->msix_entries[0].vector; |
1185 | 1187 | ||
1186 | INIT_WORK(&adapter->tx_timeout_task, netxen_reset_task); | 1188 | INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task); |
1187 | 1189 | ||
1188 | if (netxen_read_mac_addr(adapter)) | 1190 | if (netxen_read_mac_addr(adapter)) |
1189 | dev_warn(&pdev->dev, "failed to read mac addr\n"); | 1191 | dev_warn(&pdev->dev, "failed to read mac addr\n"); |
@@ -1882,7 +1884,7 @@ static void netxen_tx_timeout(struct net_device *netdev) | |||
1882 | schedule_work(&adapter->tx_timeout_task); | 1884 | schedule_work(&adapter->tx_timeout_task); |
1883 | } | 1885 | } |
1884 | 1886 | ||
1885 | static void netxen_reset_task(struct work_struct *work) | 1887 | static void netxen_tx_timeout_task(struct work_struct *work) |
1886 | { | 1888 | { |
1887 | struct netxen_adapter *adapter = | 1889 | struct netxen_adapter *adapter = |
1888 | container_of(work, struct netxen_adapter, tx_timeout_task); | 1890 | container_of(work, struct netxen_adapter, tx_timeout_task); |
@@ -1890,15 +1892,37 @@ static void netxen_reset_task(struct work_struct *work) | |||
1890 | if (!netif_running(adapter->netdev)) | 1892 | if (!netif_running(adapter->netdev)) |
1891 | return; | 1893 | return; |
1892 | 1894 | ||
1893 | if (test_bit(__NX_RESETTING, &adapter->state)) | 1895 | if (test_and_set_bit(__NX_RESETTING, &adapter->state)) |
1894 | return; | 1896 | return; |
1895 | 1897 | ||
1896 | netxen_napi_disable(adapter); | 1898 | if (++adapter->tx_timeo_cnt >= NX_MAX_TX_TIMEOUTS) |
1899 | goto request_reset; | ||
1900 | |||
1901 | if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { | ||
1902 | /* try to scrub interrupt */ | ||
1903 | netxen_napi_disable(adapter); | ||
1897 | 1904 | ||
1898 | adapter->netdev->trans_start = jiffies; | 1905 | adapter->netdev->trans_start = jiffies; |
1899 | 1906 | ||
1900 | netxen_napi_enable(adapter); | 1907 | netxen_napi_enable(adapter); |
1901 | netif_wake_queue(adapter->netdev); | 1908 | |
1909 | netif_wake_queue(adapter->netdev); | ||
1910 | |||
1911 | goto done; | ||
1912 | |||
1913 | } else { | ||
1914 | if (!netxen_nic_reset_context(adapter)) { | ||
1915 | adapter->netdev->trans_start = jiffies; | ||
1916 | goto done; | ||
1917 | } | ||
1918 | |||
1919 | /* context reset failed, fall through for fw reset */ | ||
1920 | } | ||
1921 | |||
1922 | request_reset: | ||
1923 | adapter->need_fw_reset = 1; | ||
1924 | done: | ||
1925 | clear_bit(__NX_RESETTING, &adapter->state); | ||
1902 | } | 1926 | } |
1903 | 1927 | ||
1904 | struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) | 1928 | struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) |
@@ -2048,6 +2072,22 @@ nx_decr_dev_ref_cnt(struct netxen_adapter *adapter) | |||
2048 | return count; | 2072 | return count; |
2049 | } | 2073 | } |
2050 | 2074 | ||
2075 | static void | ||
2076 | nx_dev_request_reset(struct netxen_adapter *adapter) | ||
2077 | { | ||
2078 | u32 state; | ||
2079 | |||
2080 | if (netxen_api_lock(adapter)) | ||
2081 | return; | ||
2082 | |||
2083 | state = NXRD32(adapter, NX_CRB_DEV_STATE); | ||
2084 | |||
2085 | if (state != NX_DEV_INITALIZING) | ||
2086 | NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); | ||
2087 | |||
2088 | netxen_api_unlock(adapter); | ||
2089 | } | ||
2090 | |||
2051 | static int | 2091 | static int |
2052 | netxen_can_start_firmware(struct netxen_adapter *adapter) | 2092 | netxen_can_start_firmware(struct netxen_adapter *adapter) |
2053 | { | 2093 | { |
@@ -2133,9 +2173,11 @@ netxen_fwinit_work(struct work_struct *work) | |||
2133 | switch (dev_state) { | 2173 | switch (dev_state) { |
2134 | case NX_DEV_COLD: | 2174 | case NX_DEV_COLD: |
2135 | case NX_DEV_READY: | 2175 | case NX_DEV_READY: |
2136 | netxen_start_firmware(adapter); | 2176 | if (!netxen_start_firmware(adapter)) { |
2137 | netxen_schedule_work(adapter, netxen_attach_work, 0); | 2177 | netxen_schedule_work(adapter, netxen_attach_work, 0); |
2138 | return; | 2178 | return; |
2179 | } | ||
2180 | break; | ||
2139 | 2181 | ||
2140 | case NX_DEV_INITALIZING: | 2182 | case NX_DEV_INITALIZING: |
2141 | if (++adapter->fw_wait_cnt < FW_POLL_THRESH) { | 2183 | if (++adapter->fw_wait_cnt < FW_POLL_THRESH) { |
@@ -2195,6 +2237,11 @@ netxen_check_health(struct netxen_adapter *adapter) | |||
2195 | if (netxen_nic_check_temp(adapter)) | 2237 | if (netxen_nic_check_temp(adapter)) |
2196 | goto detach; | 2238 | goto detach; |
2197 | 2239 | ||
2240 | if (adapter->need_fw_reset) { | ||
2241 | nx_dev_request_reset(adapter); | ||
2242 | goto detach; | ||
2243 | } | ||
2244 | |||
2198 | state = NXRD32(adapter, NX_CRB_DEV_STATE); | 2245 | state = NXRD32(adapter, NX_CRB_DEV_STATE); |
2199 | if (state == NX_DEV_NEED_RESET) | 2246 | if (state == NX_DEV_NEED_RESET) |
2200 | goto detach; | 2247 | goto detach; |