diff options
author | Arik Nemtsov <arik@wizery.com> | 2012-07-29 12:18:32 +0300 |
---|---|---|
committer | Luciano Coelho <luca@coelho.fi> | 2012-09-27 12:13:51 +0300 |
commit | f83e54134a6d38437ddee0fda96692a6b0c33b0e (patch) | |
tree | 6e3469f9ee859bb3d7ad7459aff235af69f0e31e /drivers/net/wireless/ti/wlcore/tx.c | |
parent | 958e303abba61bad165a96e22e138c4763047df2 (diff) |
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 <arik@wizery.com>
Signed-off-by: Luciano Coelho <luca@coelho.fi>
Diffstat (limited to 'drivers/net/wireless/ti/wlcore/tx.c')
-rw-r--r-- | drivers/net/wireless/ti/wlcore/tx.c | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index d89e0db8a6f9..f9c26b19bff0 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); |