aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorRajkumar Manoharan <rmanoharan@atheros.com>2011-05-03 07:33:59 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-05-05 14:59:07 -0400
commit1ddc286731134ad52a74b6956d9bc2a4369219a8 (patch)
tree8455c6c2db5d76d169bc652eb78b9c06c95b2fe8 /net/mac80211
parent4c468fe559f7910b1c6b10d3d223943fdd1b653c (diff)
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: Rajkumar Manoharan <rmanoharan@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/mlme.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 8d752b4d72ce..4f6b2675e41d 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -750,6 +750,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
750 dynamic_ps_enable_work); 750 dynamic_ps_enable_work);
751 struct ieee80211_sub_if_data *sdata = local->ps_sdata; 751 struct ieee80211_sub_if_data *sdata = local->ps_sdata;
752 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 752 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
753 unsigned long flags;
754 int q;
753 755
754 /* can only happen when PS was just disabled anyway */ 756 /* can only happen when PS was just disabled anyway */
755 if (!sdata) 757 if (!sdata)
@@ -758,6 +760,24 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
758 if (local->hw.conf.flags & IEEE80211_CONF_PS) 760 if (local->hw.conf.flags & IEEE80211_CONF_PS)
759 return; 761 return;
760 762
763 /*
764 * transmission can be stopped by others which leads to
765 * dynamic_ps_timer expiry. Postpond the ps timer if it
766 * is not the actual idle state.
767 */
768 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
769 for (q = 0; q < local->hw.queues; q++) {
770 if (local->queue_stop_reasons[q]) {
771 spin_unlock_irqrestore(&local->queue_stop_reason_lock,
772 flags);
773 mod_timer(&local->dynamic_ps_timer, jiffies +
774 msecs_to_jiffies(
775 local->hw.conf.dynamic_ps_timeout));
776 return;
777 }
778 }
779 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
780
761 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && 781 if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
762 (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { 782 (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) {
763 netif_tx_stop_all_queues(sdata->dev); 783 netif_tx_stop_all_queues(sdata->dev);