From f83e54134a6d38437ddee0fda96692a6b0c33b0e Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 29 Jul 2012 12:18:32 +0300 Subject: [PATCH] wlcore: tx_flush - optimize flow and force Tx during the flush Force Tx during the flush if there are packets pending in the driver. This actually solves a bug where we would get called from the mac80211 wq context, which would prevent tx_work from getting queued, even when the mutex is unlocked. Don't stop the queues needlessly if there's nothing to flush. Use a larger delay when sleeping to give the driver a chance to flush and avoid cpu busy looping. Re-arrange the loop so the last iteration is not wasted. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/tx.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index d89e0db..f9c26b1 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -1084,22 +1084,32 @@ void wl1271_tx_flush(struct wl1271 *wl) /* only one flush should be in progress, for consistent queue state */ mutex_lock(&wl->flush_mutex); + mutex_lock(&wl->mutex); + if (wl->tx_frames_cnt == 0 && wl1271_tx_total_queue_count(wl) == 0) { + mutex_unlock(&wl->mutex); + goto out; + } + wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); while (!time_after(jiffies, timeout)) { - mutex_lock(&wl->mutex); wl1271_debug(DEBUG_MAC80211, "flushing tx buffer: %d %d", wl->tx_frames_cnt, wl1271_tx_total_queue_count(wl)); + + /* force Tx and give the driver some time to flush data */ + mutex_unlock(&wl->mutex); + if (wl1271_tx_total_queue_count(wl)) + wl1271_tx_work(&wl->tx_work); + msleep(20); + mutex_lock(&wl->mutex); + if ((wl->tx_frames_cnt == 0) && (wl1271_tx_total_queue_count(wl) == 0)) { - mutex_unlock(&wl->mutex); wl1271_debug(DEBUG_MAC80211, "tx flush took %d ms", jiffies_to_msecs(jiffies - start_time)); - goto out; + goto out_wake; } - mutex_unlock(&wl->mutex); - msleep(1); } wl1271_warning("Unable to flush all TX buffers, " @@ -1107,13 +1117,13 @@ void wl1271_tx_flush(struct wl1271 *wl) WL1271_TX_FLUSH_TIMEOUT / 1000); /* forcibly flush all Tx buffers on our queues */ - mutex_lock(&wl->mutex); for (i = 0; i < WL12XX_MAX_LINKS; i++) wl1271_tx_reset_link_queues(wl, i); - mutex_unlock(&wl->mutex); -out: +out_wake: wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); + mutex_unlock(&wl->mutex); +out: mutex_unlock(&wl->flush_mutex); } EXPORT_SYMBOL_GPL(wl1271_tx_flush); -- 2.7.4