Commit f83e5413 authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Luciano Coelho
Browse files

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: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarLuciano Coelho <luca@coelho.fi>
parent 958e303a
Loading
Loading
Loading
Loading
+18 −8
Original line number Diff line number Diff line
@@ -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);