aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorKalle Valo <kalle.valo@nokia.com>2010-01-12 03:42:53 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-01-12 14:21:02 -0500
commit0c74211d19d83729c209ddcd4dc026c2aedeb29e (patch)
tree31e81616c508d63aef0ad418dc4252b87d1be208 /net/mac80211
parent5c1b98a52c3af1044c2d3842af8bae9a89502ca9 (diff)
mac80211: check uapsd state for dynamic power save
To make U-APSD client mode effective, we must not wake up from dynamic power save when transmitting frames. So if dynamic power save is enabled, it needs check the queue the transmitted packet is in and decide if we need to wake up or not. In a perfect world, where all packets would have correct QoS tags, U-APSD enabled queues should not trigger wakeup from power save. But in the real world, where very few packets have correct QoS tags, this won't work. For example, if only voip class has U-APSD enabled and we send a packet in voip class, but the packets we receive are in best effort class, we would receive the packets with the legacy power save method. And that would increase latencies too much from a voip application point of view. The workaround is to enable U-APSD for all qeueus and still use dynamic ps wakeup for all other queues except voip. That way we can still save power with a voip application and not sacrifice latency. Normal traffic (in background, best effort or video class) would still trigger wakeup from dynamic power save. Signed-off-by: Kalle Valo <kalle.valo@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/tx.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 6fcc85a2806a..daf81048c1f7 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -184,6 +184,7 @@ static ieee80211_tx_result debug_noinline
184ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) 184ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
185{ 185{
186 struct ieee80211_local *local = tx->local; 186 struct ieee80211_local *local = tx->local;
187 struct ieee80211_if_managed *ifmgd;
187 188
188 /* driver doesn't support power save */ 189 /* driver doesn't support power save */
189 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) 190 if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
@@ -208,6 +209,30 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
208 if (local->quiescing) 209 if (local->quiescing)
209 return TX_CONTINUE; 210 return TX_CONTINUE;
210 211
212 /* dynamic ps is supported only in managed mode */
213 if (tx->sdata->vif.type != NL80211_IFTYPE_STATION)
214 return TX_CONTINUE;
215
216 ifmgd = &tx->sdata->u.mgd;
217
218 /*
219 * Don't wakeup from power save if u-apsd is enabled, voip ac has
220 * u-apsd enabled and the frame is in voip class. This effectively
221 * means that even if all access categories have u-apsd enabled, in
222 * practise u-apsd is only used with the voip ac. This is a
223 * workaround for the case when received voip class packets do not
224 * have correct qos tag for some reason, due the network or the
225 * peer application.
226 *
227 * Note: local->uapsd_queues access is racy here. If the value is
228 * changed via debugfs, user needs to reassociate manually to have
229 * everything in sync.
230 */
231 if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
232 && (local->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
233 && skb_get_queue_mapping(tx->skb) == 0)
234 return TX_CONTINUE;
235
211 if (local->hw.conf.flags & IEEE80211_CONF_PS) { 236 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
212 ieee80211_stop_queues_by_reason(&local->hw, 237 ieee80211_stop_queues_by_reason(&local->hw,
213 IEEE80211_QUEUE_STOP_REASON_PS); 238 IEEE80211_QUEUE_STOP_REASON_PS);