iwlwifi: Recover TX flow stall due to stuck queue
Monitors the internal TX queues periodically. When a queue is stuck
for some unknown conditions causing the throughput to drop and the
transfer is stop, the driver will force firmware reload and bring the
system back to normal operational state.
The iwlwifi devices behave differently in this regard so this feature is
made part of the ops infrastructure so we can have more control on how to
monitor and recover from tx queue stall case per device.
Signed-off-by: Trieu 'Andrew' Nguyen <trieux.t.nguyen@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 6687b94..4995134 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -2501,6 +2501,13 @@
/* After the ALIVE response, we can send commands to 3945 uCode */
set_bit(STATUS_ALIVE, &priv->status);
+ if (priv->cfg->ops->lib->recover_from_tx_stall) {
+ /* Enable timer to monitor the driver queues */
+ mod_timer(&priv->monitor_recover,
+ jiffies +
+ msecs_to_jiffies(priv->cfg->monitor_recover_period));
+ }
+
if (iwl_is_rfkill(priv))
return;
@@ -3796,6 +3803,13 @@
iwl3945_hw_setup_deferred_work(priv);
+ if (priv->cfg->ops->lib->recover_from_tx_stall) {
+ init_timer(&priv->monitor_recover);
+ priv->monitor_recover.data = (unsigned long)priv;
+ priv->monitor_recover.function =
+ priv->cfg->ops->lib->recover_from_tx_stall;
+ }
+
tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
iwl3945_irq_tasklet, (unsigned long)priv);
}
@@ -3808,6 +3822,8 @@
cancel_delayed_work(&priv->scan_check);
cancel_delayed_work(&priv->alive_start);
cancel_work_sync(&priv->beacon_update);
+ if (priv->cfg->ops->lib->recover_from_tx_stall)
+ del_timer_sync(&priv->monitor_recover);
}
static struct attribute *iwl3945_sysfs_entries[] = {