summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/tx.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-03-11 08:34:31 +0100
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2015-03-18 07:41:33 +0100
commitfe92e32ace11b21311fbeb8dbf14ac45b87e700d (patch)
treee565098169c5a85c6a2273bc0eab771ab035563c /drivers/net/wireless/iwlwifi/mvm/tx.c
parentiwlwifi: pcie: add rx packet sequence number to dbg print (diff)
downloadlinux-fe92e32ace11b21311fbeb8dbf14ac45b87e700d.tar.xz
linux-fe92e32ace11b21311fbeb8dbf14ac45b87e700d.zip
iwlwifi: mvm: properly flush the queues for buffering transport
There are transport that must buffer frames in the driver. This means that we have frames that are not in the op_mode and not visible to the firwmare. This causes issues when we flush the queues: the op_mode flushes a queue, and the firmware flushes all the frames that are *currently* on the rings, but if the transport buffers frames, it can submit these while we are flushing. This leads to a situation where we still have frames on the queues after we flushed them. Preventing those buffered frame from getting into the firmware is possible, but then, we have to run the Tx response path on frames that didn't reach the firmware which is not desirable. The way I solve this here is to let these frames go to the firmware, but make sure the firmware will not transmit them (by setting the station as draining). The op_mode then needs to wait until the transport itself is empty to be sure that the queue is really empty. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/tx.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 7906b97c81b9..d963439cd899 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -1047,6 +1047,14 @@ out:
return 0;
}
+/*
+ * Note that there are transports that buffer frames before they reach
+ * the firmware. This means that after flush_tx_path is called, the
+ * queue might not be empty. The race-free way to handle this is to:
+ * 1) set the station as draining
+ * 2) flush the Tx path
+ * 3) wait for the transport queues to be empty
+ */
int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync)
{
int ret;