iwlwifi: mvm: free AGG queue when we STA is removed
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Tue, 19 Feb 2013 13:32:42 +0000 (15:32 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 6 Mar 2013 15:47:00 +0000 (16:47 +0100)
When we stop an AGG session, we need to look at the sequence
numbers in in the private area of the ieee80211_sta struct.
This allows us to know is the queue is empty. To get access
to this private area, we use fw_id_to_mac_id that maps
sta_id (index of the STA in fw table) to ieee80211_sta.

When the STA exists in fw, but not in mac80211, we set
an ERR ptr in fw_id_to_mac_id.

But if we first set an ERR ptr to fw_id_to_mac_id, and only
then flush the queues, then we won't be able to access the
sequence numbers in ieee80211_sta from the reclaim flow.
This means that we will never be able to release an AGG
queue when a station is deleted.

So first, flush the queue. That will let the reclaim flow
call iwl_mvm_check_ratid_empty which will disable the AGG
queue as needed, and only then, remove the mapping in
fw_id_to_mac_id.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/iwlwifi/mvm/sta.c

index 1970001..ca7aba4 100644 (file)
@@ -340,6 +340,9 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
 
        if (vif->type == NL80211_IFTYPE_STATION &&
            mvmvif->ap_sta_id == mvm_sta->sta_id) {
+               /* flush its queues here since we are freeing mvm_sta */
+               ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
+
                /*
                 * Put a non-NULL since the fw station isn't removed.
                 * It will be removed after the MAC will be set as
@@ -348,9 +351,6 @@ int iwl_mvm_rm_sta(struct iwl_mvm *mvm,
                rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
                                   ERR_PTR(-EINVAL));
 
-               /* flush its queues here since we are freeing mvm_sta */
-               ret = iwl_mvm_flush_tx_path(mvm, mvm_sta->tfd_queue_msk, true);
-
                /* if we are associated - we can't remove the AP STA now */
                if (vif->bss_conf.assoc)
                        return ret;