d14ba05e695c8ff4d464afea7ca190fad9025159
[librecmc/librecmc.git] /
1 From: Alexander Wetzel <alexander@wetzel-home.de>
2 Date: Sun, 9 Oct 2022 18:30:38 +0200
3 Subject: [PATCH] wifi: mac80211: add internal handler for wake_tx_queue
4
5 Start to align the TX handling to only use internal TX queues (iTXQs):
6
7 Provide a handler for drivers not having a custom wake_tx_queue
8 callback and update the documentation.
9
10 Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
11 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
12 ---
13
14 --- a/include/net/mac80211.h
15 +++ b/include/net/mac80211.h
16 @@ -89,15 +89,13 @@
17  /**
18   * DOC: mac80211 software tx queueing
19   *
20 - * mac80211 provides an optional intermediate queueing implementation designed
21 - * to allow the driver to keep hardware queues short and provide some fairness
22 - * between different stations/interfaces.
23 - * In this model, the driver pulls data frames from the mac80211 queue instead
24 - * of letting mac80211 push them via drv_tx().
25 - * Other frames (e.g. control or management) are still pushed using drv_tx().
26 + * mac80211 uses an intermediate queueing implementation, designed to allow the
27 + * driver to keep hardware queues short and to provide some fairness between
28 + * different stations/interfaces.
29   *
30 - * Drivers indicate that they use this model by implementing the .wake_tx_queue
31 - * driver operation.
32 + * Drivers must provide the .wake_tx_queue driver operation by either
33 + * linking it to ieee80211_handle_wake_tx_queue() or implementing a custom
34 + * handler.
35   *
36   * Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with
37   * another per-sta for non-data/non-mgmt and bufferable management frames, and
38 @@ -106,9 +104,12 @@
39   * The driver is expected to initialize its private per-queue data for stations
40   * and interfaces in the .add_interface and .sta_add ops.
41   *
42 - * The driver can't access the queue directly. To dequeue a frame from a
43 - * txq, it calls ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a
44 - * queue, it calls the .wake_tx_queue driver op.
45 + * The driver can't access the internal TX queues (iTXQs) directly.
46 + * Whenever mac80211 adds a new frame to a queue, it calls the .wake_tx_queue
47 + * driver op.
48 + * Drivers implementing a custom .wake_tx_queue op can get them by calling
49 + * ieee80211_tx_dequeue(). Drivers using ieee80211_handle_wake_tx_queue() will
50 + * simply get the individual frames pushed via the .tx driver operation.
51   *
52   * Drivers can optionally delegate responsibility for scheduling queues to
53   * mac80211, to take advantage of airtime fairness accounting. In this case, to
54 @@ -2248,8 +2249,8 @@ struct ieee80211_link_sta {
55   *     For non MLO STA it will point to the deflink data. For MLO STA
56   *     ieee80211_sta_recalc_aggregates() must be called to update it.
57   * @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not.
58 - * @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that
59 - *     the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
60 + * @txq: per-TID data TX queues; note that the last entry (%IEEE80211_NUM_TIDS)
61 + *     is used for non-data frames
62   * @deflink: This holds the default link STA information, for non MLO STA all link
63   *     specific STA information is accessed through @deflink or through
64   *     link[0] which points to address of @deflink. For MLO Link STA
65 @@ -5687,7 +5688,7 @@ void ieee80211_key_replay(struct ieee802
66   * @hw: pointer as obtained from ieee80211_alloc_hw().
67   * @queue: queue number (counted from zero).
68   *
69 - * Drivers should use this function instead of netif_wake_queue.
70 + * Drivers must use this function instead of netif_wake_queue.
71   */
72  void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
73  
74 @@ -5696,7 +5697,7 @@ void ieee80211_wake_queue(struct ieee802
75   * @hw: pointer as obtained from ieee80211_alloc_hw().
76   * @queue: queue number (counted from zero).
77   *
78 - * Drivers should use this function instead of netif_stop_queue.
79 + * Drivers must use this function instead of netif_stop_queue.
80   */
81  void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
82  
83 @@ -5705,7 +5706,7 @@ void ieee80211_stop_queue(struct ieee802
84   * @hw: pointer as obtained from ieee80211_alloc_hw().
85   * @queue: queue number (counted from zero).
86   *
87 - * Drivers should use this function instead of netif_stop_queue.
88 + * Drivers must use this function instead of netif_queue_stopped.
89   *
90   * Return: %true if the queue is stopped. %false otherwise.
91   */
92 @@ -5716,7 +5717,7 @@ int ieee80211_queue_stopped(struct ieee8
93   * ieee80211_stop_queues - stop all queues
94   * @hw: pointer as obtained from ieee80211_alloc_hw().
95   *
96 - * Drivers should use this function instead of netif_stop_queue.
97 + * Drivers must use this function instead of netif_tx_stop_all_queues.
98   */
99  void ieee80211_stop_queues(struct ieee80211_hw *hw);
100  
101 @@ -5724,7 +5725,7 @@ void ieee80211_stop_queues(struct ieee80
102   * ieee80211_wake_queues - wake all queues
103   * @hw: pointer as obtained from ieee80211_alloc_hw().
104   *
105 - * Drivers should use this function instead of netif_wake_queue.
106 + * Drivers must use this function instead of netif_tx_wake_all_queues.
107   */
108  void ieee80211_wake_queues(struct ieee80211_hw *hw);
109  
110 @@ -6946,6 +6947,18 @@ static inline struct sk_buff *ieee80211_
111  }
112  
113  /**
114 + * ieee80211_handle_wake_tx_queue - mac80211 handler for wake_tx_queue callback
115 + *
116 + * @hw: pointer as obtained from wake_tx_queue() callback().
117 + * @txq: pointer as obtained from wake_tx_queue() callback().
118 + *
119 + * Drivers can use this function for the mandatory mac80211 wake_tx_queue
120 + * callback in struct ieee80211_ops. They should not call this function.
121 + */
122 +void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
123 +                                   struct ieee80211_txq *txq);
124 +
125 +/**
126   * ieee80211_next_txq - get next tx queue to pull packets from
127   *
128   * @hw: pointer as obtained from ieee80211_alloc_hw()
129 --- a/net/mac80211/util.c
130 +++ b/net/mac80211/util.c
131 @@ -288,6 +288,52 @@ __le16 ieee80211_ctstoself_duration(stru
132  }
133  EXPORT_SYMBOL(ieee80211_ctstoself_duration);
134  
135 +static void wake_tx_push_queue(struct ieee80211_local *local,
136 +                              struct ieee80211_sub_if_data *sdata,
137 +                              struct ieee80211_txq *queue)
138 +{
139 +       int q = sdata->vif.hw_queue[queue->ac];
140 +       struct ieee80211_tx_control control = {
141 +               .sta = queue->sta,
142 +       };
143 +       struct sk_buff *skb;
144 +       unsigned long flags;
145 +       bool q_stopped;
146 +
147 +       while (1) {
148 +               spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
149 +               q_stopped = local->queue_stop_reasons[q];
150 +               spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
151 +
152 +               if (q_stopped)
153 +                       break;
154 +
155 +               skb = ieee80211_tx_dequeue(&local->hw, queue);
156 +               if (!skb)
157 +                       break;
158 +
159 +               drv_tx(local, &control, skb);
160 +       }
161 +}
162 +
163 +/* wake_tx_queue handler for driver not implementing a custom one*/
164 +void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
165 +                                   struct ieee80211_txq *txq)
166 +{
167 +       struct ieee80211_local *local = hw_to_local(hw);
168 +       struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
169 +       struct ieee80211_txq *queue;
170 +
171 +       /* Use ieee80211_next_txq() for airtime fairness accounting */
172 +       ieee80211_txq_schedule_start(hw, txq->ac);
173 +       while ((queue = ieee80211_next_txq(hw, txq->ac))) {
174 +               wake_tx_push_queue(local, sdata, queue);
175 +               ieee80211_return_txq(hw, queue, false);
176 +       }
177 +       ieee80211_txq_schedule_end(hw, txq->ac);
178 +}
179 +EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue);
180 +
181  static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
182  {
183         struct ieee80211_local *local = sdata->local;