diff options
author | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2010-03-01 20:23:50 -0500 |
---|---|---|
committer | Reinette Chatre <reinette.chatre@intel.com> | 2010-03-19 16:41:25 -0400 |
commit | b74e31a9bc1013e69b85b139072485dc153453dd (patch) | |
tree | cf3fa8db0a9a5d58d9bc633c5fe7b8e641d28d43 /drivers/net/wireless/iwlwifi/iwl-agn.c | |
parent | c11362c01b280f8b2c728bc64793d484282b8734 (diff) |
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>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 93931b61304b..82b1a3fb54ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -2074,6 +2074,13 @@ static void iwl_alive_start(struct iwl_priv *priv) | |||
2074 | /* After the ALIVE response, we can send host commands to the uCode */ | 2074 | /* After the ALIVE response, we can send host commands to the uCode */ |
2075 | set_bit(STATUS_ALIVE, &priv->status); | 2075 | set_bit(STATUS_ALIVE, &priv->status); |
2076 | 2076 | ||
2077 | if (priv->cfg->ops->lib->recover_from_tx_stall) { | ||
2078 | /* Enable timer to monitor the driver queues */ | ||
2079 | mod_timer(&priv->monitor_recover, | ||
2080 | jiffies + | ||
2081 | msecs_to_jiffies(priv->cfg->monitor_recover_period)); | ||
2082 | } | ||
2083 | |||
2077 | if (iwl_is_rfkill(priv)) | 2084 | if (iwl_is_rfkill(priv)) |
2078 | return; | 2085 | return; |
2079 | 2086 | ||
@@ -3224,6 +3231,13 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
3224 | priv->ucode_trace.data = (unsigned long)priv; | 3231 | priv->ucode_trace.data = (unsigned long)priv; |
3225 | priv->ucode_trace.function = iwl_bg_ucode_trace; | 3232 | priv->ucode_trace.function = iwl_bg_ucode_trace; |
3226 | 3233 | ||
3234 | if (priv->cfg->ops->lib->recover_from_tx_stall) { | ||
3235 | init_timer(&priv->monitor_recover); | ||
3236 | priv->monitor_recover.data = (unsigned long)priv; | ||
3237 | priv->monitor_recover.function = | ||
3238 | priv->cfg->ops->lib->recover_from_tx_stall; | ||
3239 | } | ||
3240 | |||
3227 | if (!priv->cfg->use_isr_legacy) | 3241 | if (!priv->cfg->use_isr_legacy) |
3228 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 3242 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
3229 | iwl_irq_tasklet, (unsigned long)priv); | 3243 | iwl_irq_tasklet, (unsigned long)priv); |
@@ -3243,6 +3257,8 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv) | |||
3243 | cancel_work_sync(&priv->beacon_update); | 3257 | cancel_work_sync(&priv->beacon_update); |
3244 | del_timer_sync(&priv->statistics_periodic); | 3258 | del_timer_sync(&priv->statistics_periodic); |
3245 | del_timer_sync(&priv->ucode_trace); | 3259 | del_timer_sync(&priv->ucode_trace); |
3260 | if (priv->cfg->ops->lib->recover_from_tx_stall) | ||
3261 | del_timer_sync(&priv->monitor_recover); | ||
3246 | } | 3262 | } |
3247 | 3263 | ||
3248 | static void iwl_init_hw_rates(struct iwl_priv *priv, | 3264 | static void iwl_init_hw_rates(struct iwl_priv *priv, |