]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iwlwifi: mvm: do more useful queue sync accounting
authorJohannes Berg <johannes.berg@intel.com>
Wed, 9 Dec 2020 21:16:31 +0000 (23:16 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 1 Mar 2024 12:16:47 +0000 (13:16 +0100)
[ Upstream commit 2f7a04c7b03b7fd63b7618e29295fc25732faac1 ]

We're currently doing accounting on the queue sync with an
atomic variable that counts down the number of remaining
notifications that we still need.

As we've been hitting issues in this area, modify this to
track a bitmap of queues, not just the number of queues,
and print out the remaining bitmap in the warning.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20201209231352.0a3fa177cd6b.I7c69ff999419368266279ec27dd618eb450908b3@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Stable-dep-of: 5f8a3561ea8b ("iwlwifi: mvm: write queue_sync_state only for sync")
Signed-off-by: Sasha Levin <sashal@kernel.org>
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/rxmq.c

index d2c6fdb7027320ac7bbeff2a638ad62d735d47f3..f2096729ac5aca8464f7e94039453421760e40f7 100644 (file)
@@ -5155,8 +5155,7 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
 
        if (notif->sync) {
                notif->cookie = mvm->queue_sync_cookie;
-               atomic_set(&mvm->queue_sync_counter,
-                          mvm->trans->num_rx_queues);
+               mvm->queue_sync_state = (1 << mvm->trans->num_rx_queues) - 1;
        }
 
        ret = iwl_mvm_notify_rx_queue(mvm, qmask, (u8 *)notif,
@@ -5169,14 +5168,16 @@ void iwl_mvm_sync_rx_queues_internal(struct iwl_mvm *mvm,
        if (notif->sync) {
                lockdep_assert_held(&mvm->mutex);
                ret = wait_event_timeout(mvm->rx_sync_waitq,
-                                        atomic_read(&mvm->queue_sync_counter) == 0 ||
+                                        READ_ONCE(mvm->queue_sync_state) == 0 ||
                                         iwl_mvm_is_radio_killed(mvm),
                                         HZ);
-               WARN_ON_ONCE(!ret && !iwl_mvm_is_radio_killed(mvm));
+               WARN_ONCE(!ret && !iwl_mvm_is_radio_killed(mvm),
+                         "queue sync: failed to sync, state is 0x%lx\n",
+                         mvm->queue_sync_state);
        }
 
 out:
-       atomic_set(&mvm->queue_sync_counter, 0);
+       mvm->queue_sync_state = 0;
        if (notif->sync)
                mvm->queue_sync_cookie++;
 }
index 64f5a4cb3d3ac83ae433d95b3b3a684d29808bfe..8b779c3a92d430f994c6b08c65af4866887b4d8f 100644 (file)
@@ -842,7 +842,7 @@ struct iwl_mvm {
        unsigned long status;
 
        u32 queue_sync_cookie;
-       atomic_t queue_sync_counter;
+       unsigned long queue_sync_state;
        /*
         * for beacon filtering -
         * currently only one interface can be supported
index 5b173f21e87bf10166cd057960eb55f430ef9655..3548eb57f1f305015c529658ff3eb77e332593bf 100644 (file)
@@ -725,7 +725,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
 
        init_waitqueue_head(&mvm->rx_sync_waitq);
 
-       atomic_set(&mvm->queue_sync_counter, 0);
+       mvm->queue_sync_state = 0;
 
        SET_IEEE80211_DEV(mvm->hw, mvm->trans->dev);
 
index 86b3fb321dfdd82b0871bfb7920eac724c78e09e..e2a39e8b98d07e387d76d104b3c88fdd5cefa66f 100644 (file)
@@ -853,9 +853,13 @@ void iwl_mvm_rx_queue_notif(struct iwl_mvm *mvm, struct napi_struct *napi,
                WARN_ONCE(1, "Invalid identifier %d", internal_notif->type);
        }
 
-       if (internal_notif->sync &&
-           !atomic_dec_return(&mvm->queue_sync_counter))
-               wake_up(&mvm->rx_sync_waitq);
+       if (internal_notif->sync) {
+               WARN_ONCE(!test_and_clear_bit(queue, &mvm->queue_sync_state),
+                         "queue sync: queue %d responded a second time!\n",
+                         queue);
+               if (READ_ONCE(mvm->queue_sync_state) == 0)
+                       wake_up(&mvm->rx_sync_waitq);
+       }
 }
 
 static void iwl_mvm_oldsn_workaround(struct iwl_mvm *mvm,