Skip to content

Commit adf8ed0

Browse files
committed
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 <[email protected]>
1 parent 331aead commit adf8ed0

File tree

6 files changed

+59
-26
lines changed

6 files changed

+59
-26
lines changed

include/net/mac80211.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,9 @@
101101
* Drivers indicate that they use this model by implementing the .wake_tx_queue
102102
* driver operation.
103103
*
104-
* Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with a
105-
* single per-vif queue for multicast data frames.
104+
* Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with
105+
* another per-sta for non-data/non-mgmt and bufferable management frames, and
106+
* a single per-vif queue for multicast data frames.
106107
*
107108
* The driver is expected to initialize its private per-queue data for stations
108109
* and interfaces in the .add_interface and .sta_add ops.
@@ -1843,7 +1844,8 @@ struct ieee80211_sta_rates {
18431844
* unlimited.
18441845
* @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not.
18451846
* @max_rc_amsdu_len: Maximum A-MSDU size in bytes recommended by rate control.
1846-
* @txq: per-TID data TX queues (if driver uses the TXQ abstraction)
1847+
* @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that
1848+
* the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
18471849
*/
18481850
struct ieee80211_sta {
18491851
u32 supp_rates[NUM_NL80211_BANDS];
@@ -1884,7 +1886,7 @@ struct ieee80211_sta {
18841886
bool support_p2p_ps;
18851887
u16 max_rc_amsdu_len;
18861888

1887-
struct ieee80211_txq *txq[IEEE80211_NUM_TIDS];
1889+
struct ieee80211_txq *txq[IEEE80211_NUM_TIDS + 1];
18881890

18891891
/* must be last */
18901892
u8 drv_priv[0] __aligned(sizeof(void *));
@@ -1918,7 +1920,8 @@ struct ieee80211_tx_control {
19181920
*
19191921
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
19201922
* @sta: station table entry, %NULL for per-vif queue
1921-
* @tid: the TID for this queue (unused for per-vif queue)
1923+
* @tid: the TID for this queue (unused for per-vif queue),
1924+
* %IEEE80211_NUM_TIDS for non-data (if enabled)
19221925
* @ac: the AC for this queue
19231926
* @drv_priv: driver private area, sized by hw->txq_data_size
19241927
*
@@ -2131,6 +2134,9 @@ struct ieee80211_txq {
21312134
* @IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP: The driver (or firmware) doesn't
21322135
* support QoS NDP for AP probing - that's most likely a driver bug.
21332136
*
2137+
* @IEEE80211_HW_BUFF_MMPDU_TXQ: use the TXQ for bufferable MMPDUs, this of
2138+
* course requires the driver to use TXQs to start with.
2139+
*
21342140
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
21352141
*/
21362142
enum ieee80211_hw_flags {
@@ -2176,6 +2182,7 @@ enum ieee80211_hw_flags {
21762182
IEEE80211_HW_SUPPORTS_TDLS_BUFFER_STA,
21772183
IEEE80211_HW_DEAUTH_NEED_MGD_TX_PREP,
21782184
IEEE80211_HW_DOESNT_SUPPORT_QOS_NDP,
2185+
IEEE80211_HW_BUFF_MMPDU_TXQ,
21792186

21802187
/* keep last, obviously */
21812188
NUM_IEEE80211_HW_FLAGS

net/mac80211/debugfs.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*
44
* Copyright 2007 Johannes Berg <[email protected]>
55
* Copyright 2013-2014 Intel Mobile Communications GmbH
6+
* Copyright (C) 2018 Intel Corporation
67
*
78
* GPLv2
89
*
@@ -214,6 +215,7 @@ static const char *hw_flag_names[] = {
214215
FLAG(SUPPORTS_TDLS_BUFFER_STA),
215216
FLAG(DEAUTH_NEED_MGD_TX_PREP),
216217
FLAG(DOESNT_SUPPORT_QOS_NDP),
218+
FLAG(BUFF_MMPDU_TXQ),
217219
#undef FLAG
218220
};
219221

net/mac80211/debugfs_sta.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
141141
{
142142
struct sta_info *sta = file->private_data;
143143
struct ieee80211_local *local = sta->local;
144-
size_t bufsz = AQM_TXQ_ENTRY_LEN*(IEEE80211_NUM_TIDS+1);
144+
size_t bufsz = AQM_TXQ_ENTRY_LEN * (IEEE80211_NUM_TIDS + 2);
145145
char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
146146
struct txq_info *txqi;
147147
ssize_t rv;
@@ -163,7 +163,9 @@ static ssize_t sta_aqm_read(struct file *file, char __user *userbuf,
163163
bufsz+buf-p,
164164
"tid ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets flags\n");
165165

166-
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
166+
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
167+
if (!sta->sta.txq[i])
168+
continue;
167169
txqi = to_txq_info(sta->sta.txq[i]);
168170
p += scnprintf(p, bufsz+buf-p,
169171
"%d %d %u %u %u %u %u %u %u %u %u 0x%lx(%s%s%s)\n",

net/mac80211/rx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1505,7 +1505,7 @@ static void sta_ps_start(struct sta_info *sta)
15051505
if (!sta->sta.txq[0])
15061506
return;
15071507

1508-
for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
1508+
for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
15091509
if (txq_has_queue(sta->sta.txq[tid]))
15101510
set_bit(tid, &sta->txq_buffered_tids);
15111511
else

net/mac80211/sta_info.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,12 @@ static void __cleanup_single_sta(struct sta_info *sta)
113113

114114
if (sta->sta.txq[0]) {
115115
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
116-
struct txq_info *txqi = to_txq_info(sta->sta.txq[i]);
116+
struct txq_info *txqi;
117+
118+
if (!sta->sta.txq[i])
119+
continue;
120+
121+
txqi = to_txq_info(sta->sta.txq[i]);
117122

118123
spin_lock_bh(&fq->lock);
119124
ieee80211_txq_purge(local, txqi);
@@ -374,6 +379,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
374379
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
375380
struct txq_info *txq = txq_data + i * size;
376381

382+
/* might not do anything for the bufferable MMPDU TXQ */
377383
ieee80211_txq_init(sdata, sta, txq, i);
378384
}
379385
}
@@ -1239,13 +1245,11 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
12391245
if (!ieee80211_hw_check(&local->hw, AP_LINK_PS))
12401246
drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
12411247

1242-
if (sta->sta.txq[0]) {
1243-
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
1244-
if (!txq_has_queue(sta->sta.txq[i]))
1245-
continue;
1248+
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
1249+
if (!sta->sta.txq[i] || !txq_has_queue(sta->sta.txq[i]))
1250+
continue;
12461251

1247-
drv_wake_tx_queue(local, to_txq_info(sta->sta.txq[i]));
1248-
}
1252+
drv_wake_tx_queue(local, to_txq_info(sta->sta.txq[i]));
12491253
}
12501254

12511255
skb_queue_head_init(&pending);
@@ -1683,7 +1687,8 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
16831687
return;
16841688

16851689
for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
1686-
if (!(driver_release_tids & BIT(tid)) ||
1690+
if (!sta->sta.txq[tid] ||
1691+
!(driver_release_tids & BIT(tid)) ||
16871692
txq_has_queue(sta->sta.txq[tid]))
16881693
continue;
16891694

net/mac80211/tx.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,10 +1249,17 @@ static struct txq_info *ieee80211_get_txq(struct ieee80211_local *local,
12491249
(info->control.flags & IEEE80211_TX_CTRL_PS_RESPONSE))
12501250
return NULL;
12511251

1252-
if (!ieee80211_is_data_present(hdr->frame_control))
1253-
return NULL;
1254-
1255-
if (sta) {
1252+
if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) {
1253+
if ((!ieee80211_is_mgmt(hdr->frame_control) ||
1254+
ieee80211_is_bufferable_mmpdu(hdr->frame_control)) &&
1255+
sta && sta->uploaded) {
1256+
/*
1257+
* This will be NULL if the driver didn't set the
1258+
* opt-in hardware flag.
1259+
*/
1260+
txq = sta->sta.txq[IEEE80211_NUM_TIDS];
1261+
}
1262+
} else if (sta) {
12561263
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
12571264

12581265
if (!sta->uploaded)
@@ -1440,16 +1447,26 @@ void ieee80211_txq_init(struct ieee80211_sub_if_data *sdata,
14401447

14411448
txqi->txq.vif = &sdata->vif;
14421449

1443-
if (sta) {
1444-
txqi->txq.sta = &sta->sta;
1445-
sta->sta.txq[tid] = &txqi->txq;
1446-
txqi->txq.tid = tid;
1447-
txqi->txq.ac = ieee80211_ac_from_tid(tid);
1448-
} else {
1450+
if (!sta) {
14491451
sdata->vif.txq = &txqi->txq;
14501452
txqi->txq.tid = 0;
14511453
txqi->txq.ac = IEEE80211_AC_BE;
1454+
1455+
return;
1456+
}
1457+
1458+
if (tid == IEEE80211_NUM_TIDS) {
1459+
/* Drivers need to opt in to the bufferable MMPDU TXQ */
1460+
if (!ieee80211_hw_check(&sdata->local->hw, BUFF_MMPDU_TXQ))
1461+
return;
1462+
txqi->txq.ac = IEEE80211_AC_VO;
1463+
} else {
1464+
txqi->txq.ac = ieee80211_ac_from_tid(tid);
14521465
}
1466+
1467+
txqi->txq.sta = &sta->sta;
1468+
txqi->txq.tid = tid;
1469+
sta->sta.txq[tid] = &txqi->txq;
14531470
}
14541471

14551472
void ieee80211_txq_purge(struct ieee80211_local *local,

0 commit comments

Comments
 (0)