aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/carl9170/main.c
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2010-10-29 23:26:13 +0200
committerJohn W. Linville <linville@tuxdriver.com>2010-11-15 13:25:32 -0500
commite4a668c59080f862af3ecc28b359533027cbe434 (patch)
treed9be11d5be940d49dfbb1f03c381c58799c9f78c /drivers/net/wireless/ath/carl9170/main.c
parente27769059ccb15273a7eb69ed31b8e08f9b0eda8 (diff)
downloadkernel_samsung_smdk4412-e4a668c59080f862af3ecc28b359533027cbe434.zip
kernel_samsung_smdk4412-e4a668c59080f862af3ecc28b359533027cbe434.tar.gz
kernel_samsung_smdk4412-e4a668c59080f862af3ecc28b359533027cbe434.tar.bz2
carl9170: fix spurious restart due to high latency
RX Stress tests of unidirectional bulk traffic with bitrates of up to 220Mbit/s have revealed that the fatal-event recovery logic [which was solely triggered by an out-of-rx-buffer situation] is too aggressive. The new method now "pings" the device and then decides - based on the response - whenever a restart is needed or not. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/carl9170/main.c')
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index d521bc2..4ae6a58 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -428,6 +428,7 @@ static void carl9170_cancel_worker(struct ar9170 *ar)
cancel_delayed_work_sync(&ar->led_work);
#endif /* CONFIG_CARL9170_LEDS */
cancel_work_sync(&ar->ps_work);
+ cancel_work_sync(&ar->ping_work);
cancel_work_sync(&ar->ampdu_work);
}
@@ -533,6 +534,21 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
*/
}
+static void carl9170_ping_work(struct work_struct *work)
+{
+ struct ar9170 *ar = container_of(work, struct ar9170, ping_work);
+ int err;
+
+ if (!IS_STARTED(ar))
+ return;
+
+ mutex_lock(&ar->mutex);
+ err = carl9170_echo_test(ar, 0xdeadbeef);
+ if (err)
+ carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE);
+ mutex_unlock(&ar->mutex);
+}
+
static int carl9170_init_interface(struct ar9170 *ar,
struct ieee80211_vif *vif)
{
@@ -1614,6 +1630,7 @@ void *carl9170_alloc(size_t priv_size)
skb_queue_head_init(&ar->tx_pending[i]);
}
INIT_WORK(&ar->ps_work, carl9170_ps_work);
+ INIT_WORK(&ar->ping_work, carl9170_ping_work);
INIT_WORK(&ar->restart_work, carl9170_restart_work);
INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);