From: Grazvydas Ignotas Date: Mon, 25 Oct 2010 20:09:04 +0000 (+0300) Subject: wl1251: fix TX queue stopping/waking (again) X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=91f3c70243daf1c08f374f3aab873d70ea717106;p=pandora-wifi.git wl1251: fix TX queue stopping/waking (again) 9df86e2e702c6d5547aced7f241addd2d698bb11 ported TX queue stopping/waking improvement from wl1271, but it has some issues: - it forgot to initialize wl_lock. - it placed ieee80211_wake_queues in an awkward place between result handling loops, it's better to do it after all processing is done. - it left queue wake call in wl1251_tx_packet_cb, which made the patch ineffective because by the time we reached low watermark check, queues would already be woken. - the wl1271 watermark values are too large for wl1251, as it has shorter hardware tx queue. Correct those issues. Signed-off-by: Grazvydas Ignotas --- diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 79fa99e..0efe2e6 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h @@ -405,8 +405,8 @@ void wl1251_disable_interrupts(struct wl1251 *wl); #define WL1251_DEFAULT_POWER_LEVEL 20 -#define WL1251_TX_QUEUE_LOW_WATERMARK 10 -#define WL1251_TX_QUEUE_HIGH_WATERMARK 25 +#define WL1251_TX_QUEUE_LOW_WATERMARK 8 +#define WL1251_TX_QUEUE_HIGH_WATERMARK 20 #define WL1251_DEFAULT_BEACON_INT 100 #define WL1251_DEFAULT_DTIM_PERIOD 1 diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 2f7c65c..d212b8c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1373,6 +1373,8 @@ struct ieee80211_hw *wl1251_alloc_hw(void) INIT_WORK(&wl->irq_work, wl1251_irq_work); INIT_WORK(&wl->tx_work, wl1251_tx_work); + spin_lock_init(&wl->wl_lock); + /* * In case our MAC address is not correctly set, * we use a random but Nokia MAC. diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index 0bbcf9a..62918c9 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c @@ -503,10 +503,6 @@ out: return; } } - - wl1251_debug(DEBUG_TX, "cb: waking queues"); - ieee80211_wake_queues(wl->hw); - wl->tx_queue_stopped = false; } } @@ -516,6 +512,7 @@ void wl1251_tx_complete(struct wl1251 *wl) int i, result_index, num_complete = 0; struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr; unsigned long flags; + int queue_len; if (unlikely(wl->state != WL1251_STATE_ON)) return; @@ -544,20 +541,6 @@ void wl1251_tx_complete(struct wl1251 *wl) } } - if (wl->tx_queue_stopped - && - skb_queue_len(&wl->tx_queue) <= WL1251_TX_QUEUE_LOW_WATERMARK){ - - /* firmware buffer has space, restart queues */ - wl1251_debug(DEBUG_TX, "tx_complete: waking queues"); - spin_lock_irqsave(&wl->wl_lock, flags); - ieee80211_wake_queues(wl->hw); - wl->tx_queue_stopped = false; - spin_unlock_irqrestore(&wl->wl_lock, flags); - ieee80211_queue_work(wl->hw, &wl->tx_work); - - } - /* Every completed frame needs to be acknowledged */ if (num_complete) { /* @@ -606,6 +589,20 @@ void wl1251_tx_complete(struct wl1251 *wl) } wl->next_tx_complete = result_index; + + queue_len = skb_queue_len(&wl->tx_queue); + if (wl->tx_queue_stopped && + queue_len <= WL1251_TX_QUEUE_LOW_WATERMARK) { + /* firmware buffer has space, restart queues */ + wl1251_debug(DEBUG_TX, "tx_complete: waking queues"); + spin_lock_irqsave(&wl->wl_lock, flags); + ieee80211_wake_queues(wl->hw); + wl->tx_queue_stopped = false; + spin_unlock_irqrestore(&wl->wl_lock, flags); + } + + if (queue_len > 0) + ieee80211_queue_work(wl->hw, &wl->tx_work); } /* caller must hold wl->mutex */