Search Linux Wireless

[PATCH 09/31] wlcore: tx_flush - optimize flow and force Tx during the flush

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Arik Nemtsov <arik@xxxxxxxxxx>

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@xxxxxxxxxx>
Signed-off-by: Luciano Coelho <luca@xxxxxxxxx>
---
 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);
-- 
1.7.10.4

--
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


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux