diff options
author | Christian Lamparter <chunkeey@googlemail.com> | 2010-10-29 17:26:13 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-15 13:25:32 -0500 |
commit | e4a668c59080f862af3ecc28b359533027cbe434 (patch) | |
tree | d9be11d5be940d49dfbb1f03c381c58799c9f78c /drivers/net | |
parent | e27769059ccb15273a7eb69ed31b8e08f9b0eda8 (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')
-rw-r--r-- | drivers/net/wireless/ath/carl9170/carl9170.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/carl9170/main.c | 17 | ||||
-rw-r--r-- | drivers/net/wireless/ath/carl9170/usb.c | 2 |
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 | ||
537 | static 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 | |||
536 | static int carl9170_init_interface(struct ar9170 *ar, | 552 | static 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 | /* |