mwifiex: Trigger a card reset on reaching tx_timeout threshold
authorAshok Nagarajan <asnagarajan@chromium.org>
Fri, 8 Mar 2013 18:58:45 +0000 (10:58 -0800)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 8 Mar 2013 21:02:48 +0000 (16:02 -0500)
tx_timeout doesn't always lead to a cmd_timeout. There are
occurrences where cmd_timeout never gets triggered for a long
time and we encounter a kernel crash. In this patch, we track
the consecutive timeouts (tx_timeout_cnt). When tx_timeout_cnt
exceeds the threshold, trigger a card reset thereby avoiding a
kernel crash.

Signed-off-by: Ashok Nagarajan <asnagarajan@chromium.org>
Signed-off-by: Paul Stewart <pstew@chromium.org>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/mwifiex/main.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/txrx.c

index 9c802ede9c3b94cb56f385e7c5c40699d0c2ee9f..121443a0f2a13ed91522241cfe6fc11abad613af 100644 (file)
@@ -588,10 +588,19 @@ mwifiex_tx_timeout(struct net_device *dev)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
 
-       dev_err(priv->adapter->dev, "%lu : Tx timeout, bss_type-num = %d-%d\n",
-               jiffies, priv->bss_type, priv->bss_num);
-       mwifiex_set_trans_start(dev);
        priv->num_tx_timeout++;
+       priv->tx_timeout_cnt++;
+       dev_err(priv->adapter->dev,
+               "%lu : Tx timeout(#%d), bss_type-num = %d-%d\n",
+               jiffies, priv->tx_timeout_cnt, priv->bss_type, priv->bss_num);
+       mwifiex_set_trans_start(dev);
+
+       if (priv->tx_timeout_cnt > TX_TIMEOUT_THRESHOLD &&
+           priv->adapter->if_ops.card_reset) {
+               dev_err(priv->adapter->dev,
+                       "tx_timeout_cnt exceeds threshold. Triggering card reset!\n");
+               priv->adapter->if_ops.card_reset(priv->adapter);
+       }
 }
 
 /*
index 560cf7312d08a18b2c403f056e64636f2e537deb..920657587fff110aa3e6f254dd2c02be4d40fe73 100644 (file)
@@ -130,6 +130,9 @@ enum {
 #define MWIFIEX_USB_TYPE_DATA                  0xBEADC0DE
 #define MWIFIEX_USB_TYPE_EVENT                 0xBEEFFACE
 
+/* Threshold for tx_timeout_cnt before we trigger a card reset */
+#define TX_TIMEOUT_THRESHOLD   6
+
 struct mwifiex_dbg {
        u32 num_cmd_host_to_card_failure;
        u32 num_cmd_sleep_cfm_host_to_card_failure;
@@ -394,6 +397,8 @@ struct mwifiex_private {
        u8 curr_addr[ETH_ALEN];
        u8 media_connected;
        u32 num_tx_timeout;
+       /* track consecutive timeout */
+       u8 tx_timeout_cnt;
        struct net_device *netdev;
        struct net_device_stats stats;
        u16 curr_pkt_filter;
index 296faec143657bde52c6304f429f4b0b231221a3..8f923d0d2ba657241c7634b26dc6f04697045e40 100644 (file)
@@ -169,6 +169,8 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
        if (!status) {
                priv->stats.tx_packets++;
                priv->stats.tx_bytes += skb->len;
+               if (priv->tx_timeout_cnt)
+                       priv->tx_timeout_cnt = 0;
        } else {
                priv->stats.tx_errors++;
        }