From 8908c7d5392671610a2d80107845d4aeee92d9c1 Mon Sep 17 00:00:00 2001 From: Ashok Nagarajan Date: Fri, 8 Mar 2013 10:58:45 -0800 Subject: mwifiex: Trigger a card reset on reaching tx_timeout threshold 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 Signed-off-by: Paul Stewart Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/main.c | 15 ++++++++++++--- drivers/net/wireless/mwifiex/main.h | 5 +++++ drivers/net/wireless/mwifiex/txrx.c | 2 ++ 3 files changed, 19 insertions(+), 3 deletions(-) (limited to 'drivers/net/wireless/mwifiex') diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 9c802ede9c3..121443a0f2a 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -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); + } } /* diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 560cf7312d0..920657587ff 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -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; diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 296faec1436..8f923d0d2ba 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c @@ -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++; } -- cgit v1.2.3