git: 96e43f01b762 - stable/13 - iwlwifi: cherry-pick fixes from upstream iwlwifi-next

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Thu, 30 Dec 2021 19:22:51 UTC
The branch stable/13 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=96e43f01b762b459747028a04880be4ccbfd4a38

commit 96e43f01b762b459747028a04880be4ccbfd4a38
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2021-12-27 17:41:19 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2021-12-30 18:28:42 +0000

    iwlwifi: cherry-pick fixes from upstream iwlwifi-next
    
    Cherry-pick f973795a8d19cbf3d03807704eb7c6ff65788d5a (Fix a double free
    in iwl_txq_dyn_alloc_dma), db66abeea3aefed481391ecc564fb7b7fb31d742
    (synchronize with FW after multicast commands),
    d5d8ee526d1401173ad1261c3b6388a4f947e0a3 (remove session protection
    upon station removal), and 8e967c137df3b236d2075f9538cb888129425d1a
    (avoid clearing a just saved session protection id).
    
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 8f06a2b550c6288b48996036c325a1999780cb6a)
---
 sys/contrib/dev/iwlwifi/mvm/mac80211.c   | 23 ++++++++++++++++++++---
 sys/contrib/dev/iwlwifi/mvm/time-event.c | 12 ++++++------
 sys/contrib/dev/iwlwifi/queue/tx.c       |  1 +
 3 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/sys/contrib/dev/iwlwifi/mvm/mac80211.c b/sys/contrib/dev/iwlwifi/mvm/mac80211.c
index 8aa929207986..cf116404d985 100644
--- a/sys/contrib/dev/iwlwifi/mvm/mac80211.c
+++ b/sys/contrib/dev/iwlwifi/mvm/mac80211.c
@@ -1674,6 +1674,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);
 
@@ -1683,6 +1684,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,
@@ -3292,16 +3309,16 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
 		if (vif->type == NL80211_IFTYPE_AP) {
 			mvmvif->ap_assoc_sta_count--;
 			iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
-		} else if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) {
-			/* remove session protection if still running */
+		} else if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
 			iwl_mvm_stop_session_protection(mvm, vif);
-		}
 		ret = 0;
 	} else if (old_state == IEEE80211_STA_AUTH &&
 		   new_state == IEEE80211_STA_NONE) {
 		ret = 0;
 	} else if (old_state == IEEE80211_STA_NONE &&
 		   new_state == IEEE80211_STA_NOTEXIST) {
+		if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls)
+			iwl_mvm_stop_session_protection(mvm, vif);
 		ret = iwl_mvm_rm_sta(mvm, vif, sta);
 		if (sta->tdls) {
 			iwl_mvm_recalc_tdls_state(mvm, vif, false);
diff --git a/sys/contrib/dev/iwlwifi/mvm/time-event.c b/sys/contrib/dev/iwlwifi/mvm/time-event.c
index e91f8e889df7..e6813317edf3 100644
--- a/sys/contrib/dev/iwlwifi/mvm/time-event.c
+++ b/sys/contrib/dev/iwlwifi/mvm/time-event.c
@@ -1158,15 +1158,10 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
 			cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
 							mvmvif->color)),
 		.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
+		.conf_id = cpu_to_le32(SESSION_PROTECT_CONF_ASSOC),
 		.duration_tu = cpu_to_le32(MSEC_TO_TU(duration)),
 	};
 
-	/* The time_event_data.id field is reused to save session
-	 * protection's configuration.
-	 */
-	mvmvif->time_event_data.id = SESSION_PROTECT_CONF_ASSOC;
-	cmd.conf_id = cpu_to_le32(mvmvif->time_event_data.id);
-
 	lockdep_assert_held(&mvm->mutex);
 
 	spin_lock_bh(&mvm->time_event_lock);
@@ -1180,6 +1175,11 @@ void iwl_mvm_schedule_session_protection(struct iwl_mvm *mvm,
 	}
 
 	iwl_mvm_te_clear_data(mvm, te_data);
+	/*
+	 * The time_event_data.id field is reused to save session
+	 * protection's configuration.
+	 */
+	te_data->id = le32_to_cpu(cmd.conf_id);
 	te_data->duration = le32_to_cpu(cmd.duration_tu);
 	te_data->vif = vif;
 	spin_unlock_bh(&mvm->time_event_lock);
diff --git a/sys/contrib/dev/iwlwifi/queue/tx.c b/sys/contrib/dev/iwlwifi/queue/tx.c
index efb68b45f028..2941b3c89899 100644
--- a/sys/contrib/dev/iwlwifi/queue/tx.c
+++ b/sys/contrib/dev/iwlwifi/queue/tx.c
@@ -1081,6 +1081,7 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num,
 	return 0;
 err_free_tfds:
 	dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->dma_addr);
+	txq->tfds = NULL;
 error:
 	if (txq->entries && cmd_queue)
 		for (i = 0; i < slots_num; i++)