]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
iwlwifi: mvm: clear tx queue id when unreserving aggregation queue
authorAvraham Stern <avraham.stern@intel.com>
Wed, 7 Mar 2018 08:41:18 +0000 (10:41 +0200)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Mon, 27 Aug 2018 14:40:05 +0000 (16:40 +0200)
BugLink: http://bugs.launchpad.net/bugs/1786352
[ Upstream commit 4b387906b1c3692bb790388c335515c0cf098a23 ]

When a queue is reserved for aggregation, the queue id is assigned
to the tid_data. This is fine since iwl_mvm_sta_tx_agg_oper()
takes care of allocating the queue before actual tx starts.
When the reservation is cancelled (e.g. when the AP declined the
aggregation request) the tid_data is not cleared. As a result,
following tx for this tid was trying to use an unallocated queue.

Fix this by setting the txq_id for the tid to invalid when unreserving
the queue.

Signed-off-by: Avraham Stern <avraham.stern@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Khalid Elmously <khalid.elmously@canonical.com>
drivers/net/wireless/intel/iwlwifi/mvm/sta.c

index 8d81a1603484315270a9e612aac8c2269fc8fc50..29651758f7759dcc0ccb48e95f346e0d1abaab9b 100644 (file)
@@ -2682,8 +2682,10 @@ out:
 
 static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm,
                                        struct iwl_mvm_sta *mvmsta,
-                                       u16 txq_id)
+                                       struct iwl_mvm_tid_data *tid_data)
 {
+       u16 txq_id = tid_data->txq_id;
+
        if (iwl_mvm_has_new_tx_api(mvm))
                return;
 
@@ -2695,8 +2697,10 @@ static void iwl_mvm_unreserve_agg_queue(struct iwl_mvm *mvm,
         * allocated through iwl_mvm_enable_txq, so we can just mark it back as
         * free.
         */
-       if (mvm->queue_info[txq_id].status == IWL_MVM_QUEUE_RESERVED)
+       if (mvm->queue_info[txq_id].status == IWL_MVM_QUEUE_RESERVED) {
                mvm->queue_info[txq_id].status = IWL_MVM_QUEUE_FREE;
+               tid_data->txq_id = IWL_MVM_INVALID_QUEUE;
+       }
 
        spin_unlock_bh(&mvm->queue_info_lock);
 }
@@ -2727,7 +2731,7 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
 
        mvmsta->agg_tids &= ~BIT(tid);
 
-       iwl_mvm_unreserve_agg_queue(mvm, mvmsta, txq_id);
+       iwl_mvm_unreserve_agg_queue(mvm, mvmsta, tid_data);
 
        switch (tid_data->state) {
        case IWL_AGG_ON:
@@ -2794,7 +2798,7 @@ int iwl_mvm_sta_tx_agg_flush(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        mvmsta->agg_tids &= ~BIT(tid);
        spin_unlock_bh(&mvmsta->lock);
 
-       iwl_mvm_unreserve_agg_queue(mvm, mvmsta, txq_id);
+       iwl_mvm_unreserve_agg_queue(mvm, mvmsta, tid_data);
 
        if (old_state >= IWL_AGG_ON) {
                iwl_mvm_drain_sta(mvm, mvmsta, true);