mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
184 lines
7.3 KiB
Diff
184 lines
7.3 KiB
Diff
From: Alexander Wetzel <alexander@wetzel-home.de>
|
|
Date: Sun, 9 Oct 2022 18:30:38 +0200
|
|
Subject: [PATCH] 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>
|
|
---
|
|
|
|
--- a/include/net/mac80211.h
|
|
+++ b/include/net/mac80211.h
|
|
@@ -89,15 +89,13 @@
|
|
/**
|
|
* DOC: mac80211 software tx queueing
|
|
*
|
|
- * mac80211 provides an optional intermediate queueing implementation designed
|
|
- * to allow the driver to keep hardware queues short and provide some fairness
|
|
- * between different stations/interfaces.
|
|
- * In this model, the driver pulls data frames from the mac80211 queue instead
|
|
- * of letting mac80211 push them via drv_tx().
|
|
- * Other frames (e.g. control or management) are still pushed using drv_tx().
|
|
+ * mac80211 uses an intermediate queueing implementation, designed to allow the
|
|
+ * driver to keep hardware queues short and to provide some fairness between
|
|
+ * different stations/interfaces.
|
|
*
|
|
- * Drivers indicate that they use this model by implementing the .wake_tx_queue
|
|
- * driver operation.
|
|
+ * Drivers must provide the .wake_tx_queue driver operation by either
|
|
+ * linking it to ieee80211_handle_wake_tx_queue() or implementing a custom
|
|
+ * handler.
|
|
*
|
|
* Intermediate queues (struct ieee80211_txq) are kept per-sta per-tid, with
|
|
* another per-sta for non-data/non-mgmt and bufferable management frames, and
|
|
@@ -106,9 +104,12 @@
|
|
* The driver is expected to initialize its private per-queue data for stations
|
|
* and interfaces in the .add_interface and .sta_add ops.
|
|
*
|
|
- * The driver can't access the queue directly. To dequeue a frame from a
|
|
- * txq, it calls ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a
|
|
- * queue, it calls the .wake_tx_queue driver op.
|
|
+ * The driver can't access the internal TX queues (iTXQs) directly.
|
|
+ * Whenever mac80211 adds a new frame to a queue, it calls the .wake_tx_queue
|
|
+ * driver op.
|
|
+ * Drivers implementing a custom .wake_tx_queue op can get them by calling
|
|
+ * ieee80211_tx_dequeue(). Drivers using ieee80211_handle_wake_tx_queue() will
|
|
+ * simply get the individual frames pushed via the .tx driver operation.
|
|
*
|
|
* Drivers can optionally delegate responsibility for scheduling queues to
|
|
* mac80211, to take advantage of airtime fairness accounting. In this case, to
|
|
@@ -2259,8 +2260,8 @@ struct ieee80211_link_sta {
|
|
* For non MLO STA it will point to the deflink data. For MLO STA
|
|
* ieee80211_sta_recalc_aggregates() must be called to update it.
|
|
* @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not.
|
|
- * @txq: per-TID data TX queues (if driver uses the TXQ abstraction); note that
|
|
- * the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
|
|
+ * @txq: per-TID data TX queues; note that the last entry (%IEEE80211_NUM_TIDS)
|
|
+ * is used for non-data frames
|
|
* @deflink: This holds the default link STA information, for non MLO STA all link
|
|
* specific STA information is accessed through @deflink or through
|
|
* link[0] which points to address of @deflink. For MLO Link STA
|
|
@@ -5698,7 +5699,7 @@ void ieee80211_key_replay(struct ieee802
|
|
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
|
* @queue: queue number (counted from zero).
|
|
*
|
|
- * Drivers should use this function instead of netif_wake_queue.
|
|
+ * Drivers must use this function instead of netif_wake_queue.
|
|
*/
|
|
void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
|
|
|
|
@@ -5707,7 +5708,7 @@ void ieee80211_wake_queue(struct ieee802
|
|
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
|
* @queue: queue number (counted from zero).
|
|
*
|
|
- * Drivers should use this function instead of netif_stop_queue.
|
|
+ * Drivers must use this function instead of netif_stop_queue.
|
|
*/
|
|
void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
|
|
|
|
@@ -5716,7 +5717,7 @@ void ieee80211_stop_queue(struct ieee802
|
|
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
|
* @queue: queue number (counted from zero).
|
|
*
|
|
- * Drivers should use this function instead of netif_stop_queue.
|
|
+ * Drivers must use this function instead of netif_queue_stopped.
|
|
*
|
|
* Return: %true if the queue is stopped. %false otherwise.
|
|
*/
|
|
@@ -5727,7 +5728,7 @@ int ieee80211_queue_stopped(struct ieee8
|
|
* ieee80211_stop_queues - stop all queues
|
|
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
|
*
|
|
- * Drivers should use this function instead of netif_stop_queue.
|
|
+ * Drivers must use this function instead of netif_tx_stop_all_queues.
|
|
*/
|
|
void ieee80211_stop_queues(struct ieee80211_hw *hw);
|
|
|
|
@@ -5735,7 +5736,7 @@ void ieee80211_stop_queues(struct ieee80
|
|
* ieee80211_wake_queues - wake all queues
|
|
* @hw: pointer as obtained from ieee80211_alloc_hw().
|
|
*
|
|
- * Drivers should use this function instead of netif_wake_queue.
|
|
+ * Drivers must use this function instead of netif_tx_wake_all_queues.
|
|
*/
|
|
void ieee80211_wake_queues(struct ieee80211_hw *hw);
|
|
|
|
@@ -6957,6 +6958,18 @@ static inline struct sk_buff *ieee80211_
|
|
}
|
|
|
|
/**
|
|
+ * ieee80211_handle_wake_tx_queue - mac80211 handler for wake_tx_queue callback
|
|
+ *
|
|
+ * @hw: pointer as obtained from wake_tx_queue() callback().
|
|
+ * @txq: pointer as obtained from wake_tx_queue() callback().
|
|
+ *
|
|
+ * Drivers can use this function for the mandatory mac80211 wake_tx_queue
|
|
+ * callback in struct ieee80211_ops. They should not call this function.
|
|
+ */
|
|
+void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_txq *txq);
|
|
+
|
|
+/**
|
|
* ieee80211_next_txq - get next tx queue to pull packets from
|
|
*
|
|
* @hw: pointer as obtained from ieee80211_alloc_hw()
|
|
--- a/net/mac80211/util.c
|
|
+++ b/net/mac80211/util.c
|
|
@@ -288,6 +288,52 @@ __le16 ieee80211_ctstoself_duration(stru
|
|
}
|
|
EXPORT_SYMBOL(ieee80211_ctstoself_duration);
|
|
|
|
+static void wake_tx_push_queue(struct ieee80211_local *local,
|
|
+ struct ieee80211_sub_if_data *sdata,
|
|
+ struct ieee80211_txq *queue)
|
|
+{
|
|
+ int q = sdata->vif.hw_queue[queue->ac];
|
|
+ struct ieee80211_tx_control control = {
|
|
+ .sta = queue->sta,
|
|
+ };
|
|
+ struct sk_buff *skb;
|
|
+ unsigned long flags;
|
|
+ bool q_stopped;
|
|
+
|
|
+ while (1) {
|
|
+ spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
|
|
+ q_stopped = local->queue_stop_reasons[q];
|
|
+ spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
|
+
|
|
+ if (q_stopped)
|
|
+ break;
|
|
+
|
|
+ skb = ieee80211_tx_dequeue(&local->hw, queue);
|
|
+ if (!skb)
|
|
+ break;
|
|
+
|
|
+ drv_tx(local, &control, skb);
|
|
+ }
|
|
+}
|
|
+
|
|
+/* wake_tx_queue handler for driver not implementing a custom one*/
|
|
+void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_txq *txq)
|
|
+{
|
|
+ struct ieee80211_local *local = hw_to_local(hw);
|
|
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif);
|
|
+ struct ieee80211_txq *queue;
|
|
+
|
|
+ /* Use ieee80211_next_txq() for airtime fairness accounting */
|
|
+ ieee80211_txq_schedule_start(hw, txq->ac);
|
|
+ while ((queue = ieee80211_next_txq(hw, txq->ac))) {
|
|
+ wake_tx_push_queue(local, sdata, queue);
|
|
+ ieee80211_return_txq(hw, queue, false);
|
|
+ }
|
|
+ ieee80211_txq_schedule_end(hw, txq->ac);
|
|
+}
|
|
+EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue);
|
|
+
|
|
static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
|
|
{
|
|
struct ieee80211_local *local = sdata->local;
|