forked from mirrors/linux
		
	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>
This commit is contained in:
		
							parent
							
								
									0ff57171d6
								
							
						
					
					
						commit
						c850e31f79
					
				
					 2 changed files with 78 additions and 19 deletions
				
			
		| 
						 | 
					@ -89,15 +89,13 @@
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * DOC: mac80211 software tx queueing
 | 
					 * DOC: mac80211 software tx queueing
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * mac80211 provides an optional intermediate queueing implementation designed
 | 
					 * mac80211 uses an intermediate queueing implementation, designed to allow the
 | 
				
			||||||
 * to allow the driver to keep hardware queues short and provide some fairness
 | 
					 * driver to keep hardware queues short and to provide some fairness between
 | 
				
			||||||
 * between different stations/interfaces.
 | 
					 * 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().
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Drivers indicate that they use this model by implementing the .wake_tx_queue
 | 
					 * Drivers must provide the .wake_tx_queue driver operation by either
 | 
				
			||||||
 * driver operation.
 | 
					 * 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
 | 
					 * 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
 | 
					 * 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
 | 
					 * The driver is expected to initialize its private per-queue data for stations
 | 
				
			||||||
 * and interfaces in the .add_interface and .sta_add ops.
 | 
					 * and interfaces in the .add_interface and .sta_add ops.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * The driver can't access the queue directly. To dequeue a frame from a
 | 
					 * The driver can't access the internal TX queues (iTXQs) directly.
 | 
				
			||||||
 * txq, it calls ieee80211_tx_dequeue(). Whenever mac80211 adds a new frame to a
 | 
					 * Whenever mac80211 adds a new frame to a queue, it calls the .wake_tx_queue
 | 
				
			||||||
 * queue, it calls the .wake_tx_queue driver op.
 | 
					 * 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
 | 
					 * Drivers can optionally delegate responsibility for scheduling queues to
 | 
				
			||||||
 * mac80211, to take advantage of airtime fairness accounting. In this case, to
 | 
					 * mac80211, to take advantage of airtime fairness accounting. In this case, to
 | 
				
			||||||
| 
						 | 
					@ -1826,7 +1827,7 @@ struct ieee80211_vif_cfg {
 | 
				
			||||||
 *	for this interface.
 | 
					 *	for this interface.
 | 
				
			||||||
 * @drv_priv: data area for driver use, will always be aligned to
 | 
					 * @drv_priv: data area for driver use, will always be aligned to
 | 
				
			||||||
 *	sizeof(void \*).
 | 
					 *	sizeof(void \*).
 | 
				
			||||||
 * @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
 | 
					 * @txq: the multicast data TX queue
 | 
				
			||||||
 * @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped,
 | 
					 * @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped,
 | 
				
			||||||
 *	protected by fq->lock.
 | 
					 *	protected by fq->lock.
 | 
				
			||||||
 * @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
 | 
					 * @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
 | 
				
			||||||
| 
						 | 
					@ -2259,8 +2260,8 @@ struct ieee80211_link_sta {
 | 
				
			||||||
 *	For non MLO STA it will point to the deflink data. For MLO 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.
 | 
					 *	ieee80211_sta_recalc_aggregates() must be called to update it.
 | 
				
			||||||
 * @support_p2p_ps: indicates whether the STA supports P2P PS mechanism or not.
 | 
					 * @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
 | 
					 * @txq: per-TID data TX queues; note that the last entry (%IEEE80211_NUM_TIDS)
 | 
				
			||||||
 *	the last entry (%IEEE80211_NUM_TIDS) is used for non-data frames
 | 
					 *	is used for non-data frames
 | 
				
			||||||
 * @deflink: This holds the default link STA information, for non MLO STA all link
 | 
					 * @deflink: This holds the default link STA information, for non MLO STA all link
 | 
				
			||||||
 *	specific STA information is accessed through @deflink or through
 | 
					 *	specific STA information is accessed through @deflink or through
 | 
				
			||||||
 *	link[0] which points to address of @deflink. For MLO Link STA
 | 
					 *	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);
 | 
				
			||||||
 * @hw: pointer as obtained from ieee80211_alloc_hw().
 | 
					 * @hw: pointer as obtained from ieee80211_alloc_hw().
 | 
				
			||||||
 * @queue: queue number (counted from zero).
 | 
					 * @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);
 | 
					void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5722,7 +5723,7 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue);
 | 
				
			||||||
 * @hw: pointer as obtained from ieee80211_alloc_hw().
 | 
					 * @hw: pointer as obtained from ieee80211_alloc_hw().
 | 
				
			||||||
 * @queue: queue number (counted from zero).
 | 
					 * @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);
 | 
					void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5731,7 +5732,7 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue);
 | 
				
			||||||
 * @hw: pointer as obtained from ieee80211_alloc_hw().
 | 
					 * @hw: pointer as obtained from ieee80211_alloc_hw().
 | 
				
			||||||
 * @queue: queue number (counted from zero).
 | 
					 * @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.
 | 
					 * Return: %true if the queue is stopped. %false otherwise.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -5742,7 +5743,7 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue);
 | 
				
			||||||
 * ieee80211_stop_queues - stop all queues
 | 
					 * ieee80211_stop_queues - stop all queues
 | 
				
			||||||
 * @hw: pointer as obtained from ieee80211_alloc_hw().
 | 
					 * @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);
 | 
					void ieee80211_stop_queues(struct ieee80211_hw *hw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5750,7 +5751,7 @@ void ieee80211_stop_queues(struct ieee80211_hw *hw);
 | 
				
			||||||
 * ieee80211_wake_queues - wake all queues
 | 
					 * ieee80211_wake_queues - wake all queues
 | 
				
			||||||
 * @hw: pointer as obtained from ieee80211_alloc_hw().
 | 
					 * @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);
 | 
					void ieee80211_wake_queues(struct ieee80211_hw *hw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6971,6 +6972,18 @@ static inline struct sk_buff *ieee80211_tx_dequeue_ni(struct ieee80211_hw *hw,
 | 
				
			||||||
	return skb;
 | 
						return skb;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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
 | 
					 * ieee80211_next_txq - get next tx queue to pull packets from
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -288,6 +288,52 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(ieee80211_ctstoself_duration);
 | 
					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)
 | 
					static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ieee80211_local *local = sdata->local;
 | 
						struct ieee80211_local *local = sdata->local;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue