Skip to content

Commit

Permalink
carl9170: fix spurious restart due to high latency
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christian Lamparter authored and John W. Linville committed Nov 15, 2010
1 parent e277690 commit e4a668c
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 2 deletions.
3 changes: 2 additions & 1 deletion drivers/net/wireless/ath/carl9170/carl9170.h
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ enum carl9170_restart_reasons {
CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
CARL9170_RR_WATCHDOG,
CARL9170_RR_STUCK_TX,
CARL9170_RR_SLOW_SYSTEM,
CARL9170_RR_UNRESPONSIVE_DEVICE,
CARL9170_RR_COMMAND_TIMEOUT,
CARL9170_RR_TOO_MANY_PHY_ERRORS,
CARL9170_RR_LOST_RSP,
Expand Down Expand Up @@ -287,6 +287,7 @@ struct ar9170 {

/* reset / stuck frames/queue detection */
struct work_struct restart_work;
struct work_struct ping_work;
unsigned int restart_counter;
unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
unsigned long max_queue_stop_timeout[__AR9170_NUM_TXQ];
Expand Down
17 changes: 17 additions & 0 deletions drivers/net/wireless/ath/carl9170/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/ath/carl9170/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ static void carl9170_usb_rx_complete(struct urb *urb)
* device.
*/

carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
ieee80211_queue_work(ar->hw, &ar->ping_work);
}
} else {
/*
Expand Down

0 comments on commit e4a668c

Please sign in to comment.