aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ti/wlcore/tx.c
diff options
context:
space:
mode:
authorArik Nemtsov <arik@wizery.com>2012-07-29 12:18:32 +0300
committerLuciano Coelho <luca@coelho.fi>2012-09-27 12:13:51 +0300
commitf83e54134a6d38437ddee0fda96692a6b0c33b0e (patch)
tree6e3469f9ee859bb3d7ad7459aff235af69f0e31e /drivers/net/wireless/ti/wlcore/tx.c
parentwlcore: make Tx flush timings more verbose (diff)
downloadlinux-dev-f83e54134a6d38437ddee0fda96692a6b0c33b0e.tar.xz
linux-dev-f83e54134a6d38437ddee0fda96692a6b0c33b0e.zip
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.c26
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);