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>
This commit is contained in:
committed by
John W. Linville
parent
e27769059c
commit
e4a668c590
@@ -215,7 +215,7 @@ enum carl9170_restart_reasons {
|
|||||||
CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
|
CARL9170_RR_TOO_MANY_FIRMWARE_ERRORS,
|
||||||
CARL9170_RR_WATCHDOG,
|
CARL9170_RR_WATCHDOG,
|
||||||
CARL9170_RR_STUCK_TX,
|
CARL9170_RR_STUCK_TX,
|
||||||
CARL9170_RR_SLOW_SYSTEM,
|
CARL9170_RR_UNRESPONSIVE_DEVICE,
|
||||||
CARL9170_RR_COMMAND_TIMEOUT,
|
CARL9170_RR_COMMAND_TIMEOUT,
|
||||||
CARL9170_RR_TOO_MANY_PHY_ERRORS,
|
CARL9170_RR_TOO_MANY_PHY_ERRORS,
|
||||||
CARL9170_RR_LOST_RSP,
|
CARL9170_RR_LOST_RSP,
|
||||||
@@ -287,6 +287,7 @@ struct ar9170 {
|
|||||||
|
|
||||||
/* reset / stuck frames/queue detection */
|
/* reset / stuck frames/queue detection */
|
||||||
struct work_struct restart_work;
|
struct work_struct restart_work;
|
||||||
|
struct work_struct ping_work;
|
||||||
unsigned int restart_counter;
|
unsigned int restart_counter;
|
||||||
unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
|
unsigned long queue_stop_timeout[__AR9170_NUM_TXQ];
|
||||||
unsigned long max_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);
|
cancel_delayed_work_sync(&ar->led_work);
|
||||||
#endif /* CONFIG_CARL9170_LEDS */
|
#endif /* CONFIG_CARL9170_LEDS */
|
||||||
cancel_work_sync(&ar->ps_work);
|
cancel_work_sync(&ar->ps_work);
|
||||||
|
cancel_work_sync(&ar->ping_work);
|
||||||
cancel_work_sync(&ar->ampdu_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,
|
static int carl9170_init_interface(struct ar9170 *ar,
|
||||||
struct ieee80211_vif *vif)
|
struct ieee80211_vif *vif)
|
||||||
{
|
{
|
||||||
@@ -1614,6 +1630,7 @@ void *carl9170_alloc(size_t priv_size)
|
|||||||
skb_queue_head_init(&ar->tx_pending[i]);
|
skb_queue_head_init(&ar->tx_pending[i]);
|
||||||
}
|
}
|
||||||
INIT_WORK(&ar->ps_work, carl9170_ps_work);
|
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->restart_work, carl9170_restart_work);
|
||||||
INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
|
INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
|
||||||
INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
|
INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
|
||||||
|
@@ -431,7 +431,7 @@ static void carl9170_usb_rx_complete(struct urb *urb)
|
|||||||
* device.
|
* device.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
carl9170_restart(ar, CARL9170_RR_SLOW_SYSTEM);
|
ieee80211_queue_work(ar->hw, &ar->ping_work);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user