diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 102 |
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) | |||
1163 | EXPORT_SYMBOL(ieee80211_sta_ps_transition); | 1163 | EXPORT_SYMBOL(ieee80211_sta_ps_transition); |
1164 | 1164 | ||
1165 | static ieee80211_rx_result debug_noinline | 1165 | static ieee80211_rx_result debug_noinline |
1166 | ieee80211_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 | |||
1238 | static ieee80211_rx_result debug_noinline | ||
1166 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | 1239 | ieee80211_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 | ||
1475 | static ieee80211_rx_result debug_noinline | 1548 | static ieee80211_rx_result debug_noinline |
1476 | ieee80211_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 | |||
1502 | static ieee80211_rx_result debug_noinline | ||
1503 | ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx) | 1549 | ieee80211_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 |