OSDN Git Service

wifi: iwlwifi: mvm: fix mvmtxq->stopped handling
authorJohannes Berg <johannes.berg@intel.com>
Fri, 17 Mar 2023 09:53:24 +0000 (10:53 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 22 Mar 2023 12:14:18 +0000 (13:14 +0100)
This could race if the queue is redirected while full, then
the flushing internally would start it while it's not yet
usable again. Fix it by using two state bits instead of just
one.

Reviewed-by: Benjamin Berg <benjamin.berg@intel.com>
Tested-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/mvm/ops.c
drivers/net/wireless/intel/iwlwifi/mvm/sta.c

index 5655224..f81c609 100644 (file)
@@ -732,7 +732,10 @@ void iwl_mvm_mac_itxq_xmit(struct ieee80211_hw *hw, struct ieee80211_txq *txq)
 
        rcu_read_lock();
        do {
-               while (likely(!mvmtxq->stopped &&
+               while (likely(!test_bit(IWL_MVM_TXQ_STATE_STOP_FULL,
+                                       &mvmtxq->state) &&
+                             !test_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT,
+                                       &mvmtxq->state) &&
                              !test_bit(IWL_MVM_STATUS_IN_D3, &mvm->status))) {
                        skb = ieee80211_tx_dequeue(hw, txq);
 
index 90bc95d..421d264 100644 (file)
@@ -729,7 +729,9 @@ struct iwl_mvm_txq {
        struct list_head list;
        u16 txq_id;
        atomic_t tx_request;
-       bool stopped;
+#define IWL_MVM_TXQ_STATE_STOP_FULL    0
+#define IWL_MVM_TXQ_STATE_STOP_REDIRECT        1
+       unsigned long state;
 };
 
 static inline struct iwl_mvm_txq *
index f4e9446..efad8f9 100644 (file)
@@ -1691,7 +1691,10 @@ static void iwl_mvm_queue_state_change(struct iwl_op_mode *op_mode,
 
                txq = sta->txq[tid];
                mvmtxq = iwl_mvm_txq_from_mac80211(txq);
-               mvmtxq->stopped = !start;
+               if (start)
+                       clear_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
+               else
+                       set_bit(IWL_MVM_TXQ_STATE_STOP_FULL, &mvmtxq->state);
 
                if (start && mvmsta->sta_state != IEEE80211_STA_NOTEXIST)
                        iwl_mvm_mac_itxq_xmit(mvm->hw, txq);
index 69634fb..21ad7b8 100644 (file)
@@ -693,7 +693,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,
                            queue, iwl_mvm_ac_to_tx_fifo[ac]);
 
        /* Stop the queue and wait for it to empty */
-       txq->stopped = true;
+       set_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);
 
        ret = iwl_trans_wait_tx_queues_empty(mvm->trans, BIT(queue));
        if (ret) {
@@ -736,7 +736,7 @@ static int iwl_mvm_redirect_queue(struct iwl_mvm *mvm, int queue, int tid,
 
 out:
        /* Continue using the queue */
-       txq->stopped = false;
+       clear_bit(IWL_MVM_TXQ_STATE_STOP_REDIRECT, &txq->state);
 
        return ret;
 }