aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2018-08-31 11:31:08 +0300
committerJohannes Berg <johannes.berg@intel.com>2018-09-05 10:03:13 +0200
commitadf8ed01e4fdd254efead978d633718ab01a7d5c (patch)
tree52d3daf8a8b99db1d72cbe0fcf1efb8e4c770c8b /net/mac80211/tx.c
parentmac80211: use le16_encode_bits() instead of open-coding (diff)
downloadlinux-dev-adf8ed01e4fdd254efead978d633718ab01a7d5c.tar.xz
linux-dev-adf8ed01e4fdd254efead978d633718ab01a7d5c.zip
mac80211: add an optional TXQ for other PS-buffered frames
Some drivers may want to also use the TXQ abstraction with non-data packets that need powersave buffering, so add a hardware flag to allow this. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to '')
-rw-r--r--net/mac80211/tx.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 58502d29be54..5083905486c7 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1249,10 +1249,17 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
return NULL;
- if (!ieee80211_is_data_present(hdr->frame_control))
- return NULL;
-
- if (sta) {
+ if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
+ if ((!ieee80211_is_mgmt(hdr->frame_control) ||
+ ieee80211_is_bufferable_mmpdu(hdr->frame_control)) &&
+ sta && sta->uploaded) {
+ /*
+ * This will be NULL if the driver didn't set the
+ * opt-in hardware flag.
+ */
+ txq = sta->sta.txq[IEEE80211_NUM_TIDS];
+ }
+ } else if (sta) {
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
if (!sta->uploaded)
@@ -1440,16 +1447,26 @@ void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
txqi->txq.vif = &sdata->vif;
- if (sta) {
- txqi->txq.sta = &sta->sta;
- sta->sta.txq[tid] = &txqi->txq;
- txqi->txq.tid = tid;
- txqi->txq.ac = ieee80211_ac_from_tid(tid);
- } else {
+ if (!sta) {
sdata->vif.txq = &txqi->txq;
txqi->txq.tid = 0;
txqi->txq.ac = IEEE80211_AC_BE;
+
+ return;
+ }
+
+ if (tid == IEEE80211_NUM_TIDS) {
+ /* Drivers need to opt in to the bufferable MMPDU TXQ */
+ if (!ieee80211_hw_check(&sdata->local->hw, BUFF_MMPDU_TXQ))
+ return;
+ txqi->txq.ac = IEEE80211_AC_VO;
+ } else {
+ txqi->txq.ac = ieee80211_ac_from_tid(tid);
}
+
+ txqi->txq.sta = &sta->sta;
+ txqi->txq.tid = tid;
+ sta->sta.txq[tid] = &txqi->txq;
}
void ieee80211_txq_purge(struct ieee80211_local *local,