Skip to content

Commit c850e31

Browse files
alexw65500jmberg-intel
authored andcommitted
wifi: mac80211: add internal handler for wake_tx_queue
Start to align the TX handling to only use internal TX queues (iTXQs): Provide a handler for drivers not having a custom wake_tx_queue callback and update the documentation. Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1 parent 0ff5717 commit c850e31

File tree

2 files changed

+78
-19
lines changed

2 files changed

+78
-19
lines changed

include/net/mac80211.h

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,13 @@
8989
/**
9090
* DOC: mac80211 software tx queueing
9191
*
92-
* mac80211 provides an optional intermediate queueing implementation designed
93-
* to allow the driver to keep hardware queues short and provide some fairness
94-
* between different stations/interfaces.
95-
* In this model, the driver pulls data frames from the mac80211 queue instead
96-
* of letting mac80211 push them via drv_tx().
97-
* Other frames (e.g. control or management) are still pushed using drv_tx().
92+
* mac80211 uses an intermediate queueing implementation, designed to allow the
93+
* driver to keep hardware queues short and to provide some fairness between
94+
* different stations/interfaces.
9895
*
99-
* Drivers indicate that they use this model by implementing the .wake_tx_queue
100-
* driver operation.
96+
* Drivers must provide the .wake_tx_queue driver operation by either
97+
* linking it to ieee80211_handle_wake_tx_queue() or implementing a custom
98+
* handler.
10199
*
102100
* Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with
103101
* another per-sta for non-data/non-mgmt and bufferable management frames, and
@@ -106,9 +104,12 @@
106104
* The driver is expected to initialize its private per-queue data for stations
107105
* and interfaces in the .add_interface and .sta_add ops.
108106
*
109-
* The driver can't access the queue directly. To dequeue a frame from a
110-
* txq, it calls ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a
111-
* queue, it calls the .wake_tx_queue driver op.
107+
* The driver can't access the internal TX queues (iTXQs) directly.
108+
* Whenever mac80211 adds a new frame to a queue, it calls the .wake_tx_queue
109+
* driver op.
110+
* Drivers implementing a custom .wake_tx_queue op can get them by calling
111+
* ieee80211_tx_dequeue(). Drivers using ieee80211_handle_wake_tx_queue() will
112+
* simply get the individual frames pushed via the .tx driver operation.
112113
*
113114
* Drivers can optionally delegate responsibility for scheduling queues to
114115
* mac80211, to take advantage of airtime fairness accounting. In this case, to
@@ -1826,7 +1827,7 @@ struct ieee80211_vif_cfg {
18261827
* for this interface.
18271828
* @drv_priv: data area for driver use, will always be aligned to
18281829
* sizeof(void \*).
1829-
* @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
1830+
* @txq: the multicast data TX queue
18301831
* @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped,
18311832
* protected by fq->lock.
18321833
* @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
@@ -2259,8 +2260,8 @@ struct ieee80211_link_sta {
22592260
* For non MLO STA it will point to the deflink data. For MLO STA
22602261
* ieee80211_sta_recalc_aggregates() must be called to update it.
22612262
* @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not.
2262-
* @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that
2263-
* the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
2263+
* @txq: per-TID data TX queues; note that the last entry (%IEEE80211_NUM_TIDS)
2264+
* is used for non-data frames
22642265
* @deflink: This holds the default link STA information, for non MLO STA all link
22652266
* specific STA information is accessed through @deflink or through
22662267
* link[0] which points to address of @deflink. For MLO Link STA
@@ -5713,7 +5714,7 @@ void ieee80211_key_replay(struct ieee80211_key_conf *keyconf);
57135714
* @hw: pointer as obtained from ieee80211_alloc_hw().
57145715
* @queue: queue number (counted from zero).
57155716
*
5716-
* Drivers should use this function instead of netif_wake_queue.
5717+
* Drivers must use this function instead of netif_wake_queue.
57175718
*/
57185719
void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
57195720

@@ -5722,7 +5723,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
57225723
* @hw: pointer as obtained from ieee80211_alloc_hw().
57235724
* @queue: queue number (counted from zero).
57245725
*
5725-
* Drivers should use this function instead of netif_stop_queue.
5726+
* Drivers must use this function instead of netif_stop_queue.
57265727
*/
57275728
void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
57285729

@@ -5731,7 +5732,7 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
57315732
* @hw: pointer as obtained from ieee80211_alloc_hw().
57325733
* @queue: queue number (counted from zero).
57335734
*
5734-
* Drivers should use this function instead of netif_stop_queue.
5735+
* Drivers must use this function instead of netif_queue_stopped.
57355736
*
57365737
* Return: %true if the queue is stopped. %false otherwise.
57375738
*/
@@ -5742,15 +5743,15 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue);
57425743
* ieee80211_stop_queues - stop all queues
57435744
* @hw: pointer as obtained from ieee80211_alloc_hw().
57445745
*
5745-
* Drivers should use this function instead of netif_stop_queue.
5746+
* Drivers must use this function instead of netif_tx_stop_all_queues.
57465747
*/
57475748
void ieee80211_stop_queues(struct ieee80211_hw *hw);
57485749

57495750
/**
57505751
* ieee80211_wake_queues - wake all queues
57515752
* @hw: pointer as obtained from ieee80211_alloc_hw().
57525753
*
5753-
* Drivers should use this function instead of netif_wake_queue.
5754+
* Drivers must use this function instead of netif_tx_wake_all_queues.
57545755
*/
57555756
void ieee80211_wake_queues(struct ieee80211_hw *hw);
57565757

@@ -6971,6 +6972,18 @@ static inline struct sk_buff *ieee80211_tx_dequeue_ni(struct ieee80211_hw *hw,
69716972
return skb;
69726973
}
69736974

6975+
/**
6976+
* ieee80211_handle_wake_tx_queue - mac80211 handler for wake_tx_queue callback
6977+
*
6978+
* @hw: pointer as obtained from wake_tx_queue() callback().
6979+
* @txq: pointer as obtained from wake_tx_queue() callback().
6980+
*
6981+
* Drivers can use this function for the mandatory mac80211 wake_tx_queue
6982+
* callback in struct ieee80211_ops. They should not call this function.
6983+
*/
6984+
void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
6985+
struct ieee80211_txq *txq);
6986+
69746987
/**
69756988
* ieee80211_next_txq - get next tx queue to pull packets from
69766989
*

net/mac80211/util.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,52 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
288288
}
289289
EXPORT_SYMBOL(ieee80211_ctstoself_duration);
290290

291+
static void wake_tx_push_queue(struct ieee80211_local *local,
292+
struct ieee80211_sub_if_data *sdata,
293+
struct ieee80211_txq *queue)
294+
{
295+
int q = sdata->vif.hw_queue[queue->ac];
296+
struct ieee80211_tx_control control = {
297+
.sta = queue->sta,
298+
};
299+
struct sk_buff *skb;
300+
unsigned long flags;
301+
bool q_stopped;
302+
303+
while (1) {
304+
spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
305+
q_stopped = local->queue_stop_reasons[q];
306+
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
307+
308+
if (q_stopped)
309+
break;
310+
311+
skb = ieee80211_tx_dequeue(&local->hw, queue);
312+
if (!skb)
313+
break;
314+
315+
drv_tx(local, &control, skb);
316+
}
317+
}
318+
319+
/* wake_tx_queue handler for driver not implementing a custom one*/
320+
void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
321+
struct ieee80211_txq *txq)
322+
{
323+
struct ieee80211_local *local = hw_to_local(hw);
324+
struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
325+
struct ieee80211_txq *queue;
326+
327+
/* Use ieee80211_next_txq() for airtime fairness accounting */
328+
ieee80211_txq_schedule_start(hw, txq->ac);
329+
while ((queue = ieee80211_next_txq(hw, txq->ac))) {
330+
wake_tx_push_queue(local, sdata, queue);
331+
ieee80211_return_txq(hw, queue, false);
332+
}
333+
ieee80211_txq_schedule_end(hw, txq->ac);
334+
}
335+
EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue);
336+
291337
static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
292338
{
293339
struct ieee80211_local *local = sdata->local;

0 commit comments

Comments
 (0)