Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Amit Kumar Salecha and committed by
David S. Miller
74c520da ec5c50cb

+64 -13
+3 -1
drivers/net/netxen/netxen_nic.h
··· 178 178 179 179 #define MAX_BUFFERS_PER_CMD 32 180 180 #define TX_STOP_THRESH ((MAX_SKB_FRAGS >> 2) + 4) 181 + #define NX_MAX_TX_TIMEOUTS 2 181 182 182 183 /* 183 184 * Following are the states of the Phantom. Phantom will set them and ··· 1146 1145 u8 link_changed; 1147 1146 u8 fw_wait_cnt; 1148 1147 u8 fw_fail_cnt; 1149 - u16 resv4; 1148 + u8 tx_timeo_cnt; 1149 + u8 need_fw_reset; 1150 1150 1151 1151 u8 has_link_events; 1152 1152 u8 fw_type;
+3 -1
drivers/net/netxen/netxen_nic_init.c
··· 1434 1434 1435 1435 if (netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) { 1436 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 1438 netif_wake_queue(netdev); 1439 + adapter->tx_timeo_cnt = 0; 1440 + } 1439 1441 __netif_tx_unlock(tx_ring->txq); 1440 1442 } 1441 1443 }
+58 -11
drivers/net/netxen/netxen_nic_main.c
··· 66 66 static netdev_tx_t netxen_nic_xmit_frame(struct sk_buff *, 67 67 struct net_device *); 68 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 70 static void netxen_fw_poll_work(struct work_struct *work); 71 71 static void netxen_schedule_work(struct netxen_adapter *adapter, 72 72 work_func_t func, int delay); ··· 875 875 876 876 netxen_check_options(adapter); 877 877 878 + adapter->need_fw_reset = 0; 879 + 878 880 /* fall through and release firmware */ 879 881 880 882 err_out: ··· 1185 1183 1186 1184 netdev->irq = adapter->msix_entries[0].vector; 1187 1185 1188 - INIT_WORK(&adapter->tx_timeout_task, netxen_reset_task); 1186 + INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task); 1189 1187 1190 1188 if (netxen_read_mac_addr(adapter)) 1191 1189 dev_warn(&pdev->dev, "failed to read mac addr\n"); ··· 1884 1882 schedule_work(&adapter->tx_timeout_task); 1885 1883 } 1886 1884 1887 - static void netxen_reset_task(struct work_struct *work) 1885 + static void netxen_tx_timeout_task(struct work_struct *work) 1888 1886 { 1889 1887 struct netxen_adapter *adapter = 1890 1888 container_of(work, struct netxen_adapter, tx_timeout_task); ··· 1892 1890 if (!netif_running(adapter->netdev)) 1893 1891 return; 1894 1892 1895 - if (test_bit(__NX_RESETTING, &adapter->state)) 1893 + if (test_and_set_bit(__NX_RESETTING, &adapter->state)) 1896 1894 return; 1897 1895 1898 - netxen_napi_disable(adapter); 1896 + if (++adapter->tx_timeo_cnt >= NX_MAX_TX_TIMEOUTS) 1897 + goto request_reset; 1899 1898 1900 - adapter->netdev->trans_start = jiffies; 1899 + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { 1900 + /* try to scrub interrupt */ 1901 + netxen_napi_disable(adapter); 1901 1902 1902 - netxen_napi_enable(adapter); 1903 - netif_wake_queue(adapter->netdev); 1903 + adapter->netdev->trans_start = jiffies; 1904 + 1905 + netxen_napi_enable(adapter); 1906 + 1907 + netif_wake_queue(adapter->netdev); 1908 + 1909 + goto done; 1910 + 1911 + } else { 1912 + if (!netxen_nic_reset_context(adapter)) { 1913 + adapter->netdev->trans_start = jiffies; 1914 + goto done; 1915 + } 1916 + 1917 + /* context reset failed, fall through for fw reset */ 1918 + } 1919 + 1920 + request_reset: 1921 + adapter->need_fw_reset = 1; 1922 + done: 1923 + clear_bit(__NX_RESETTING, &adapter->state); 1904 1924 } 1905 1925 1906 1926 struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) ··· 2072 2048 return count; 2073 2049 } 2074 2050 2051 + static void 2052 + nx_dev_request_reset(struct netxen_adapter *adapter) 2053 + { 2054 + u32 state; 2055 + 2056 + if (netxen_api_lock(adapter)) 2057 + return; 2058 + 2059 + state = NXRD32(adapter, NX_CRB_DEV_STATE); 2060 + 2061 + if (state != NX_DEV_INITALIZING) 2062 + NXWR32(adapter, NX_CRB_DEV_STATE, NX_DEV_NEED_RESET); 2063 + 2064 + netxen_api_unlock(adapter); 2065 + } 2066 + 2075 2067 static int 2076 2068 netxen_can_start_firmware(struct netxen_adapter *adapter) 2077 2069 { ··· 2173 2133 switch (dev_state) { 2174 2134 case NX_DEV_COLD: 2175 2135 case NX_DEV_READY: 2176 - netxen_start_firmware(adapter); 2177 - netxen_schedule_work(adapter, netxen_attach_work, 0); 2178 - return; 2136 + if (!netxen_start_firmware(adapter)) { 2137 + netxen_schedule_work(adapter, netxen_attach_work, 0); 2138 + return; 2139 + } 2140 + break; 2179 2141 2180 2142 case NX_DEV_INITALIZING: 2181 2143 if (++adapter->fw_wait_cnt < FW_POLL_THRESH) { ··· 2236 2194 2237 2195 if (netxen_nic_check_temp(adapter)) 2238 2196 goto detach; 2197 + 2198 + if (adapter->need_fw_reset) { 2199 + nx_dev_request_reset(adapter); 2200 + goto detach; 2201 + } 2239 2202 2240 2203 state = NXRD32(adapter, NX_CRB_DEV_STATE); 2241 2204 if (state == NX_DEV_NEED_RESET)