Commit 0c74211d authored by Kalle Valo's avatar Kalle Valo Committed by John W. Linville

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: default avatarKalle Valo <kalle.valo@nokia.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 5c1b98a5
...@@ -184,6 +184,7 @@ static ieee80211_tx_result debug_noinline ...@@ -184,6 +184,7 @@ static ieee80211_tx_result debug_noinline
ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
{ {
struct ieee80211_local *local = tx->local; struct ieee80211_local *local = tx->local;
struct ieee80211_if_managed *ifmgd;
/* driver doesn't support power save */ /* driver doesn't support power save */
if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS)) if (!(local->hw.flags & IEEE80211_HW_SUPPORTS_PS))
...@@ -208,6 +209,30 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) ...@@ -208,6 +209,30 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
if (local->quiescing) if (local->quiescing)
return TX_CONTINUE; return TX_CONTINUE;
/* dynamic ps is supported only in managed mode */
if (tx->sdata->vif.type != NL80211_IFTYPE_STATION)
return TX_CONTINUE;
ifmgd = &tx->sdata->u.mgd;
/*
* Don't wakeup from power save if u-apsd is enabled, voip ac has
* u-apsd enabled and the frame is in voip class. This effectively
* means that even if all access categories have u-apsd enabled, in
* practise u-apsd is only used with the voip ac. This is a
* workaround for the case when received voip class packets do not
* have correct qos tag for some reason, due the network or the
* peer application.
*
* Note: local->uapsd_queues access is racy here. If the value is
* changed via debugfs, user needs to reassociate manually to have
* everything in sync.
*/
if ((ifmgd->flags & IEEE80211_STA_UAPSD_ENABLED)
&& (local->uapsd_queues & IEEE80211_WMM_IE_STA_QOSINFO_AC_VO)
&& skb_get_queue_mapping(tx->skb) == 0)
return TX_CONTINUE;
if (local->hw.conf.flags & IEEE80211_CONF_PS) { if (local->hw.conf.flags & IEEE80211_CONF_PS) {
ieee80211_stop_queues_by_reason(&local->hw, ieee80211_stop_queues_by_reason(&local->hw,
IEEE80211_QUEUE_STOP_REASON_PS); IEEE80211_QUEUE_STOP_REASON_PS);
......
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