aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
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 db46601e50bf..9a703f00b5fb 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