From 2d055afdcada4bd8b510e9d2a8566fbded3c9696 Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Sun, 7 Apr 2013 10:13:44 +0300 Subject: iwlwifi: dvm: handle FLUSH ampdu actions from mac80211 Until now we didn't handle properly the FLUSH ampdu action coming from mac80211. This could result in SCD queue leak: mac80211 would STOP_FLUSH an AMPDU Tx session and remove the station. If we had still packets on the ring, we wouldn't deallocate the SCD queue and wait for it to be empty. The indication of the queue being empty comes from the Tx response flow which relies on the tid_data structure. The problem is that this structure has been cleared when the station has been removed. In order to solve this issue, block in the STOP_FLUSH ampdu_action until the SCD queue is flushed, and only then, let mac80211 move forward to remove the station. iwlagn_txfifo_flush had to be enhanced to allow this. The bug fixed here caused the "txq_id mismatch: 12 0" print. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg --- drivers/net/wireless/iwlwifi/dvm/lib.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers/net/wireless/iwlwifi/dvm/lib.c') diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index f2aeb1a..29ff93f 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c @@ -136,7 +136,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, * 1. acquire mutex before calling * 2. make sure rf is on and not in exit state */ -int iwlagn_txfifo_flush(struct iwl_priv *priv) +int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk) { struct iwl_txfifo_flush_cmd flush_cmd; struct iwl_host_cmd cmd = { @@ -162,6 +162,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv) if (priv->nvm_data->sku_cap_11n_enable) flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK; + if (scd_q_msk) + flush_cmd.queue_control = cpu_to_le32(scd_q_msk); + IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", flush_cmd.queue_control); flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL); @@ -173,7 +176,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv) { mutex_lock(&priv->mutex); ieee80211_stop_queues(priv->hw); - if (iwlagn_txfifo_flush(priv)) { + if (iwlagn_txfifo_flush(priv, 0)) { IWL_ERR(priv, "flush request fail\n"); goto done; } -- cgit v1.1