diff options
-rw-r--r-- | net/mac80211/tx.c | 25 |
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 | |||
184 | ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) | 184 | ieee80211_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); |