Commit 1ddc2867 authored by Rajkumar Manoharan's avatar Rajkumar Manoharan Committed by John W. Linville

mac80211: Postpond ps timer if tx is stopped by others

Whenever the driver's queue depth reaches the max, the queues are
stopped by the driver till the driver can accept the frames.
At the mean time dynamic_ps_timer can be expired due to not
receiving packet from upper layer which could restart the transmission
at the end of ps work. Due to the mismatch with driver state,
mac80211 is unneccesarity buffering all the frames till the driver
wakes up the queue.

Check whether there is no transmit or the tx queues were stopped by some
reasons. If any of the queue was stopped, the postpond ps timer and
do not restart netif_tx.
Signed-off-by: default avatarRajkumar Manoharan <rmanoharan@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 4c468fe5
...@@ -750,6 +750,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) ...@@ -750,6 +750,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
dynamic_ps_enable_work); dynamic_ps_enable_work);
struct ieee80211_sub_if_data *sdata = local->ps_sdata; struct ieee80211_sub_if_data *sdata = local->ps_sdata;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
unsigned long flags;
int q;
/* can only happen when PS was just disabled anyway */ /* can only happen when PS was just disabled anyway */
if (!sdata) if (!sdata)
...@@ -758,6 +760,24 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) ...@@ -758,6 +760,24 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
if (local->hw.conf.flags & IEEE80211_CONF_PS) if (local->hw.conf.flags & IEEE80211_CONF_PS)
return; return;
/*
* transmission can be stopped by others which leads to
* dynamic_ps_timer expiry. Postpond the ps timer if it
* is not the actual idle state.
*/
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
for (q = 0; q < local->hw.queues; q++) {
if (local->queue_stop_reasons[q]) {
spin_unlock_irqrestore(&local->queue_stop_reason_lock,
flags);
mod_timer(&local->dynamic_ps_timer, jiffies +
msecs_to_jiffies(
local->hw.conf.dynamic_ps_timeout));
return;
}
}
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
(!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) {
netif_tx_stop_all_queues(sdata->dev); netif_tx_stop_all_queues(sdata->dev);
......
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