Skip to content

Commit 46fa38e

Browse files
committed
mac80211: allow software PS-Poll/U-APSD with AP_LINK_PS
When using RSS, frames might not be processed in the correct order, and thus AP_LINK_PS must be used; most likely with firmware keeping track of the powersave state, this is the case in iwlwifi now. In this case, the driver can use ieee80211_sta_ps_transition() to still have mac80211 manage powersave buffering. However, for U-APSD and PS-Poll this isn't sufficient. If the device can't manage that entirely on its own, mac80211's code should be used. To allow this, export two functions: ieee80211_sta_uapsd_trigger() and ieee80211_sta_pspoll(). Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1 parent 53873f1 commit 46fa38e

File tree

2 files changed

+71
-26
lines changed

2 files changed

+71
-26
lines changed

include/net/mac80211.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3996,6 +3996,33 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
39963996
return ret;
39973997
}
39983998

3999+
/**
4000+
* ieee80211_sta_pspoll - PS-Poll frame received
4001+
* @sta: currently connected station
4002+
*
4003+
* When operating in AP mode with the %IEEE80211_HW_AP_LINK_PS flag set,
4004+
* use this function to inform mac80211 that a PS-Poll frame from a
4005+
* connected station was received.
4006+
* This must be used in conjunction with ieee80211_sta_ps_transition()
4007+
* and possibly ieee80211_sta_uapsd_trigger(); calls to all three must
4008+
* be serialized.
4009+
*/
4010+
void ieee80211_sta_pspoll(struct ieee80211_sta *sta);
4011+
4012+
/**
4013+
* ieee80211_sta_uapsd_trigger - (potential) U-APSD trigger frame received
4014+
* @sta: currently connected station
4015+
* @tid: TID of the received (potential) trigger frame
4016+
*
4017+
* When operating in AP mode with the %IEEE80211_HW_AP_LINK_PS flag set,
4018+
* use this function to inform mac80211 that a (potential) trigger frame
4019+
* from a connected station was received.
4020+
* This must be used in conjunction with ieee80211_sta_ps_transition()
4021+
* and possibly ieee80211_sta_pspoll(); calls to all three must be
4022+
* serialized.
4023+
*/
4024+
void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *sta, u8 tid);
4025+
39994026
/*
40004027
* The TX headroom reserved by mac80211 for its own tx_status functions.
40014028
* This is enough for the radiotap header.

net/mac80211/rx.c

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,13 +1319,52 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *pubsta, bool start)
13191319
}
13201320
EXPORT_SYMBOL(ieee80211_sta_ps_transition);
13211321

1322+
void ieee80211_sta_pspoll(struct ieee80211_sta *pubsta)
1323+
{
1324+
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
1325+
1326+
if (test_sta_flag(sta, WLAN_STA_SP))
1327+
return;
1328+
1329+
if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER))
1330+
ieee80211_sta_ps_deliver_poll_response(sta);
1331+
else
1332+
set_sta_flag(sta, WLAN_STA_PSPOLL);
1333+
}
1334+
EXPORT_SYMBOL(ieee80211_sta_pspoll);
1335+
1336+
void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *pubsta, u8 tid)
1337+
{
1338+
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
1339+
u8 ac = ieee802_1d_to_ac[tid & 7];
1340+
1341+
/*
1342+
* If this AC is not trigger-enabled do nothing.
1343+
*
1344+
* NB: This could/should check a separate bitmap of trigger-
1345+
* enabled queues, but for now we only implement uAPSD w/o
1346+
* TSPEC changes to the ACs, so they're always the same.
1347+
*/
1348+
if (!(sta->sta.uapsd_queues & BIT(ac)))
1349+
return;
1350+
1351+
/* if we are in a service period, do nothing */
1352+
if (test_sta_flag(sta, WLAN_STA_SP))
1353+
return;
1354+
1355+
if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER))
1356+
ieee80211_sta_ps_deliver_uapsd(sta);
1357+
else
1358+
set_sta_flag(sta, WLAN_STA_UAPSD);
1359+
}
1360+
EXPORT_SYMBOL(ieee80211_sta_uapsd_trigger);
1361+
13221362
static ieee80211_rx_result debug_noinline
13231363
ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
13241364
{
13251365
struct ieee80211_sub_if_data *sdata = rx->sdata;
13261366
struct ieee80211_hdr *hdr = (void *)rx->skb->data;
13271367
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
1328-
int tid, ac;
13291368

13301369
if (!rx->sta)
13311370
return RX_CONTINUE;
@@ -1351,12 +1390,7 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
13511390
return RX_CONTINUE;
13521391

13531392
if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) {
1354-
if (!test_sta_flag(rx->sta, WLAN_STA_SP)) {
1355-
if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER))
1356-
ieee80211_sta_ps_deliver_poll_response(rx->sta);
1357-
else
1358-
set_sta_flag(rx->sta, WLAN_STA_PSPOLL);
1359-
}
1393+
ieee80211_sta_pspoll(&rx->sta->sta);
13601394

13611395
/* Free PS Poll skb here instead of returning RX_DROP that would
13621396
* count as an dropped frame. */
@@ -1368,27 +1402,11 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
13681402
ieee80211_has_pm(hdr->frame_control) &&
13691403
(ieee80211_is_data_qos(hdr->frame_control) ||
13701404
ieee80211_is_qos_nullfunc(hdr->frame_control))) {
1371-
tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
1372-
ac = ieee802_1d_to_ac[tid & 7];
1405+
u8 tid;
13731406

1374-
/*
1375-
* If this AC is not trigger-enabled do nothing.
1376-
*
1377-
* NB: This could/should check a separate bitmap of trigger-
1378-
* enabled queues, but for now we only implement uAPSD w/o
1379-
* TSPEC changes to the ACs, so they're always the same.
1380-
*/
1381-
if (!(rx->sta->sta.uapsd_queues & BIT(ac)))
1382-
return RX_CONTINUE;
1383-
1384-
/* if we are in a service period, do nothing */
1385-
if (test_sta_flag(rx->sta, WLAN_STA_SP))
1386-
return RX_CONTINUE;
1407+
tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
13871408

1388-
if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER))
1389-
ieee80211_sta_ps_deliver_uapsd(rx->sta);
1390-
else
1391-
set_sta_flag(rx->sta, WLAN_STA_UAPSD);
1409+
ieee80211_sta_uapsd_trigger(&rx->sta->sta, tid);
13921410
}
13931411

13941412
return RX_CONTINUE;

0 commit comments

Comments
 (0)