aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-09-29 10:04:33 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-09-30 15:57:15 -0400
commit47086fc51aa2220f58049704a8b73e4fcdf372b9 (patch)
tree31f7ae0e59318352d772b62fa26316d349cde88e /net/mac80211/rx.c
parent4049e09acdf4ffd270cb8fbf1cf5b39c3d02357c (diff)
mac80211: implement uAPSD
Add uAPSD support to mac80211. This is probably not possible with all devices, so advertising it with the cfg80211 flag will be left up to drivers that want it. Due to my previous patches it is now a fairly straight-forward extension. Drivers need to have accurate TX status reporting for the EOSP frame. For drivers that buffer themselves, the provided APIs allow releasing the right number of frames, but then drivers need to set EOSP and more-data themselves. This is documented in more detail in the new code itself. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c102
1 files changed, 74 insertions, 28 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index db46601e50b..9a703f00b5f 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1163,6 +1163,79 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start)
1163EXPORT_SYMBOL(ieee80211_sta_ps_transition); 1163EXPORT_SYMBOL(ieee80211_sta_ps_transition);
1164 1164
1165static ieee80211_rx_result debug_noinline 1165static ieee80211_rx_result debug_noinline
1166ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
1167{
1168 struct ieee80211_sub_if_data *sdata = rx->sdata;
1169 struct ieee80211_hdr *hdr = (void *)rx->skb->data;
1170 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
1171 int tid, ac;
1172
1173 if (!rx->sta || !(status->rx_flags & IEEE80211_RX_RA_MATCH))
1174 return RX_CONTINUE;
1175
1176 if (sdata->vif.type != NL80211_IFTYPE_AP &&
1177 sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
1178 return RX_CONTINUE;
1179
1180 /*
1181 * The device handles station powersave, so don't do anything about
1182 * uAPSD and PS-Poll frames (the latter shouldn't even come up from
1183 * it to mac80211 since they're handled.)
1184 */
1185 if (sdata->local->hw.flags & IEEE80211_HW_AP_LINK_PS)
1186 return RX_CONTINUE;
1187
1188 /*
1189 * Don't do anything if the station isn't already asleep. In
1190 * the uAPSD case, the station will probably be marked asleep,
1191 * in the PS-Poll case the station must be confused ...
1192 */
1193 if (!test_sta_flags(rx->sta, WLAN_STA_PS_STA))
1194 return RX_CONTINUE;
1195
1196 if (unlikely(ieee80211_is_pspoll(hdr->frame_control))) {
1197 if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER))
1198 ieee80211_sta_ps_deliver_poll_response(rx->sta);
1199 else
1200 set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
1201
1202 /* Free PS Poll skb here instead of returning RX_DROP that would
1203 * count as an dropped frame. */
1204 dev_kfree_skb(rx->skb);
1205
1206 return RX_QUEUED;
1207 } else if (!ieee80211_has_morefrags(hdr->frame_control) &&
1208 !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
1209 ieee80211_has_pm(hdr->frame_control) &&
1210 (ieee80211_is_data_qos(hdr->frame_control) ||
1211 ieee80211_is_qos_nullfunc(hdr->frame_control))) {
1212 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
1213 ac = ieee802_1d_to_ac[tid & 7];
1214
1215 /*
1216 * If this AC is not trigger-enabled do nothing.
1217 *
1218 * NB: This could/should check a separate bitmap of trigger-
1219 * enabled queues, but for now we only implement uAPSD w/o
1220 * TSPEC changes to the ACs, so they're always the same.
1221 */
1222 if (!(rx->sta->sta.uapsd_queues & BIT(ac)))
1223 return RX_CONTINUE;
1224
1225 /* if we are in a service period, do nothing */
1226 if (test_sta_flags(rx->sta, WLAN_STA_SP))
1227 return RX_CONTINUE;
1228
1229 if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER))
1230 ieee80211_sta_ps_deliver_uapsd(rx->sta);
1231 else
1232 set_sta_flags(rx->sta, WLAN_STA_UAPSD);
1233 }
1234
1235 return RX_CONTINUE;
1236}
1237
1238static ieee80211_rx_result debug_noinline
1166ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) 1239ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
1167{ 1240{
1168 struct sta_info *sta = rx->sta; 1241 struct sta_info *sta = rx->sta;
@@ -1473,33 +1546,6 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
1473} 1546}
1474 1547
1475static ieee80211_rx_result debug_noinline 1548static ieee80211_rx_result debug_noinline
1476ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
1477{
1478 struct ieee80211_sub_if_data *sdata = rx->sdata;
1479 __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control;
1480 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
1481
1482 if (likely(!rx->sta || !ieee80211_is_pspoll(fc) ||
1483 !(status->rx_flags & IEEE80211_RX_RA_MATCH)))
1484 return RX_CONTINUE;
1485
1486 if ((sdata->vif.type != NL80211_IFTYPE_AP) &&
1487 (sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
1488 return RX_DROP_UNUSABLE;
1489
1490 if (!test_sta_flags(rx->sta, WLAN_STA_PS_DRIVER))
1491 ieee80211_sta_ps_deliver_poll_response(rx->sta);
1492 else
1493 set_sta_flags(rx->sta, WLAN_STA_PSPOLL);
1494
1495 /* Free PS Poll skb here instead of returning RX_DROP that would
1496 * count as an dropped frame. */
1497 dev_kfree_skb(rx->skb);
1498
1499 return RX_QUEUED;
1500}
1501
1502static ieee80211_rx_result debug_noinline
1503ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) 1549ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
1504{ 1550{
1505 u8 *data = rx->skb->data; 1551 u8 *data = rx->skb->data;
@@ -2567,9 +2613,9 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx)
2567 2613
2568 CALL_RXH(ieee80211_rx_h_decrypt) 2614 CALL_RXH(ieee80211_rx_h_decrypt)
2569 CALL_RXH(ieee80211_rx_h_check_more_data) 2615 CALL_RXH(ieee80211_rx_h_check_more_data)
2616 CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll)
2570 CALL_RXH(ieee80211_rx_h_sta_process) 2617 CALL_RXH(ieee80211_rx_h_sta_process)
2571 CALL_RXH(ieee80211_rx_h_defragment) 2618 CALL_RXH(ieee80211_rx_h_defragment)
2572 CALL_RXH(ieee80211_rx_h_ps_poll)
2573 CALL_RXH(ieee80211_rx_h_michael_mic_verify) 2619 CALL_RXH(ieee80211_rx_h_michael_mic_verify)
2574 /* must be after MMIC verify so header is counted in MPDU mic */ 2620 /* must be after MMIC verify so header is counted in MPDU mic */
2575#ifdef CONFIG_MAC80211_MESH 2621#ifdef CONFIG_MAC80211_MESH