aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/dvm/mac80211.c
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2013-04-07 03:13:44 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-04-08 07:32:20 -0400
commit2d055afdcada4bd8b510e9d2a8566fbded3c9696 (patch)
tree3462550733d3646acf56b9048772ed21f6ead8f5 /drivers/net/wireless/iwlwifi/dvm/mac80211.c
parentff40231282d4eb57c5008ed48fef6dd1be9f3130 (diff)
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 <emmanuel.grumbach@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/dvm/mac80211.c')
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index a7294fa4d7e5..fc3879804622 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -777,9 +777,12 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
777 IWL_DEBUG_HT(priv, "start Tx\n"); 777 IWL_DEBUG_HT(priv, "start Tx\n");
778 ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); 778 ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
779 break; 779 break;
780 case IEEE80211_AMPDU_TX_STOP_CONT:
781 case IEEE80211_AMPDU_TX_STOP_FLUSH: 780 case IEEE80211_AMPDU_TX_STOP_FLUSH:
782 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: 781 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
782 IWL_DEBUG_HT(priv, "Flush Tx\n");
783 ret = iwlagn_tx_agg_flush(priv, vif, sta, tid);
784 break;
785 case IEEE80211_AMPDU_TX_STOP_CONT:
783 IWL_DEBUG_HT(priv, "stop Tx\n"); 786 IWL_DEBUG_HT(priv, "stop Tx\n");
784 ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); 787 ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
785 if ((ret == 0) && (priv->agg_tids_count > 0)) { 788 if ((ret == 0) && (priv->agg_tids_count > 0)) {
@@ -1122,7 +1125,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
1122 */ 1125 */
1123 if (drop) { 1126 if (drop) {
1124 IWL_DEBUG_MAC80211(priv, "send flush command\n"); 1127 IWL_DEBUG_MAC80211(priv, "send flush command\n");
1125 if (iwlagn_txfifo_flush(priv)) { 1128 if (iwlagn_txfifo_flush(priv, 0)) {
1126 IWL_ERR(priv, "flush request fail\n"); 1129 IWL_ERR(priv, "flush request fail\n");
1127 goto done; 1130 goto done;
1128 } 1131 }