diff options
author | Johannes Berg <johannes.berg@intel.com> | 2016-05-03 09:58:00 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2016-05-12 05:16:55 -0400 |
commit | 46fa38e84b656f80edf83d21144221b0cad18d61 (patch) | |
tree | 42f204b73d06436d055c0e29d85495576a65ed09 /net | |
parent | 53873f134d285191ef6435882d55837093a36c53 (diff) |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/rx.c | 70 |
1 files changed, 44 insertions, 26 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c5678703921e..5e65e838992a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1319,13 +1319,52 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *pubsta, bool start) | |||
1319 | } | 1319 | } |
1320 | EXPORT_SYMBOL(ieee80211_sta_ps_transition); | 1320 | EXPORT_SYMBOL(ieee80211_sta_ps_transition); |
1321 | 1321 | ||
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 | |||
1322 | static ieee80211_rx_result debug_noinline | 1362 | static ieee80211_rx_result debug_noinline |
1323 | ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) | 1363 | ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) |
1324 | { | 1364 | { |
1325 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1365 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1326 | struct ieee80211_hdr *hdr = (void *)rx->skb->data; | 1366 | struct ieee80211_hdr *hdr = (void *)rx->skb->data; |
1327 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | 1367 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); |
1328 | int tid, ac; | ||
1329 | 1368 | ||
1330 | if (!rx->sta) | 1369 | if (!rx->sta) |
1331 | return RX_CONTINUE; | 1370 | return RX_CONTINUE; |
@@ -1351,12 +1390,7 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) | |||
1351 | return RX_CONTINUE; | 1390 | return RX_CONTINUE; |
1352 | 1391 | ||
1353 | if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) { | 1392 | if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) { |
1354 | if (!test_sta_flag(rx->sta, WLAN_STA_SP)) { | 1393 | ieee80211_sta_pspoll(&rx->sta->sta); |
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 | } | ||
1360 | 1394 | ||
1361 | /* Free PS Poll skb here instead of returning RX_DROP that would | 1395 | /* Free PS Poll skb here instead of returning RX_DROP that would |
1362 | * count as an dropped frame. */ | 1396 | * count as an dropped frame. */ |
@@ -1368,27 +1402,11 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx) | |||
1368 | ieee80211_has_pm(hdr->frame_control) && | 1402 | ieee80211_has_pm(hdr->frame_control) && |
1369 | (ieee80211_is_data_qos(hdr->frame_control) || | 1403 | (ieee80211_is_data_qos(hdr->frame_control) || |
1370 | ieee80211_is_qos_nullfunc(hdr->frame_control))) { | 1404 | ieee80211_is_qos_nullfunc(hdr->frame_control))) { |
1371 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 1405 | u8 tid; |
1372 | ac = ieee802_1d_to_ac[tid & 7]; | ||
1373 | 1406 | ||
1374 | /* | 1407 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
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; | ||
1387 | 1408 | ||
1388 | if (!test_sta_flag(rx->sta, WLAN_STA_PS_DRIVER)) | 1409 | ieee80211_sta_uapsd_trigger(&rx->sta->sta, tid); |
1389 | ieee80211_sta_ps_deliver_uapsd(rx->sta); | ||
1390 | else | ||
1391 | set_sta_flag(rx->sta, WLAN_STA_UAPSD); | ||
1392 | } | 1410 | } |
1393 | 1411 | ||
1394 | return RX_CONTINUE; | 1412 | return RX_CONTINUE; |