aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/carl9170
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2010-10-29 17:26:13 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-11-15 13:25:32 -0500
commite4a668c59080f862af3ecc28b359533027cbe434 (patch)
treed9be11d5be940d49dfbb1f03c381c58799c9f78c /drivers/net/wireless/ath/carl9170
parente27769059ccb15273a7eb69ed31b8e08f9b0eda8 (diff)
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')
-rw-r--r--drivers/net/wireless/ath/carl9170/carl9170.h3
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c17
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c2
3 files changed, 20 insertions, 2 deletions
diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h
index b69d31972c77..d07ff7f2fd92 100644
--- a/drivers/net/wireless/ath/carl9170/carl9170.h
+++ b/drivers/net/wireless/ath/carl9170/carl9170.h
@@ -215,7 +215,7 @@ enum carl9170_restart_reasons {
215 CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS, 215 CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
216 CARL9170_RR_WATCHDOG, 216 CARL9170_RR_WATCHDOG,
217 CARL9170_RR_STUCK_TX, 217 CARL9170_RR_STUCK_TX,
218 CARL9170_RR_SLOW_SYSTEM, 218 CARL9170_RR_UNRESPONSIVE_DEVICE,
219 CARL9170_RR_COMMAND_TIMEOUT, 219 CARL9170_RR_COMMAND_TIMEOUT,
220 CARL9170_RR_TOO_MANY_PHY_ERRORS, 220 CARL9170_RR_TOO_MANY_PHY_ERRORS,
221 CARL9170_RR_LOST_RSP, 221 CARL9170_RR_LOST_RSP,
@@ -287,6 +287,7 @@ struct ar9170 {
287 287
288 /* reset / stuck frames/queue detection */ 288 /* reset / stuck frames/queue detection */
289 struct work_struct restart_work; 289 struct work_struct restart_work;
290 struct work_struct ping_work;
290 unsigned int restart_counter; 291 unsigned int restart_counter;
291 unsigned long queue_stop_timeout[__AR9170_NUM_TXQ]; 292 unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
292 unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ]; 293 unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index d521bc2b0496..4ae6a5849076 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)
428 cancel_delayed_work_sync(&ar->led_work); 428 cancel_delayed_work_sync(&ar->led_work);
429#endif /* CONFIG_CARL9170_LEDS */ 429#endif /* CONFIG_CARL9170_LEDS */
430 cancel_work_sync(&ar->ps_work); 430 cancel_work_sync(&ar->ps_work);
431 cancel_work_sync(&ar->ping_work);
431 cancel_work_sync(&ar->ampdu_work); 432 cancel_work_sync(&ar->ampdu_work);
432} 433}
433 434
@@ -533,6 +534,21 @@ void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
533 */ 534 */
534} 535}
535 536
537static void carl9170_ping_work(struct work_struct *work)
538{
539 struct ar9170 *ar = container_of(work, struct ar9170, ping_work);
540 int err;
541
542 if (!IS_STARTED(ar))
543 return;
544
545 mutex_lock(&ar->mutex);
546 err = carl9170_echo_test(ar, 0xdeadbeef);
547 if (err)
548 carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE);
549 mutex_unlock(&ar->mutex);
550}
551
536static int carl9170_init_interface(struct ar9170 *ar, 552static int carl9170_init_interface(struct ar9170 *ar,
537 struct ieee80211_vif *vif) 553 struct ieee80211_vif *vif)
538{ 554{
@@ -1614,6 +1630,7 @@ void *carl9170_alloc(size_t priv_size)
1614 skb_queue_head_init(&ar->tx_pending[i]); 1630 skb_queue_head_init(&ar->tx_pending[i]);
1615 } 1631 }
1616 INIT_WORK(&ar->ps_work, carl9170_ps_work); 1632 INIT_WORK(&ar->ps_work, carl9170_ps_work);
1633 INIT_WORK(&ar->ping_work, carl9170_ping_work);
1617 INIT_WORK(&ar->restart_work, carl9170_restart_work); 1634 INIT_WORK(&ar->restart_work, carl9170_restart_work);
1618 INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work); 1635 INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
1619 INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor); 1636 INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index d8607f4c144d..ddf5373ee689 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -431,7 +431,7 @@ static void carl9170_usb_rx_complete(struct urb *urb)
431 * device. 431 * device.
432 */ 432 */
433 433
434 carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM); 434 ieee80211_queue_work(ar->hw, &ar->ping_work);
435 } 435 }
436 } else { 436 } else {
437 /* 437 /*