Commit e4a668c5 authored by Christian Lamparter's avatar Christian Lamparter Committed by John W. Linville

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: default avatarChristian Lamparter <chunkeey@googlemail.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent e2776905
......@@ -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,
......@@ -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];
......
......@@ -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);
......
......@@ -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 {
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment