Search Linux Wireless

Re: [PATCH 3/8] mac80211: rework the pending packets code

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

 



On Mon, Mar 23, 2009 at 05:28:37PM +0100, Johannes Berg wrote:
> The pending packets code is quite incomprehensible, uses memory barriers
> nobody really understands, etc. This patch reworks it entirely, using
> the queue spinlock, proper stop bits and the skb queues themselves to
> indicate whether packets are pending or not (rather than a separate
> variable like before).
> 
> Signed-off-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx>

<-- snip -->

>  /*
> @@ -1830,40 +1829,57 @@ void ieee80211_tx_pending(unsigned long 
>  {
>  	struct ieee80211_local *local = (struct ieee80211_local *)data;
>  	struct net_device *dev = local->mdev;
> -	struct ieee80211_tx_stored_packet *store;
>  	struct ieee80211_hdr *hdr;
> +	unsigned long flags;
>  	struct ieee80211_tx_data tx;
>  	int i, ret;
> +	bool next;
>  
>  	rcu_read_lock();
>  	netif_tx_lock_bh(dev);
> +
>  	for (i = 0; i < local->hw.queues; i++) {
> -		/* Check that this queue is ok */
> -		if (__netif_subqueue_stopped(local->mdev, i) &&
> -		    !test_bit(i, local->queues_pending_run))
> -			continue;
> +		/*
> +		 * If queue is stopped by something other than due to pending
> +		 * frames, or we have no pending frames, proceed to next queue.
> +		 */
> +		spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
> +		next = false;
> +		if (local->queue_stop_reasons[i] !=
> +			BIT(IEEE80211_QUEUE_STOP_REASON_PENDING) ||
> +		    skb_queue_empty(&local->pending[i]))
> +			next = true;
> +		spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
>  
> -		if (!test_bit(i, local->queues_pending)) {
> -			clear_bit(i, local->queues_pending_run);
> -			ieee80211_wake_queue(&local->hw, i);
> +		if (next)
>  			continue;
> -		}
>  
> -		clear_bit(i, local->queues_pending_run);
> +		/*
> +		 * start the queue now to allow processing our packets,
> +		 * we're under the tx lock here anyway so nothing will
> +		 * happen as a result of this
> +		 */
>  		netif_start_subqueue(local->mdev, i);
>  
> -		store = &local->pending_packet[i];
> -		tx.flags = 0;
> -		tx.skb = store->skb;
> -		hdr = (struct ieee80211_hdr *)tx.skb->data;
> -		tx.sta = sta_info_get(local, hdr->addr1);
> -		ret = __ieee80211_tx(local, &tx);
> -		store->skb = tx.skb;
> -		if (!ret) {
> -			clear_bit(i, local->queues_pending);
> -			ieee80211_wake_queue(&local->hw, i);
> +		while (!skb_queue_empty(&local->pending[i])) {
> +			tx.flags = 0;
> +			tx.skb = skb_dequeue(&local->pending[i]);
> +			hdr = (struct ieee80211_hdr *)tx.skb->data;
> +			tx.sta = sta_info_get(local, hdr->addr1);
> +
> +			ret = __ieee80211_tx(local, &tx);
> +			if (ret != IEEE80211_TX_OK) {
> +				skb_queue_head(&local->pending[i], tx.skb);
> +				break;
> +			}
>  		}

So this is good functional change, might be worth mentioning in the
commit log, that is, we now requeue onto the pending queue the skb
when the driver's tx() didn't return NETDEV_TX_OK or when __ieee80211_tx()
returns IEEE80211_TX_PENDING (which happens when the queue is stopped).
Maybe even better as a seperate patch. Before this we were just dropping
the skbs in the pending queue under those same conditions.

Other than that:

Reviewed-by: Luis R. Rodriguez <lrodriguez@xxxxxxxxxxx>

  Luis
--
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

[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