Search Linux Wireless

Re: [PATCH v5 2/3] mac80211: track master queue status

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, 2008-12-18 at 23:17 +0200, Kalle Valo wrote:
> This is a preparation for the dynamic power save support. In future there are
> two paths to stop the master queues and we need to track this properly to
> avoid starting queues incorrectly. Implement this by adding a status
> array for each queue.
> 
> The original idea and design is from Johannes Berg, I just did
> the implementation based on his notes. All the bugs are mine, of course.
> 
> Signed-off-by: Kalle Valo <kalle.valo@xxxxxxxxx>

Looks good, thanks

Acked-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx>

> ---
> 
>  net/mac80211/ieee80211_i.h |   12 ++++++
>  net/mac80211/main.c        |    2 +
>  net/mac80211/util.c        |   86 +++++++++++++++++++++++++++++++++++++++++---
>  3 files changed, 93 insertions(+), 7 deletions(-)
> 
> diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
> index 18b9160..a74d673 100644
> --- a/net/mac80211/ieee80211_i.h
> +++ b/net/mac80211/ieee80211_i.h
> @@ -538,6 +538,10 @@ enum {
>  	IEEE80211_ADDBA_MSG	= 4,
>  };
>  
> +enum queue_stop_reason {
> +	IEEE80211_QUEUE_STOP_REASON_DRIVER,
> +};
> +
>  /* maximum number of hardware queues we support. */
>  #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES)
>  
> @@ -554,7 +558,8 @@ struct ieee80211_local {
>  	const struct ieee80211_ops *ops;
>  
>  	unsigned long queue_pool[BITS_TO_LONGS(QD_MAX_QUEUES)];
> -
> +	unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES];
> +	spinlock_t queue_stop_reason_lock;
>  	struct net_device *mdev; /* wmaster# - "master" 802.11 device */
>  	int open_count;
>  	int monitors, cooked_mntrs;
> @@ -972,6 +977,11 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq);
>  u64 ieee80211_mandatory_rates(struct ieee80211_local *local,
>  			      enum ieee80211_band band);
>  
> +void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
> +				     enum queue_stop_reason reason);
> +void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
> +				     enum queue_stop_reason reason);
> +
>  #ifdef CONFIG_MAC80211_NOINLINE
>  #define debug_noinline noinline
>  #else
> diff --git a/net/mac80211/main.c b/net/mac80211/main.c
> index a0371ca..7c6e90a 100644
> --- a/net/mac80211/main.c
> +++ b/net/mac80211/main.c
> @@ -724,6 +724,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
>  
>  	spin_lock_init(&local->key_lock);
>  
> +	spin_lock_init(&local->queue_stop_reason_lock);
> +
>  	INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);
>  
>  	sta_info_init(local);
> diff --git a/net/mac80211/util.c b/net/mac80211/util.c
> index 71a8391..fb89e1d 100644
> --- a/net/mac80211/util.c
> +++ b/net/mac80211/util.c
> @@ -330,10 +330,20 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
>  }
>  EXPORT_SYMBOL(ieee80211_ctstoself_duration);
>  
> -void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
> +static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
> +				   enum queue_stop_reason reason)
>  {
>  	struct ieee80211_local *local = hw_to_local(hw);
>  
> +	/* we don't need to track ampdu queues */
> +	if (queue < ieee80211_num_regular_queues(hw)) {
> +		__clear_bit(reason, &local->queue_stop_reasons[queue]);
> +
> +		if (local->queue_stop_reasons[queue] != 0)
> +			/* someone still has this queue stopped */
> +			return;
> +	}
> +
>  	if (test_bit(queue, local->queues_pending)) {
>  		set_bit(queue, local->queues_pending_run);
>  		tasklet_schedule(&local->tx_pending_tasklet);
> @@ -341,22 +351,74 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
>  		netif_wake_subqueue(local->mdev, queue);
>  	}
>  }
> +
> +void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
> +				    enum queue_stop_reason reason)
> +{
> +	struct ieee80211_local *local = hw_to_local(hw);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
> +	__ieee80211_wake_queue(hw, queue, reason);
> +	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
> +}
> +
> +void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
> +{
> +	ieee80211_wake_queue_by_reason(hw, queue,
> +				       IEEE80211_QUEUE_STOP_REASON_DRIVER);
> +}
>  EXPORT_SYMBOL(ieee80211_wake_queue);
>  
> -void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
> +static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
> +				   enum queue_stop_reason reason)
>  {
>  	struct ieee80211_local *local = hw_to_local(hw);
>  
> +	/* we don't need to track ampdu queues */
> +	if (queue < ieee80211_num_regular_queues(hw))
> +		__set_bit(reason, &local->queue_stop_reasons[queue]);
> +
>  	netif_stop_subqueue(local->mdev, queue);
>  }
> +
> +void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
> +				    enum queue_stop_reason reason)
> +{
> +	struct ieee80211_local *local = hw_to_local(hw);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
> +	__ieee80211_stop_queue(hw, queue, reason);
> +	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
> +}
> +
> +void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
> +{
> +	ieee80211_stop_queue_by_reason(hw, queue,
> +				       IEEE80211_QUEUE_STOP_REASON_DRIVER);
> +}
>  EXPORT_SYMBOL(ieee80211_stop_queue);
>  
> -void ieee80211_stop_queues(struct ieee80211_hw *hw)
> +void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
> +				    enum queue_stop_reason reason)
>  {
> +	struct ieee80211_local *local = hw_to_local(hw);
> +	unsigned long flags;
>  	int i;
>  
> +	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
> +
>  	for (i = 0; i < ieee80211_num_queues(hw); i++)
> -		ieee80211_stop_queue(hw, i);
> +		__ieee80211_stop_queue(hw, i, reason);
> +
> +	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
> +}
> +
> +void ieee80211_stop_queues(struct ieee80211_hw *hw)
> +{
> +	ieee80211_stop_queues_by_reason(hw,
> +					IEEE80211_QUEUE_STOP_REASON_DRIVER);
>  }
>  EXPORT_SYMBOL(ieee80211_stop_queues);
>  
> @@ -367,12 +429,24 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
>  }
>  EXPORT_SYMBOL(ieee80211_queue_stopped);
>  
> -void ieee80211_wake_queues(struct ieee80211_hw *hw)
> +void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
> +				     enum queue_stop_reason reason)
>  {
> +	struct ieee80211_local *local = hw_to_local(hw);
> +	unsigned long flags;
>  	int i;
>  
> +	spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
> +
>  	for (i = 0; i < hw->queues + hw->ampdu_queues; i++)
> -		ieee80211_wake_queue(hw, i);
> +		__ieee80211_wake_queue(hw, i, reason);
> +
> +	spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
> +}
> +
> +void ieee80211_wake_queues(struct ieee80211_hw *hw)
> +{
> +	ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_DRIVER);
>  }
>  EXPORT_SYMBOL(ieee80211_wake_queues);
>  
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

Attachment: signature.asc
Description: This is a digitally signed message part


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux