diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/rx.c | 102 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 170 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 8 | ||||
-rw-r--r-- | net/mac80211/status.c | 15 | ||||
-rw-r--r-- | net/mac80211/tx.c | 8 |
5 files changed, 224 insertions, 79 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 |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index b3f841948c09..f9079e478f77 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -248,6 +248,9 @@ static void sta_unblock(struct work_struct *wk) | |||
248 | else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) { | 248 | else if (test_and_clear_sta_flags(sta, WLAN_STA_PSPOLL)) { |
249 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER); | 249 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER); |
250 | ieee80211_sta_ps_deliver_poll_response(sta); | 250 | ieee80211_sta_ps_deliver_poll_response(sta); |
251 | } else if (test_and_clear_sta_flags(sta, WLAN_STA_UAPSD)) { | ||
252 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER); | ||
253 | ieee80211_sta_ps_deliver_uapsd(sta); | ||
251 | } else | 254 | } else |
252 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER); | 255 | clear_sta_flags(sta, WLAN_STA_PS_DRIVER); |
253 | } | 256 | } |
@@ -1117,6 +1120,8 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1117 | struct sk_buff_head pending; | 1120 | struct sk_buff_head pending; |
1118 | int filtered = 0, buffered = 0, ac; | 1121 | int filtered = 0, buffered = 0, ac; |
1119 | 1122 | ||
1123 | clear_sta_flags(sta, WLAN_STA_SP); | ||
1124 | |||
1120 | BUILD_BUG_ON(BITS_TO_LONGS(STA_TID_NUM) > 1); | 1125 | BUILD_BUG_ON(BITS_TO_LONGS(STA_TID_NUM) > 1); |
1121 | sta->driver_buffered_tids = 0; | 1126 | sta->driver_buffered_tids = 0; |
1122 | 1127 | ||
@@ -1152,32 +1157,28 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1152 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1157 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1153 | } | 1158 | } |
1154 | 1159 | ||
1155 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | 1160 | static void |
1161 | ieee80211_sta_ps_deliver_response(struct sta_info *sta, | ||
1162 | int n_frames, u8 ignored_acs, | ||
1163 | enum ieee80211_frame_release_type reason) | ||
1156 | { | 1164 | { |
1157 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 1165 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
1158 | struct ieee80211_local *local = sdata->local; | 1166 | struct ieee80211_local *local = sdata->local; |
1159 | struct sk_buff *skb = NULL; | ||
1160 | bool found = false; | 1167 | bool found = false; |
1161 | bool more_data = false; | 1168 | bool more_data = false; |
1162 | int ac; | 1169 | int ac; |
1163 | unsigned long driver_release_tids = 0; | 1170 | unsigned long driver_release_tids = 0; |
1164 | u8 ignore_for_response = sta->sta.uapsd_queues; | 1171 | struct sk_buff_head frames; |
1165 | 1172 | ||
1166 | /* | 1173 | __skb_queue_head_init(&frames); |
1167 | * If all ACs are delivery-enabled then we should reply | ||
1168 | * from any of them, if only some are enabled we reply | ||
1169 | * only from the non-enabled ones. | ||
1170 | */ | ||
1171 | if (ignore_for_response == BIT(IEEE80211_NUM_ACS) - 1) | ||
1172 | ignore_for_response = 0; | ||
1173 | 1174 | ||
1174 | /* | 1175 | /* |
1175 | * Get response frame and more data bit for it. | 1176 | * Get response frame(s) and more data bit for it. |
1176 | */ | 1177 | */ |
1177 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 1178 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
1178 | unsigned long tids; | 1179 | unsigned long tids; |
1179 | 1180 | ||
1180 | if (ignore_for_response & BIT(ac)) | 1181 | if (ignored_acs & BIT(ac)) |
1181 | continue; | 1182 | continue; |
1182 | 1183 | ||
1183 | tids = ieee80211_tids_for_ac(ac); | 1184 | tids = ieee80211_tids_for_ac(ac); |
@@ -1187,14 +1188,22 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | |||
1187 | if (driver_release_tids) { | 1188 | if (driver_release_tids) { |
1188 | found = true; | 1189 | found = true; |
1189 | } else { | 1190 | } else { |
1190 | skb = skb_dequeue(&sta->tx_filtered[ac]); | 1191 | struct sk_buff *skb; |
1191 | if (!skb) { | 1192 | |
1192 | skb = skb_dequeue(&sta->ps_tx_buf[ac]); | 1193 | while (n_frames > 0) { |
1193 | if (skb) | 1194 | skb = skb_dequeue(&sta->tx_filtered[ac]); |
1194 | local->total_ps_buffered--; | 1195 | if (!skb) { |
1195 | } | 1196 | skb = skb_dequeue( |
1196 | if (skb) | 1197 | &sta->ps_tx_buf[ac]); |
1198 | if (skb) | ||
1199 | local->total_ps_buffered--; | ||
1200 | } | ||
1201 | if (!skb) | ||
1202 | break; | ||
1203 | n_frames--; | ||
1197 | found = true; | 1204 | found = true; |
1205 | __skb_queue_tail(&frames, skb); | ||
1206 | } | ||
1198 | } | 1207 | } |
1199 | 1208 | ||
1200 | /* | 1209 | /* |
@@ -1202,7 +1211,8 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | |||
1202 | * certainly there's more data if we release just a | 1211 | * certainly there's more data if we release just a |
1203 | * single frame now (from a single TID). | 1212 | * single frame now (from a single TID). |
1204 | */ | 1213 | */ |
1205 | if (hweight16(driver_release_tids) > 1) { | 1214 | if (reason == IEEE80211_FRAME_RELEASE_PSPOLL && |
1215 | hweight16(driver_release_tids) > 1) { | ||
1206 | more_data = true; | 1216 | more_data = true; |
1207 | driver_release_tids = | 1217 | driver_release_tids = |
1208 | BIT(ffs(driver_release_tids) - 1); | 1218 | BIT(ffs(driver_release_tids) - 1); |
@@ -1225,38 +1235,56 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | |||
1225 | * Should we send it a null-func frame indicating we | 1235 | * Should we send it a null-func frame indicating we |
1226 | * have nothing buffered for it? | 1236 | * have nothing buffered for it? |
1227 | */ | 1237 | */ |
1228 | printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " | 1238 | if (reason == IEEE80211_FRAME_RELEASE_PSPOLL) |
1229 | "though there are no buffered frames for it\n", | 1239 | printk(KERN_DEBUG "%s: STA %pM sent PS Poll even " |
1230 | sdata->name, sta->sta.addr); | 1240 | "though there are no buffered frames for it\n", |
1241 | sdata->name, sta->sta.addr); | ||
1231 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 1242 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
1232 | 1243 | ||
1233 | return; | 1244 | return; |
1234 | } | 1245 | } |
1235 | 1246 | ||
1236 | if (skb) { | 1247 | if (!driver_release_tids) { |
1237 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1248 | struct sk_buff_head pending; |
1238 | struct ieee80211_hdr *hdr = | 1249 | struct sk_buff *skb; |
1239 | (struct ieee80211_hdr *) skb->data; | ||
1240 | 1250 | ||
1241 | /* | 1251 | skb_queue_head_init(&pending); |
1242 | * Tell TX path to send this frame even though the STA may | ||
1243 | * still remain is PS mode after this frame exchange. | ||
1244 | */ | ||
1245 | info->flags |= IEEE80211_TX_CTL_PSPOLL_RESPONSE; | ||
1246 | 1252 | ||
1247 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 1253 | while ((skb = __skb_dequeue(&frames))) { |
1248 | printk(KERN_DEBUG "STA %pM aid %d: PS Poll\n", | 1254 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1249 | sta->sta.addr, sta->sta.aid); | 1255 | struct ieee80211_hdr *hdr = (void *) skb->data; |
1250 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | ||
1251 | 1256 | ||
1252 | /* Use MoreData flag to indicate whether there are more | 1257 | /* |
1253 | * buffered frames for this STA */ | 1258 | * Tell TX path to send this frame even though the |
1254 | if (!more_data) | 1259 | * STA may still remain is PS mode after this frame |
1255 | hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_MOREDATA); | 1260 | * exchange. |
1256 | else | 1261 | */ |
1257 | hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 1262 | info->flags |= IEEE80211_TX_CTL_POLL_RESPONSE; |
1263 | |||
1264 | /* | ||
1265 | * Use MoreData flag to indicate whether there are | ||
1266 | * more buffered frames for this STA | ||
1267 | */ | ||
1268 | if (!more_data) | ||
1269 | hdr->frame_control &= | ||
1270 | cpu_to_le16(~IEEE80211_FCTL_MOREDATA); | ||
1271 | else | ||
1272 | hdr->frame_control |= | ||
1273 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | ||
1274 | |||
1275 | if (reason == IEEE80211_FRAME_RELEASE_UAPSD && | ||
1276 | skb_queue_empty(&frames)) { | ||
1277 | /* set EOSP for the frame */ | ||
1278 | u8 *p = ieee80211_get_qos_ctl(hdr); | ||
1279 | *p |= IEEE80211_QOS_CTL_EOSP; | ||
1280 | info->flags |= IEEE80211_TX_STATUS_EOSP | | ||
1281 | IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1282 | } | ||
1258 | 1283 | ||
1259 | ieee80211_add_pending_skb(local, skb); | 1284 | __skb_queue_tail(&pending, skb); |
1285 | } | ||
1286 | |||
1287 | ieee80211_add_pending_skbs(local, &pending); | ||
1260 | 1288 | ||
1261 | sta_info_recalc_tim(sta); | 1289 | sta_info_recalc_tim(sta); |
1262 | } else { | 1290 | } else { |
@@ -1271,8 +1299,7 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | |||
1271 | * needs to be set anyway. | 1299 | * needs to be set anyway. |
1272 | */ | 1300 | */ |
1273 | drv_release_buffered_frames(local, sta, driver_release_tids, | 1301 | drv_release_buffered_frames(local, sta, driver_release_tids, |
1274 | 1, IEEE80211_FRAME_RELEASE_PSPOLL, | 1302 | n_frames, reason, more_data); |
1275 | more_data); | ||
1276 | 1303 | ||
1277 | /* | 1304 | /* |
1278 | * Note that we don't recalculate the TIM bit here as it would | 1305 | * Note that we don't recalculate the TIM bit here as it would |
@@ -1285,6 +1312,59 @@ void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | |||
1285 | } | 1312 | } |
1286 | } | 1313 | } |
1287 | 1314 | ||
1315 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta) | ||
1316 | { | ||
1317 | u8 ignore_for_response = sta->sta.uapsd_queues; | ||
1318 | |||
1319 | /* | ||
1320 | * If all ACs are delivery-enabled then we should reply | ||
1321 | * from any of them, if only some are enabled we reply | ||
1322 | * only from the non-enabled ones. | ||
1323 | */ | ||
1324 | if (ignore_for_response == BIT(IEEE80211_NUM_ACS) - 1) | ||
1325 | ignore_for_response = 0; | ||
1326 | |||
1327 | ieee80211_sta_ps_deliver_response(sta, 1, ignore_for_response, | ||
1328 | IEEE80211_FRAME_RELEASE_PSPOLL); | ||
1329 | } | ||
1330 | |||
1331 | void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta) | ||
1332 | { | ||
1333 | int n_frames = sta->sta.max_sp; | ||
1334 | u8 delivery_enabled = sta->sta.uapsd_queues; | ||
1335 | |||
1336 | /* | ||
1337 | * If we ever grow support for TSPEC this might happen if | ||
1338 | * the TSPEC update from hostapd comes in between a trigger | ||
1339 | * frame setting WLAN_STA_UAPSD in the RX path and this | ||
1340 | * actually getting called. | ||
1341 | */ | ||
1342 | if (!delivery_enabled) | ||
1343 | return; | ||
1344 | |||
1345 | /* Ohh, finally, the service period starts :-) */ | ||
1346 | set_sta_flags(sta, WLAN_STA_SP); | ||
1347 | |||
1348 | switch (sta->sta.max_sp) { | ||
1349 | case 1: | ||
1350 | n_frames = 2; | ||
1351 | break; | ||
1352 | case 2: | ||
1353 | n_frames = 4; | ||
1354 | break; | ||
1355 | case 3: | ||
1356 | n_frames = 6; | ||
1357 | break; | ||
1358 | case 0: | ||
1359 | /* XXX: what is a good value? */ | ||
1360 | n_frames = 8; | ||
1361 | break; | ||
1362 | } | ||
1363 | |||
1364 | ieee80211_sta_ps_deliver_response(sta, n_frames, ~delivery_enabled, | ||
1365 | IEEE80211_FRAME_RELEASE_UAPSD); | ||
1366 | } | ||
1367 | |||
1288 | void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | 1368 | void ieee80211_sta_block_awake(struct ieee80211_hw *hw, |
1289 | struct ieee80211_sta *pubsta, bool block) | 1369 | struct ieee80211_sta *pubsta, bool block) |
1290 | { | 1370 | { |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 8589afad3295..751ad25f925f 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -46,6 +46,11 @@ | |||
46 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. | 46 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. |
47 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct | 47 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct |
48 | * packets. This means the link is enabled. | 48 | * packets. This means the link is enabled. |
49 | * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was | ||
50 | * keeping station in power-save mode, reply when the driver | ||
51 | * unblocks the station. | ||
52 | * @WLAN_STA_SP: Station is in a service period, so don't try to | ||
53 | * reply to other uAPSD trigger frames. | ||
49 | */ | 54 | */ |
50 | enum ieee80211_sta_info_flags { | 55 | enum ieee80211_sta_info_flags { |
51 | WLAN_STA_AUTH = 1<<0, | 56 | WLAN_STA_AUTH = 1<<0, |
@@ -63,6 +68,8 @@ enum ieee80211_sta_info_flags { | |||
63 | WLAN_STA_PSPOLL = 1<<13, | 68 | WLAN_STA_PSPOLL = 1<<13, |
64 | WLAN_STA_TDLS_PEER = 1<<15, | 69 | WLAN_STA_TDLS_PEER = 1<<15, |
65 | WLAN_STA_TDLS_PEER_AUTH = 1<<16, | 70 | WLAN_STA_TDLS_PEER_AUTH = 1<<16, |
71 | WLAN_STA_UAPSD = 1<<17, | ||
72 | WLAN_STA_SP = 1<<18, | ||
66 | }; | 73 | }; |
67 | 74 | ||
68 | #define STA_TID_NUM 16 | 75 | #define STA_TID_NUM 16 |
@@ -539,5 +546,6 @@ void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | |||
539 | 546 | ||
540 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); | 547 | void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta); |
541 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); | 548 | void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta); |
549 | void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta); | ||
542 | 550 | ||
543 | #endif /* STA_INFO_H */ | 551 | #endif /* STA_INFO_H */ |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 94475eb51d28..b5df9be4d043 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -76,8 +76,16 @@ static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | |||
76 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 76 | hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
77 | 77 | ||
78 | if (ieee80211_is_data_qos(hdr->frame_control)) { | 78 | if (ieee80211_is_data_qos(hdr->frame_control)) { |
79 | int tid = *ieee80211_get_qos_ctl(hdr) & | 79 | u8 *p = ieee80211_get_qos_ctl(hdr); |
80 | IEEE80211_QOS_CTL_TID_MASK; | 80 | int tid = *p & IEEE80211_QOS_CTL_TID_MASK; |
81 | |||
82 | /* | ||
83 | * Clear EOSP if set, this could happen e.g. | ||
84 | * if an absence period (us being a P2P GO) | ||
85 | * shortens the SP. | ||
86 | */ | ||
87 | if (*p & IEEE80211_QOS_CTL_EOSP) | ||
88 | *p &= ~IEEE80211_QOS_CTL_EOSP; | ||
81 | ac = ieee802_1d_to_ac[tid & 7]; | 89 | ac = ieee802_1d_to_ac[tid & 7]; |
82 | } else { | 90 | } else { |
83 | ac = IEEE80211_AC_BE; | 91 | ac = IEEE80211_AC_BE; |
@@ -276,6 +284,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
276 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) | 284 | if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN)) |
277 | continue; | 285 | continue; |
278 | 286 | ||
287 | if (info->flags & IEEE80211_TX_STATUS_EOSP) | ||
288 | clear_sta_flags(sta, WLAN_STA_SP); | ||
289 | |||
279 | acked = !!(info->flags & IEEE80211_TX_STAT_ACK); | 290 | acked = !!(info->flags & IEEE80211_TX_STAT_ACK); |
280 | if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) { | 291 | if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) { |
281 | /* | 292 | /* |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index a1029449df44..a0676d39fe8f 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -456,7 +456,7 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
456 | staflags = get_sta_flags(sta); | 456 | staflags = get_sta_flags(sta); |
457 | 457 | ||
458 | if (unlikely((staflags & (WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) && | 458 | if (unlikely((staflags & (WLAN_STA_PS_STA | WLAN_STA_PS_DRIVER)) && |
459 | !(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE))) { | 459 | !(info->flags & IEEE80211_TX_CTL_POLL_RESPONSE))) { |
460 | int ac = skb_get_queue_mapping(tx->skb); | 460 | int ac = skb_get_queue_mapping(tx->skb); |
461 | 461 | ||
462 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 462 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
@@ -497,9 +497,9 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
497 | } | 497 | } |
498 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG | 498 | #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG |
499 | else if (unlikely(staflags & WLAN_STA_PS_STA)) { | 499 | else if (unlikely(staflags & WLAN_STA_PS_STA)) { |
500 | printk(KERN_DEBUG "%s: STA %pM in PS mode, but pspoll " | 500 | printk(KERN_DEBUG |
501 | "set -> send frame\n", tx->sdata->name, | 501 | "%s: STA %pM in PS mode, but polling/in SP -> send frame\n", |
502 | sta->sta.addr); | 502 | tx->sdata->name, sta->sta.addr); |
503 | } | 503 | } |
504 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ | 504 | #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */ |
505 | 505 | ||