summaryrefslogtreecommitdiff
path: root/net/mac80211/status.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-09-29 16:04:33 +0200
committerJohn W. Linville <linville@tuxdriver.com>2011-09-30 15:57:15 -0400
commit47086fc51aa2220f58049704a8b73e4fcdf372b9 (patch)
tree31f7ae0e59318352d772b62fa26316d349cde88e /net/mac80211/status.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/status.c')
-rw-r--r--net/mac80211/status.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 94475eb51d2..b5df9be4d04 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,
hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_MOREDATA);
if (ieee80211_is_data_qos(hdr->frame_control)) {
- int tid = *ieee80211_get_qos_ctl(hdr) &
- IEEE80211_QOS_CTL_TID_MASK;
+ u8 *p = ieee80211_get_qos_ctl(hdr);
+ int tid = *p & IEEE80211_QOS_CTL_TID_MASK;
+
+ /*
+ * Clear EOSP if set, this could happen e.g.
+ * if an absence period (us being a P2P GO)
+ * shortens the SP.
+ */
+ if (*p & IEEE80211_QOS_CTL_EOSP)
+ *p &= ~IEEE80211_QOS_CTL_EOSP;
ac = ieee802_1d_to_ac[tid & 7];
} else {
ac = IEEE80211_AC_BE;
@@ -276,6 +284,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
if (memcmp(hdr->addr2, sta->sdata->vif.addr, ETH_ALEN))
continue;
+ if (info->flags & IEEE80211_TX_STATUS_EOSP)
+ clear_sta_flags(sta, WLAN_STA_SP);
+
acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
if (!acked && test_sta_flags(sta, WLAN_STA_PS_STA)) {
/*