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 | |
| 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>
| -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; |
