From: Ulrich Kunitz <kune@xxxxxxxxxxxxxx> This patch controls the mac80211 tx queues by the number of submitted URBs. Signed-off-by: Ulrich Kunitz <kune@xxxxxxxxxxxxxx> Signed-off-by: Daniel Drake <dsd@xxxxxxxxxx> --- drivers/net/wireless/mac80211/zd1211rw/zd_usb.c | 44 ++++++++++++++++++++--- drivers/net/wireless/mac80211/zd1211rw/zd_usb.h | 19 +++------- 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/drivers/net/wireless/mac80211/zd1211rw/zd_usb.c b/drivers/net/wireless/mac80211/zd1211rw/zd_usb.c index 30ae209..9b4950f 100644 --- a/drivers/net/wireless/mac80211/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/mac80211/zd1211rw/zd_usb.c @@ -736,7 +736,10 @@ void zd_usb_disable_tx(struct zd_usb *usb) usb_free_urb(list_entry(pos, struct urb, urb_list)); } tx->enabled = 0; - atomic_set(&tx->submitted_urbs, 0); + tx->submitted_urbs = 0; + /* The stopped state is ignored, relying on ieee80211_wake_queues() + * in a potentionally following zd_usb_enable_tx(). + */ spin_unlock_irqrestore(&tx->lock, flags); } @@ -754,7 +757,9 @@ void zd_usb_enable_tx(struct zd_usb *usb) spin_lock_irqsave(&tx->lock, flags); tx->enabled = 1; - atomic_set(&tx->submitted_urbs, 0); + tx->submitted_urbs = 0; + ieee80211_wake_queues(zd_usb_to_dev(usb)); + tx->stopped = 0; spin_unlock_irqrestore(&tx->lock, flags); } @@ -808,6 +813,34 @@ out: spin_unlock_irqrestore(&tx->lock, flags); } +static void tx_dec_submitted_urbs(struct zd_usb *usb) +{ + struct zd_usb_tx *tx = &usb->tx; + unsigned long flags; + + spin_lock_irqsave(&tx->lock, flags); + --tx->submitted_urbs; + if (tx->stopped && tx->submitted_urbs <= ZD_USB_TX_LOW) { + ieee80211_wake_queues(zd_usb_to_dev(usb)); + tx->stopped = 0; + } + spin_unlock_irqrestore(&tx->lock, flags); +} + +static void tx_inc_submitted_urbs(struct zd_usb *usb) +{ + struct zd_usb_tx *tx = &usb->tx; + unsigned long flags; + + spin_lock_irqsave(&tx->lock, flags); + ++tx->submitted_urbs; + if (!tx->stopped && tx->submitted_urbs > ZD_USB_TX_HIGH) { + ieee80211_stop_queues(zd_usb_to_dev(usb)); + tx->stopped = 1; + } + spin_unlock_irqrestore(&tx->lock, flags); +} + /** * tx_urb_complete - completes the execution of an URB * @urb: a URB @@ -842,8 +875,8 @@ free_urb: zd_mac_tx_to_dev(skb, urb->status); cb = (struct zd_tx_skb_control_block *)skb->cb; usb = &zd_dev_mac(cb->dev)->chip.usb; - atomic_dec(&usb->tx.submitted_urbs); free_tx_urb(usb, urb); + tx_dec_submitted_urbs(usb); return; resubmit: r = usb_submit_urb(urb, GFP_ATOMIC); @@ -883,7 +916,7 @@ int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb) r = usb_submit_urb(urb, GFP_ATOMIC); if (r) goto error; - atomic_inc(&usb->tx.submitted_urbs); + tx_inc_submitted_urbs(usb); return 0; error: free_tx_urb(usb, urb); @@ -918,8 +951,9 @@ static inline void init_usb_tx(struct zd_usb *usb) struct zd_usb_tx *tx = &usb->tx; spin_lock_init(&tx->lock); tx->enabled = 0; + tx->stopped = 0; INIT_LIST_HEAD(&tx->free_urb_list); - atomic_set(&tx->submitted_urbs, 0); + tx->submitted_urbs = 0; } void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *dev, diff --git a/drivers/net/wireless/mac80211/zd1211rw/zd_usb.h b/drivers/net/wireless/mac80211/zd1211rw/zd_usb.h index 7c58301..530f3b3 100644 --- a/drivers/net/wireless/mac80211/zd1211rw/zd_usb.h +++ b/drivers/net/wireless/mac80211/zd1211rw/zd_usb.h @@ -26,6 +26,9 @@ #include "zd_def.h" +#define ZD_USB_TX_HIGH 5 +#define ZD_USB_TX_LOW 2 + enum devicetype { DEVICE_ZD1211 = 0, DEVICE_ZD1211B = 1, @@ -183,12 +186,14 @@ struct zd_usb_rx { * @submitted_urbs: atomic integer that counts the URBs having sent to the * device, which haven't been completed * @enabled: enabled flag, indicates whether tx is enabled + * @stopped: indicates whether higher level tx queues are stopped */ struct zd_usb_tx { spinlock_t lock; struct list_head free_urb_list; - atomic_t submitted_urbs; + int submitted_urbs; int enabled; + int stopped; }; /* Contains the usb parts. The structure doesn't require a lock because intf @@ -237,18 +242,6 @@ void zd_usb_disable_tx(struct zd_usb *usb); int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb); -/** - * zd_usb_tx_frames - frames in transfer to the device - * @usb: a &struct zd_usb pointer - * - * This function returns the number of frames, which are currently - * transmitted to the device. - */ -static inline int zd_usb_tx_frames(struct zd_usb *usb) -{ - return atomic_read(&usb->tx.submitted_urbs); -} - int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, const zd_addr_t *addresses, unsigned int count); -- 1.5.2.2 - 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