306-01-v6.2-wifi-mac80211-add-internal-handler-for-wake_tx_queue.patch 7.3 KB

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