| From 26f4a3d51f215cad2a4ce42818a6de2be2847a1b Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sat, 4 Dec 2021 08:35:45 +0200 |
| Subject: iwlwifi: mvm: synchronize with FW after multicast commands |
| |
| From: Johannes Berg <johannes.berg@intel.com> |
| |
| [ Upstream commit db66abeea3aefed481391ecc564fb7b7fb31d742 ] |
| |
| If userspace installs a lot of multicast groups very quickly, then |
| we may run out of command queue space as we send the updates in an |
| asynchronous fashion (due to locking concerns), and the CPU can |
| create them faster than the firmware can process them. This is true |
| even when mac80211 has a work struct that gets scheduled. |
| |
| Fix this by synchronizing with the firmware after sending all those |
| commands - outside of the iteration we can send a synchronous echo |
| command that just has the effect of the CPU waiting for the prior |
| asynchronous commands to finish. This also will cause fewer of the |
| commands to be sent to the firmware overall, because the work will |
| only run once when rescheduled multiple times while it's running. |
| |
| Link: https://bugzilla.kernel.org/show_bug.cgi?id=213649 |
| Suggested-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> |
| Reported-by: Maximilian Ernestus <maximilian@ernestus.de> |
| 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.20211204083238.51aea5b79ea4.I88a44798efda16e9fe480fb3e94224931d311b29@changeid |
| Signed-off-by: Luca Coelho <luciano.coelho@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| .../net/wireless/intel/iwlwifi/mvm/mac80211.c | 17 +++++++++++++++++ |
| 1 file changed, 17 insertions(+) |
| |
| diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c |
| index d82d8cfe2e41c..f896758a3fa31 100644 |
| --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c |
| +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c |
| @@ -1608,6 +1608,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm) |
| struct iwl_mvm_mc_iter_data iter_data = { |
| .mvm = mvm, |
| }; |
| + int ret; |
| |
| lockdep_assert_held(&mvm->mutex); |
| |
| @@ -1617,6 +1618,22 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm) |
| ieee80211_iterate_active_interfaces_atomic( |
| mvm->hw, IEEE80211_IFACE_ITER_NORMAL, |
| iwl_mvm_mc_iface_iterator, &iter_data); |
| + |
| + /* |
| + * Send a (synchronous) ech command so that we wait for the |
| + * multiple asynchronous MCAST_FILTER_CMD commands sent by |
| + * the interface iterator. Otherwise, we might get here over |
| + * and over again (by userspace just sending a lot of these) |
| + * and the CPU can send them faster than the firmware can |
| + * process them. |
| + * Note that the CPU is still faster - but with this we'll |
| + * actually send fewer commands overall because the CPU will |
| + * not schedule the work in mac80211 as frequently if it's |
| + * still running when rescheduled (possibly multiple times). |
| + */ |
| + ret = iwl_mvm_send_cmd_pdu(mvm, ECHO_CMD, 0, 0, NULL); |
| + if (ret) |
| + IWL_ERR(mvm, "Failed to synchronize multicast groups update\n"); |
| } |
| |
| static u64 iwl_mvm_prepare_multicast(struct ieee80211_hw *hw, |
| -- |
| 2.34.1 |
| |