* [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID
@ 2026-07-20 6:43 Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 1/8] wifi: ath12k: fix out-of-bounds clear_bit in ath12k_mac_dp_peer_cleanup() Baochen Qiang
` (8 more replies)
0 siblings, 9 replies; 12+ messages in thread
From: Baochen Qiang @ 2026-07-20 6:43 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
ath12k currently assumes the host allocates the MLD peer ID and passes
it down to firmware via WMI_PEER_ASSOC_CMDID. This works on QCN9274
but breaks WCN7850/QCC2072, whose firmware always picks the ID itself
and reports it back through HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP. As a
result dp_hw->dp_peers[] is never populated for MLO peers and the data
path lookup fails. On QCC2072 the firmware additionally crashes on MLO
disconnect when ATH12K_WMI_FLAG_MLO_PEER_ID_VALID was set in the peer
assoc command.
Add a host_alloc_ml_id hw_param to branch behavior, defer the
dp_peers[] publish to the HTT event for firmware-allocated chips, and
propagate the firmware-assigned ID through the existing host
bookkeeping when it arrives.
Patch summary:
1: fix for an out-of-bounds clear_bit() in
ath12k_mac_dp_peer_cleanup().
2: group peer assoc send-and-wait into a helper
3: refactor, keep ATH12K_PEER_ML_ID_VALID set in ahsta->ml_peer_id
so later patches do not have to OR or mask it at every call site;
4: parse the HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP message;
5: introduce hw_param host_alloc_ml_id, set true on QCN9274 family
and false on WCN7850/QCC2072;
6: on host_alloc_ml_id == false, leave peer_id_valid unset and send
ml_peer_id == 0 in WMI_PEER_ASSOC_CMDID;
7: on host_alloc_ml_id == false, mark ahsta->ml_peer_id and
dp_peer->peer_id as ATH12K_MLO_PEER_ID_PENDING and skip the
dp_hw->dp_peers[] publish until the firmware reports the ID;
8: in the MLO_RX_PEER_MAP handler, propagate the firmware-assigned
ID into dp_peer->peer_id, every dp_link_peer in
dp_peer->link_peers[], and ahsta->ml_peer_id, all under
dp_hw->peer_lock.
---
Changes in v2:
- patch 5/8: initialize ret before goto err handling in ath12k_mac_allocate()
- Link to v1: https://lore.kernel.org/r/20260713-ath12k-fw-allocated-ml-peer-id-v1-0-d0a2a1a519eb@oss.qualcomm.com
---
Baochen Qiang (8):
wifi: ath12k: fix out-of-bounds clear_bit in ath12k_mac_dp_peer_cleanup()
wifi: ath12k: factor out peer assoc send-and-wait into a helper
wifi: ath12k: keep ATH12K_PEER_ML_ID_VALID set in ath12k_sta::ml_peer_id
wifi: ath12k: add support for HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP
wifi: ath12k: introduce host_alloc_ml_id hardware parameter
wifi: ath12k: do not advertise MLD peer ID for firmware-allocate devices
wifi: ath12k: defer dp_peer registration when firmware allocates MLD peer ID
wifi: ath12k: resolve PENDING ML peer ID from MLO_PEER_MAP HTT event
drivers/net/wireless/ath/ath12k/core.c | 2 +
drivers/net/wireless/ath/ath12k/core.h | 3 +
drivers/net/wireless/ath/ath12k/dp_htt.c | 49 +++++++++
drivers/net/wireless/ath/ath12k/dp_htt.h | 12 +++
drivers/net/wireless/ath/ath12k/dp_peer.c | 75 +++++++++++--
drivers/net/wireless/ath/ath12k/dp_peer.h | 2 +
drivers/net/wireless/ath/ath12k/hw.h | 2 +
drivers/net/wireless/ath/ath12k/mac.c | 165 ++++++++++++++++++++---------
drivers/net/wireless/ath/ath12k/peer.c | 31 +++++-
drivers/net/wireless/ath/ath12k/peer.h | 1 +
drivers/net/wireless/ath/ath12k/wifi7/hw.c | 12 +++
11 files changed, 293 insertions(+), 61 deletions(-)
---
base-commit: 951dc0a744e4dc8490935316d3b76e23990bde3c
change-id: 20260527-ath12k-fw-allocated-ml-peer-id-2b456891157f
Best regards,
--
Baochen Qiang <baochen.qiang@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH ath-current v2 1/8] wifi: ath12k: fix out-of-bounds clear_bit in ath12k_mac_dp_peer_cleanup()
2026-07-20 6:43 [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Baochen Qiang
@ 2026-07-20 6:43 ` Baochen Qiang
2026-07-23 15:45 ` Jeff Johnson
2026-07-20 6:43 ` [PATCH ath-current v2 2/8] wifi: ath12k: factor out peer assoc send-and-wait into a helper Baochen Qiang
` (7 subsequent siblings)
8 siblings, 1 reply; 12+ messages in thread
From: Baochen Qiang @ 2026-07-20 6:43 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
ath12k_mac_dp_peer_cleanup() clears the ML peer ID slot on the
free_ml_peer_id_map bitmap by indexing it with dp_peer->peer_id. That is
wrong: dp_peer->peer_id for an MLO peer always carries the
ATH12K_PEER_ML_ID_VALID bit (BIT(13)), so clear_bit() is invoked with
index >= 0x2000, which is far outside the bitmap of ATH12K_MAX_MLO_PEERS
(256) bits and corrupts memory adjacent to ah->free_ml_peer_id_map. The
intended bitmap entry also never gets cleared, so subsequent
ath12k_peer_ml_alloc() calls eventually run out of IDs.
The ID without the VALID bit is what ath12k_peer_ml_alloc() returned and
is stored in ahsta->ml_peer_id. Use that instead.
While there, also reset ahsta->ml_peer_id to ATH12K_MLO_PEER_ID_INVALID so
the bitmap and ahsta->ml_peer_id stay in sync;
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3
Fixes: ee16dcf573d5 ("wifi: ath12k: Define ath12k_dp_peer structure & APIs for create & delete")
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 490c134c1f29..b7eba8ea981b 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -1283,8 +1283,11 @@ void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah)
spin_lock_bh(&dp_hw->peer_lock);
list_for_each_entry_safe(dp_peer, tmp, &dp_hw->dp_peers_list, list) {
if (dp_peer->is_mlo) {
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(dp_peer->sta);
+
rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
- clear_bit(dp_peer->peer_id, ah->free_ml_peer_id_map);
+ clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
+ ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
}
list_move(&dp_peer->list, &peers);
--
2.25.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ath-current v2 2/8] wifi: ath12k: factor out peer assoc send-and-wait into a helper
2026-07-20 6:43 [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 1/8] wifi: ath12k: fix out-of-bounds clear_bit in ath12k_mac_dp_peer_cleanup() Baochen Qiang
@ 2026-07-20 6:43 ` Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 3/8] wifi: ath12k: keep ATH12K_PEER_ML_ID_VALID set in ath12k_sta::ml_peer_id Baochen Qiang
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Baochen Qiang @ 2026-07-20 6:43 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
ath12k_bss_assoc(), ath12k_mac_station_assoc() and
ath12k_sta_rc_update_wk() all open-code the same sequence: reinit the
peer_assoc_done completion, send the peer assoc WMI command, then wait
for the firmware confirmation event. The reinit_completion() was buried
in ath12k_peer_assoc_prepare(), far from the wait_for_completion_timeout()
that consumes it, making the reinit/send/wait sequence hard to follow,
and the three open-coded copies are easy to get out of sync.
Move the sequence into a new helper ath12k_mac_peer_assoc() and call it
from all three sites. The reinit, send and wait now live together so the
completion's lifecycle is easy to read.
While at it, ath12k_sta_rc_update_wk() previously warned but still
waited the full timeout when the peer assoc command failed to send. Now
a send failure returns immediately and skips the pointless 1 second
wait, matching the other two callers.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 59 +++++++++++++++++------------------
1 file changed, 29 insertions(+), 30 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index b7eba8ea981b..3e3b06e15f80 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -3594,8 +3594,6 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar,
memset(arg, 0, sizeof(*arg));
- reinit_completion(&ar->peer_assoc_done);
-
arg->peer_new_assoc = !reassoc;
ath12k_peer_assoc_h_basic(ar, arvif, arsta, arg);
ath12k_peer_assoc_h_crypto(ar, arvif, arsta, arg);
@@ -3835,6 +3833,29 @@ static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,
return bw;
}
+static int ath12k_mac_peer_assoc(struct ath12k *ar,
+ struct ath12k_wmi_peer_assoc_arg *peer_arg)
+{
+ int ret;
+
+ reinit_completion(&ar->peer_assoc_done);
+
+ ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",
+ peer_arg->peer_mac, peer_arg->vdev_id, ret);
+ return ret;
+ }
+
+ if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
+ ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
+ peer_arg->peer_mac, peer_arg->vdev_id);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
static void ath12k_bss_assoc(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ieee80211_bss_conf *bss_conf)
@@ -3915,18 +3936,10 @@ static void ath12k_bss_assoc(struct ath12k *ar,
}
peer_arg->is_assoc = true;
- ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
- if (ret) {
- ath12k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",
- bss_conf->bssid, arvif->vdev_id, ret);
- return;
- }
- if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
- ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
- bss_conf->bssid, arvif->vdev_id);
+ ret = ath12k_mac_peer_assoc(ar, peer_arg);
+ if (ret)
return;
- }
ret = ath12k_setup_peer_smps(ar, arvif, bss_conf->bssid,
&link_sta->ht_cap, &link_sta->he_6ghz_capa);
@@ -6480,18 +6493,10 @@ static int ath12k_mac_station_assoc(struct ath12k *ar,
}
peer_arg->is_assoc = true;
- ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
- if (ret) {
- ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
- arsta->addr, arvif->vdev_id, ret);
- return ret;
- }
- if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
- ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
- arsta->addr, arvif->vdev_id);
- return -ETIMEDOUT;
- }
+ ret = ath12k_mac_peer_assoc(ar, peer_arg);
+ if (ret)
+ return ret;
num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask);
@@ -6840,14 +6845,8 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
peer_arg, true);
peer_arg->is_assoc = false;
- err = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
- if (err)
- ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
- arsta->addr, arvif->vdev_id, err);
- if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ))
- ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
- arsta->addr, arvif->vdev_id);
+ ath12k_mac_peer_assoc(ar, peer_arg);
}
}
}
--
2.25.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ath-current v2 3/8] wifi: ath12k: keep ATH12K_PEER_ML_ID_VALID set in ath12k_sta::ml_peer_id
2026-07-20 6:43 [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 1/8] wifi: ath12k: fix out-of-bounds clear_bit in ath12k_mac_dp_peer_cleanup() Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 2/8] wifi: ath12k: factor out peer assoc send-and-wait into a helper Baochen Qiang
@ 2026-07-20 6:43 ` Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 4/8] wifi: ath12k: add support for HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP Baochen Qiang
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Baochen Qiang @ 2026-07-20 6:43 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
Several pieces of host bookkeeping for MLD peer IDs encode the
same fact in different ways:
- ath12k_sta::ml_peer_id stores the raw ID in [0, ATH12K_MAX_MLO_PEERS);
- ath12k_dp_peer::peer_id, ath12k_dp_link_peer::ml_id and the index used
on ath12k_dp_hw::dp_peers[] always carry the ATH12K_PEER_ML_ID_VALID
bit (BIT(13)) when the ID is real;
- WMI_MLO_PEER_ASSOC_PARAMS::ml_peer_id sent down to firmware is
raw, without the bookkeeping bit.
The mismatch leaks into call sites that have to remember to OR
the bit in (ath12k_peer_create(), ath12k_mac_op_sta_state()) or
remember not to (ath12k_peer_assoc_h_mlo()).
Make ath12k_sta::ml_peer_id carry the VALID bit when valid, the same
way ath12k_dp_peer::peer_id and ath12k_dp_link_peer::ml_id do:
- ath12k_peer_ml_alloc() OR-s the bit in once on the way out;
the internal bitmap stays raw [0, ATH12K_MAX_MLO_PEERS);
- ath12k_peer_create() and ath12k_mac_op_sta_state() drop the
explicit OR;
- ath12k_peer_assoc_h_mlo() masks the bit off when populating
the WMI ml_peer_id;
While there, introduce ath12k_peer_ml_free() to mirror
ath12k_peer_ml_alloc(), which helps avoid code duplication.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 27 +++++++++++++--------------
drivers/net/wireless/ath/ath12k/peer.c | 17 ++++++++++++++---
drivers/net/wireless/ath/ath12k/peer.h | 1 +
3 files changed, 28 insertions(+), 17 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 3e3b06e15f80..7d0d7d5fbf53 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -1278,16 +1278,15 @@ void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah)
struct ath12k_dp_peer *dp_peer, *tmp;
struct ath12k_dp_hw *dp_hw = &ah->dp_hw;
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
INIT_LIST_HEAD(&peers);
spin_lock_bh(&dp_hw->peer_lock);
list_for_each_entry_safe(dp_peer, tmp, &dp_hw->dp_peers_list, list) {
if (dp_peer->is_mlo) {
- struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(dp_peer->sta);
-
rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
- clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
- ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
+ ath12k_peer_ml_free(ah, ath12k_sta_to_ahsta(dp_peer->sta));
}
list_move(&dp_peer->list, &peers);
@@ -3547,7 +3546,11 @@ static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta,
ether_addr_copy(ml->mld_addr, sta->addr);
ml->logical_link_idx = arsta->link_idx;
- ml->ml_peer_id = ahsta->ml_peer_id;
+ /*
+ * WMI_MLO_PEER_ASSOC_PARAMS expects the raw ML peer ID without
+ * the host-side ATH12K_PEER_ML_ID_VALID bookkeeping bit.
+ */
+ ml->ml_peer_id = ahsta->ml_peer_id & ~ATH12K_PEER_ML_ID_VALID;
ml->ieee_link_id = arsta->link_id;
ml->num_partner_links = 0;
ml->eml_cap = sta->eml_cap;
@@ -7264,10 +7267,8 @@ static void ath12k_mac_ml_station_remove(struct ath12k_vif *ahvif,
ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id);
}
- if (sta->mlo) {
- clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
- ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
- }
+ if (sta->mlo)
+ ath12k_peer_ml_free(ah, ahsta);
}
static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
@@ -7739,7 +7740,7 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
}
dp_params.is_mlo = true;
- dp_params.peer_id = ahsta->ml_peer_id | ATH12K_PEER_ML_ID_VALID;
+ dp_params.peer_id = ahsta->ml_peer_id;
}
dp_params.sta = sta;
@@ -7876,10 +7877,8 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
peer_delete:
ath12k_dp_peer_delete(&ah->dp_hw, sta->addr, sta);
ml_peer_id_clear:
- if (sta->mlo) {
- clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
- ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
- }
+ if (sta->mlo)
+ ath12k_peer_ml_free(ah, ahsta);
exit:
/* update the state if everything went well */
if (!ret)
diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
index c222bdaa333c..ae93731b4177 100644
--- a/drivers/net/wireless/ath/ath12k/peer.c
+++ b/drivers/net/wireless/ath/ath12k/peer.c
@@ -230,7 +230,7 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
/* Fill ML info into created peer */
if (sta->mlo) {
ml_peer_id = ahsta->ml_peer_id;
- peer->ml_id = ml_peer_id | ATH12K_PEER_ML_ID_VALID;
+ peer->ml_id = ml_peer_id;
ether_addr_copy(peer->ml_addr, sta->addr);
/* the assoc link is considered primary for now */
@@ -276,9 +276,20 @@ u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah)
}
if (ml_peer_id == ATH12K_MAX_MLO_PEERS)
- ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
+ return ATH12K_MLO_PEER_ID_INVALID;
- return ml_peer_id;
+ return ml_peer_id | ATH12K_PEER_ML_ID_VALID;
+}
+
+void ath12k_peer_ml_free(struct ath12k_hw *ah, struct ath12k_sta *ahsta)
+{
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ if (ahsta->ml_peer_id <
+ (ATH12K_MAX_MLO_PEERS | ATH12K_PEER_ML_ID_VALID))
+ clear_bit(ahsta->ml_peer_id & ~ATH12K_PEER_ML_ID_VALID,
+ ah->free_ml_peer_id_map);
+ ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
}
int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta)
diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h
index 49d89796bc46..0f7f25b8e89c 100644
--- a/drivers/net/wireless/ath/ath12k/peer.h
+++ b/drivers/net/wireless/ath/ath12k/peer.h
@@ -26,4 +26,5 @@ int ath12k_link_sta_rhash_add(struct ath12k_base *ab, struct ath12k_link_sta *ar
struct ath12k_link_sta *ath12k_link_sta_find_by_addr(struct ath12k_base *ab,
const u8 *addr);
u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah);
+void ath12k_peer_ml_free(struct ath12k_hw *ah, struct ath12k_sta *ahsta);
#endif /* _PEER_H_ */
--
2.25.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ath-current v2 4/8] wifi: ath12k: add support for HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP
2026-07-20 6:43 [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Baochen Qiang
` (2 preceding siblings ...)
2026-07-20 6:43 ` [PATCH ath-current v2 3/8] wifi: ath12k: keep ATH12K_PEER_ML_ID_VALID set in ath12k_sta::ml_peer_id Baochen Qiang
@ 2026-07-20 6:43 ` Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 5/8] wifi: ath12k: introduce host_alloc_ml_id hardware parameter Baochen Qiang
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Baochen Qiang @ 2026-07-20 6:43 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
Firmware on chips that allocate the MLD peer ID itself (WCN7850 and
QCC2072) reports the assignment back to the host through
HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP. The message carries the chosen
MLD peer id, the MLD MAC address etc.
Add the message type, the on-the-wire struct, the field masks and a
handler that parses them out. The host-side state update (publishing the
dp peer into ath12k_dp_hw::dp_peers[], propagating the ID to
ath12k_dp_link_peer::ml_id and ath12k_sta::ml_peer_id) is added in a
follow-up patch;
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/dp_htt.c | 30 ++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/dp_htt.h | 12 ++++++++++++
2 files changed, 42 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/dp_htt.c b/drivers/net/wireless/ath/ath12k/dp_htt.c
index 52e10059c6d5..150b190f9c7f 100644
--- a/drivers/net/wireless/ath/ath12k/dp_htt.c
+++ b/drivers/net/wireless/ath/ath12k/dp_htt.c
@@ -575,6 +575,33 @@ static void ath12k_htt_mlo_offset_event_handler(struct ath12k_base *ab,
rcu_read_unlock();
}
+static void ath12k_dp_htt_mlo_peer_map_handler(struct ath12k_base *ab,
+ struct sk_buff *skb)
+{
+ struct htt_resp_msg *resp = (struct htt_resp_msg *)skb->data;
+ struct htt_t2h_mlo_peer_map_event *ev = &resp->mlo_peer_map_ev;
+ u16 raw_peer_id, peer_id, addr_h16;
+ u8 peer_addr[ETH_ALEN];
+
+ if (skb->len < sizeof(*ev)) {
+ ath12k_warn(ab, "unexpected htt mlo peer map event len %u\n",
+ skb->len);
+ return;
+ }
+
+ raw_peer_id = le32_get_bits(ev->info0,
+ HTT_T2H_MLO_PEER_MAP_INFO0_MLO_PEER_ID);
+ peer_id = raw_peer_id | ATH12K_PEER_ML_ID_VALID;
+
+ addr_h16 = le32_get_bits(ev->info1,
+ HTT_T2H_MLO_PEER_MAP_INFO1_MAC_ADDR_H16);
+ ath12k_dp_get_mac_addr(le32_to_cpu(ev->mac_addr_l32), addr_h16,
+ peer_addr);
+
+ ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt mlo peer map peer %pM id %u\n",
+ peer_addr, peer_id);
+}
+
void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
struct sk_buff *skb)
{
@@ -659,6 +686,9 @@ void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
case HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND:
ath12k_htt_mlo_offset_event_handler(ab, skb);
break;
+ case HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP:
+ ath12k_dp_htt_mlo_peer_map_handler(ab, skb);
+ break;
default:
ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt event %d not handled\n",
type);
diff --git a/drivers/net/wireless/ath/ath12k/dp_htt.h b/drivers/net/wireless/ath/ath12k/dp_htt.h
index 987689f11cda..2db7fb27c036 100644
--- a/drivers/net/wireless/ath/ath12k/dp_htt.h
+++ b/drivers/net/wireless/ath/ath12k/dp_htt.h
@@ -930,6 +930,7 @@ enum htt_t2h_msg_type {
HTT_T2H_MSG_TYPE_EXT_STATS_CONF = 0x1c,
HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND = 0x24,
HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND = 0x28,
+ HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP = 0x29,
HTT_T2H_MSG_TYPE_PEER_MAP3 = 0x2b,
HTT_T2H_MSG_TYPE_VDEV_TXRX_STATS_PERIODIC_IND = 0x2c,
};
@@ -974,11 +975,22 @@ struct htt_t2h_peer_unmap_event {
__le32 info1;
} __packed;
+#define HTT_T2H_MLO_PEER_MAP_INFO0_MLO_PEER_ID GENMASK(23, 8)
+#define HTT_T2H_MLO_PEER_MAP_INFO1_MAC_ADDR_H16 GENMASK(15, 0)
+
+struct htt_t2h_mlo_peer_map_event {
+ __le32 info0;
+ __le32 mac_addr_l32;
+ __le32 info1;
+ __le32 reserved[5];
+} __packed;
+
struct htt_resp_msg {
union {
struct htt_t2h_version_conf_msg version_msg;
struct htt_t2h_peer_map_event peer_map_ev;
struct htt_t2h_peer_unmap_event peer_unmap_ev;
+ struct htt_t2h_mlo_peer_map_event mlo_peer_map_ev;
};
} __packed;
--
2.25.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ath-current v2 5/8] wifi: ath12k: introduce host_alloc_ml_id hardware parameter
2026-07-20 6:43 [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Baochen Qiang
` (3 preceding siblings ...)
2026-07-20 6:43 ` [PATCH ath-current v2 4/8] wifi: ath12k: add support for HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP Baochen Qiang
@ 2026-07-20 6:43 ` Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 6/8] wifi: ath12k: do not advertise MLD peer ID for firmware-allocate devices Baochen Qiang
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Baochen Qiang @ 2026-07-20 6:43 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
Different ath12k devices diverge on who allocates MLD peer id:
WCN7850/QCC2072 have the firmware allocate it and notify the host via
HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP event; While others let the host allocate
it and pass it down through WMI_PEER_ASSOC_CMDID with
ATH12K_WMI_FLAG_MLO_PEER_ID_VALID set.
Currently ath12k host allocates this ID and sends it to firmware by
default for all devices. This breaks WCN7850/QCC2072, because the host
maintained ID may be different from the firmware-allocated one.
Consequently data path may fail to find the dp peer and drop some received
packets. From user point of view, this results in bugs reported in [1] or
the 4-way handshake timeout issue.
Add host_alloc_ml_id flag to struct ath12k_hw_params (and a copy on struct
ath12k_hw for hot-path access) so subsequent patches can branch on it. Set
true for QCN9274/IPQ5332/IPQ5424, false for WCN7850/QCC2072. The flag will
be consumed by subsequent patches.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3
Link: https://bugzilla.kernel.org/show_bug.cgi?id=221039 # 1
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/core.h | 1 +
drivers/net/wireless/ath/ath12k/hw.h | 2 ++
drivers/net/wireless/ath/ath12k/mac.c | 18 +++++++++++++++++-
drivers/net/wireless/ath/ath12k/wifi7/hw.c | 12 ++++++++++++
4 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index fc5127b5c1a3..1f56474efbea 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -793,6 +793,7 @@ struct ath12k_hw {
enum ath12k_hw_state state;
bool regd_updated;
bool use_6ghz_regd;
+ bool host_alloc_ml_id;
u8 num_radio;
diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h
index d135b2936378..8091501cf742 100644
--- a/drivers/net/wireless/ath/ath12k/hw.h
+++ b/drivers/net/wireless/ath/ath12k/hw.h
@@ -232,6 +232,8 @@ struct ath12k_hw_params {
u32 max_client_dbs;
u32 max_client_dbs_sbs;
} client;
+
+ bool host_alloc_ml_id;
};
struct ath12k_hw_ops {
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 7d0d7d5fbf53..1ae21618afb6 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -15382,8 +15382,9 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)
int mac_id, device_id, total_radio, num_hw;
struct ath12k_base *ab;
struct ath12k_hw *ah;
- int ret, i, j;
+ bool conf = false;
u8 radio_per_hw;
+ int ret, i, j;
total_radio = 0;
for (i = 0; i < ag->num_devices; i++) {
@@ -15423,6 +15424,20 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)
}
ab = ag->ab[device_id];
+
+ /*
+ * the assumption is all devices within an ah
+ * share the same host_alloc_ml_id configuration
+ */
+ if (j == 0) {
+ conf = ab->hw_params->host_alloc_ml_id;
+ } else if (conf != ab->hw_params->host_alloc_ml_id) {
+ ath12k_warn(ab, "inconsistent ML ID config within ah, device 0 uses %s allocated ID, while device %u doesn't\n",
+ conf ? "host" : "firmware", device_id);
+ ret = -EINVAL;
+ goto err;
+ }
+
pdev_map[j].ab = ab;
pdev_map[j].pdev_idx = mac_id;
mac_id++;
@@ -15447,6 +15462,7 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)
}
ah->dev = ab->dev;
+ ah->host_alloc_ml_id = conf;
ag->ah[i] = ah;
ag->num_hw++;
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
index e5bf9d218104..0c277f51d99c 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
@@ -439,6 +439,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_client_dbs = 128,
.max_client_dbs_sbs = 128,
},
+
+ .host_alloc_ml_id = true,
},
{
.name = "wcn7850 hw2.0",
@@ -530,6 +532,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_client_dbs = 128,
.max_client_dbs_sbs = 128,
},
+
+ .host_alloc_ml_id = false,
},
{
.name = "qcn9274 hw2.0",
@@ -617,6 +621,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_client_dbs = 128,
.max_client_dbs_sbs = 128,
},
+
+ .host_alloc_ml_id = true,
},
{
.name = "ipq5332 hw1.0",
@@ -697,6 +703,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_client_dbs = 128,
.max_client_dbs_sbs = 128,
},
+
+ .host_alloc_ml_id = true,
},
{
.name = "qcc2072 hw1.0",
@@ -789,6 +797,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_client_dbs = 128,
.max_client_dbs_sbs = 128,
},
+
+ .host_alloc_ml_id = false,
},
{
.name = "ipq5424 hw1.0",
@@ -873,6 +883,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_client_dbs = 128,
.max_client_dbs_sbs = 128,
},
+
+ .host_alloc_ml_id = true,
},
};
--
2.25.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ath-current v2 6/8] wifi: ath12k: do not advertise MLD peer ID for firmware-allocate devices
2026-07-20 6:43 [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Baochen Qiang
` (4 preceding siblings ...)
2026-07-20 6:43 ` [PATCH ath-current v2 5/8] wifi: ath12k: introduce host_alloc_ml_id hardware parameter Baochen Qiang
@ 2026-07-20 6:43 ` Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 7/8] wifi: ath12k: defer dp_peer registration when firmware allocates MLD peer ID Baochen Qiang
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Baochen Qiang @ 2026-07-20 6:43 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
ath12k_peer_assoc_h_mlo() unconditionally sets ml->peer_id_valid and copies
ahsta->ml_peer_id (with the ATH12K_PEER_ML_ID_VALID bookkeeping bit masked
off) into the WMI_PEER_ASSOC_CMDID ML params, which causes
ath12k_wmi_send_peer_assoc_cmd() to set ATH12K_WMI_FLAG_MLO_PEER_ID_VALID.
This needs to be gated on chips where the firmware allocates the MLD peer
ID:
- WCN7850/QCC2072 firmware always picks the ID itself and does not honor
a host-supplied one, so the value would be silently ignored anyway;
- QCC2072 firmware additionally crashes during MLO disconnect when
ATH12K_WMI_FLAG_MLO_PEER_ID_VALID was set in the preceding peer assoc,
so the bit must not be sent at all.
Branch on ah->host_alloc_ml_id:
- When true (QCN9274 etc.), behavior is unchanged: peer_id_valid is set
and the raw ahsta->ml_peer_id (without the VALID bit) is sent down.
- When false (WCN7850, QCC2072), peer_id_valid stays unset and
ml_peer_id is sent as 0. The firmware ignores both fields and reports
the ID it allocated through HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP.
The early-return on ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID only
applies on the host-alloc path, since on the firmware-alloc path the value
is ATH12K_MLO_PEER_ID_PENDING here, not INVALID.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/mac.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 1ae21618afb6..485be2998180 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -3529,11 +3529,16 @@ static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta,
struct ath12k_sta *ahsta = arsta->ahsta;
struct ath12k_link_sta *arsta_p;
struct ath12k_link_vif *arvif;
+ struct ath12k_hw *ah = arsta->arvif->ar->ah;
unsigned long links;
u8 link_id;
int i;
- if (!sta->mlo || ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID)
+ if (!sta->mlo)
+ return;
+
+ if (ah->host_alloc_ml_id &&
+ ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID)
return;
ml->enabled = true;
@@ -3541,16 +3546,25 @@ static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta,
/* For now considering the primary umac based on assoc link */
ml->primary_umac = arsta->is_assoc_link;
- ml->peer_id_valid = true;
+ /*
+ * Only chips that allocate the MLD peer ID on the host send a valid
+ * ml_peer_id in WMI_PEER_ASSOC_CMDID. For chips where the firmware
+ * picks the ID, leave peer_id_valid false to avoid unexpected issues.
+ */
+ ml->peer_id_valid = ah->host_alloc_ml_id;
ml->logical_link_idx_valid = true;
ether_addr_copy(ml->mld_addr, sta->addr);
ml->logical_link_idx = arsta->link_idx;
/*
* WMI_MLO_PEER_ASSOC_PARAMS expects the raw ML peer ID without
- * the host-side ATH12K_PEER_ML_ID_VALID bookkeeping bit.
+ * the host-side ATH12K_PEER_ML_ID_VALID bookkeeping bit. For chips
+ * where the firmware allocates the ID, the field is unused (the
+ * firmware always allocates regardless of the value here); send 0
+ * to make that intent explicit.
*/
- ml->ml_peer_id = ahsta->ml_peer_id & ~ATH12K_PEER_ML_ID_VALID;
+ ml->ml_peer_id = ah->host_alloc_ml_id ?
+ (ahsta->ml_peer_id & ~ATH12K_PEER_ML_ID_VALID) : 0;
ml->ieee_link_id = arsta->link_id;
ml->num_partner_links = 0;
ml->eml_cap = sta->eml_cap;
--
2.25.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ath-current v2 7/8] wifi: ath12k: defer dp_peer registration when firmware allocates MLD peer ID
2026-07-20 6:43 [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Baochen Qiang
` (5 preceding siblings ...)
2026-07-20 6:43 ` [PATCH ath-current v2 6/8] wifi: ath12k: do not advertise MLD peer ID for firmware-allocate devices Baochen Qiang
@ 2026-07-20 6:43 ` Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 8/8] wifi: ath12k: resolve PENDING ML peer ID from MLO_PEER_MAP HTT event Baochen Qiang
2026-07-23 17:21 ` [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Jeff Johnson
8 siblings, 0 replies; 12+ messages in thread
From: Baochen Qiang @ 2026-07-20 6:43 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
For chips with host_alloc_ml_id=true (QCN9274 etc.), the host allocates
the MLD peer ID up front; ath12k_dp_peer_create() publishes the dp_peer
into dp_hw->dp_peers[] using that ID immediately. WCN7850/QCC2072 does
not work that way: the firmware picks the ID and only tells the host
afterwards via HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP, so the publication has
to be delayed until the event arrives.
Introduce ATH12K_MLO_PEER_ID_PENDING (0xFFFE) as a sentinel for "is_mlo,
but ID not yet known". On the firmware-allocates path:
- ath12k_mac_op_sta_state(NOTEXIST->NONE) skips ath12k_peer_ml_alloc()
and stores PENDING in ahsta->ml_peer_id and dp_params.peer_id;
- ath12k_dp_peer_create() skips dp_peer registration until a real ID is
known;
- ath12k_peer_create() leaves peer->ml_id at INVALID so consumer sites
do not treat PENDING as a real ID;
- ath12k_peer_ml_free() and ath12k_mac_dp_peer_cleanup() skip the
dp_peers[] write and the free_ml_peer_id_map clear when
host_alloc_ml_id is false or the ID is still PENDING.
The HTT handler change that resolves the PENDING ID is added in a
follow-up patch.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/core.h | 1 +
drivers/net/wireless/ath/ath12k/dp_peer.c | 23 +++++++++++++++--------
drivers/net/wireless/ath/ath12k/mac.c | 22 ++++++++++++++++------
drivers/net/wireless/ath/ath12k/peer.c | 20 +++++++++++++++++---
4 files changed, 49 insertions(+), 17 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 1f56474efbea..8769b41f5db5 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -72,6 +72,7 @@
#define ATH12K_MAX_MLO_PEERS 256
#define ATH12K_MLO_PEER_ID_INVALID 0xFFFF
+#define ATH12K_MLO_PEER_ID_PENDING 0xFFFE
#define ATH12K_INVALID_RSSI_FULL -1
#define ATH12K_INVALID_RSSI_EMPTY -128
diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c
index 47d009a0d61f..2a2eae194007 100644
--- a/drivers/net/wireless/ath/ath12k/dp_peer.c
+++ b/drivers/net/wireless/ath/ath12k/dp_peer.c
@@ -472,7 +472,9 @@ int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr,
dp_peer->is_mlo = params->is_mlo;
/*
- * For MLO client, the host assigns the ML peer ID, so set peer_id in dp_peer
+ * For MLO client, the ML peer ID, either known or PENDING, needs to be
+ * initialized here since the following logic depends on it.
+ *
* For non-MLO client, host gets link peer ID from firmware and will be
* assigned at the time of link peer creation
*/
@@ -488,13 +490,17 @@ int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr,
list_add(&dp_peer->list, &dp_hw->dp_peers_list);
/*
- * For MLO client, the peer_id for ath12k_dp_peer is allocated by host
- * and that peer_id is known at this point, and hence this ath12k_dp_peer
- * can be added to the RCU table using the peer_id.
- * For non-MLO client, this addition to RCU table shall be done at the
- * time of assignment of ath12k_dp_link_peer to ath12k_dp_peer.
+ * For an MLO client whose ML peer ID is allocated by the host, the
+ * peer_id is known here and the dp_peer can be added to the RCU
+ * table using it. For an MLO client on chips where the firmware
+ * allocates the ID, peer_id is ATH12K_MLO_PEER_ID_PENDING and the
+ * RCU table publish is deferred to the
+ * HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP handler. For a non-MLO client
+ * the publish happens later, at the time of assignment of
+ * ath12k_dp_link_peer to ath12k_dp_peer.
*/
- if (dp_peer->is_mlo)
+ if (dp_peer->is_mlo &&
+ dp_peer->peer_id != ATH12K_MLO_PEER_ID_PENDING)
rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], dp_peer);
spin_unlock_bh(&dp_hw->peer_lock);
@@ -515,7 +521,8 @@ void ath12k_dp_peer_delete(struct ath12k_dp_hw *dp_hw, u8 *addr,
return;
}
- if (dp_peer->is_mlo)
+ if (dp_peer->is_mlo &&
+ dp_peer->peer_id != ATH12K_MLO_PEER_ID_PENDING)
rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
list_del(&dp_peer->list);
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 485be2998180..533109f9d5bd 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -1285,7 +1285,9 @@ void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah)
spin_lock_bh(&dp_hw->peer_lock);
list_for_each_entry_safe(dp_peer, tmp, &dp_hw->dp_peers_list, list) {
if (dp_peer->is_mlo) {
- rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
+ if (dp_peer->peer_id != ATH12K_MLO_PEER_ID_PENDING)
+ rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id],
+ NULL);
ath12k_peer_ml_free(ah, ath12k_sta_to_ahsta(dp_peer->sta));
}
@@ -7746,11 +7748,19 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
/* ML sta */
if (sta->mlo && !ahsta->links_map &&
(hweight16(sta->valid_links) == 1)) {
- ahsta->ml_peer_id = ath12k_peer_ml_alloc(ah);
- if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {
- ath12k_hw_warn(ah, "unable to allocate ML peer id for sta %pM",
- sta->addr);
- goto exit;
+ if (ah->host_alloc_ml_id) {
+ ahsta->ml_peer_id = ath12k_peer_ml_alloc(ah);
+ if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {
+ ath12k_hw_warn(ah, "unable to allocate ML peer id for sta %pM",
+ sta->addr);
+ goto exit;
+ }
+ } else {
+ /*
+ * firmware allocates the ML peer ID and notifies
+ * the host via HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP
+ */
+ ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_PENDING;
}
dp_params.is_mlo = true;
diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
index ae93731b4177..25e4b79f11d6 100644
--- a/drivers/net/wireless/ath/ath12k/peer.c
+++ b/drivers/net/wireless/ath/ath12k/peer.c
@@ -230,7 +230,16 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
/* Fill ML info into created peer */
if (sta->mlo) {
ml_peer_id = ahsta->ml_peer_id;
- peer->ml_id = ml_peer_id;
+ /*
+ * For chips where firmware allocates the ML peer ID,
+ * ml_peer_id is ATH12K_MLO_PEER_ID_PENDING here. The
+ * MLO_RX_PEER_MAP HTT event handler fixes up
+ * peer->ml_id once the ID is known.
+ */
+ if (ml_peer_id == ATH12K_MLO_PEER_ID_PENDING)
+ peer->ml_id = ATH12K_MLO_PEER_ID_INVALID;
+ else
+ peer->ml_id = ml_peer_id;
ether_addr_copy(peer->ml_addr, sta->addr);
/* the assoc link is considered primary for now */
@@ -285,8 +294,13 @@ void ath12k_peer_ml_free(struct ath12k_hw *ah, struct ath12k_sta *ahsta)
{
lockdep_assert_wiphy(ah->hw->wiphy);
- if (ahsta->ml_peer_id <
- (ATH12K_MAX_MLO_PEERS | ATH12K_PEER_ML_ID_VALID))
+ /*
+ * Only devices that allocate the ID on the host own a slot in
+ * free_ml_peer_id_map.
+ */
+ if (ah->host_alloc_ml_id &&
+ (ahsta->ml_peer_id <
+ (ATH12K_MAX_MLO_PEERS | ATH12K_PEER_ML_ID_VALID)))
clear_bit(ahsta->ml_peer_id & ~ATH12K_PEER_ML_ID_VALID,
ah->free_ml_peer_id_map);
ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
--
2.25.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH ath-current v2 8/8] wifi: ath12k: resolve PENDING ML peer ID from MLO_PEER_MAP HTT event
2026-07-20 6:43 [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Baochen Qiang
` (6 preceding siblings ...)
2026-07-20 6:43 ` [PATCH ath-current v2 7/8] wifi: ath12k: defer dp_peer registration when firmware allocates MLD peer ID Baochen Qiang
@ 2026-07-20 6:43 ` Baochen Qiang
2026-07-23 17:21 ` [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Jeff Johnson
8 siblings, 0 replies; 12+ messages in thread
From: Baochen Qiang @ 2026-07-20 6:43 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, Baochen Qiang
Add ath12k_dp_peer_fixup_peer_id() and call it from the
HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP handler. For devices where the
firmware allocates the MLD peer ID, this is the point at which
all data structures that were left with ATH12K_MLO_PEER_ID_PENDING
or ATH12K_MLO_PEER_ID_INVALID get their real ID:
- dp_peer->peer_id is updated and the dp_peer is published into
dp_hw->dp_peers[];
- every existing dp_link_peer in dp_peer->link_peers[] gets its
ml_id set to the same value;
- ahsta->ml_peer_id is updated to the same value so peer_assoc,
sta_state and cleanup paths see a consistent ID.
Devices with host_alloc_ml_id == true also receive the same HTT
event, but the firmware-reported ID always matches the
host-allocated one and everything has already been populated by
ath12k_dp_peer_create(); Skips the helper entirely on those devices.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221039
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/core.c | 2 ++
drivers/net/wireless/ath/ath12k/core.h | 1 +
drivers/net/wireless/ath/ath12k/dp_htt.c | 19 +++++++++++
drivers/net/wireless/ath/ath12k/dp_peer.c | 52 +++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath12k/dp_peer.h | 2 ++
drivers/net/wireless/ath/ath12k/mac.c | 24 ++++++++++++++
6 files changed, 100 insertions(+)
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index 0e7c732f8222..cf9c5b068fa6 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -1547,6 +1547,8 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
}
wiphy_unlock(ah->hw->wiphy);
+
+ complete(&ah->peer_ml_id_done);
}
wake_up(&ab->wmi_ab.tx_credits_wq);
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 8769b41f5db5..30726e580833 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -795,6 +795,7 @@ struct ath12k_hw {
bool regd_updated;
bool use_6ghz_regd;
bool host_alloc_ml_id;
+ struct completion peer_ml_id_done;
u8 num_radio;
diff --git a/drivers/net/wireless/ath/ath12k/dp_htt.c b/drivers/net/wireless/ath/ath12k/dp_htt.c
index 150b190f9c7f..68968f96b4f1 100644
--- a/drivers/net/wireless/ath/ath12k/dp_htt.c
+++ b/drivers/net/wireless/ath/ath12k/dp_htt.c
@@ -6,6 +6,7 @@
#include "core.h"
#include "peer.h"
+#include "dp_peer.h"
#include "htc.h"
#include "dp_htt.h"
#include "debugfs_htt_stats.h"
@@ -582,6 +583,7 @@ static void ath12k_dp_htt_mlo_peer_map_handler(struct ath12k_base *ab,
struct htt_t2h_mlo_peer_map_event *ev = &resp->mlo_peer_map_ev;
u16 raw_peer_id, peer_id, addr_h16;
u8 peer_addr[ETH_ALEN];
+ int ret;
if (skb->len < sizeof(*ev)) {
ath12k_warn(ab, "unexpected htt mlo peer map event len %u\n",
@@ -600,6 +602,23 @@ static void ath12k_dp_htt_mlo_peer_map_handler(struct ath12k_base *ab,
ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt mlo peer map peer %pM id %u\n",
peer_addr, peer_id);
+
+ /*
+ * Fix up the dp_peer entry created with ATH12K_MLO_PEER_ID_PENDING
+ * earlier; on chips with host_alloc_ml_id == false this is the only
+ * point at which the host learns the firmware-assigned ID. Chips
+ * that allocate the ID on the host also receive this event but the
+ * firmware-reported ID matches the host-allocated one, so there is
+ * nothing to fix up.
+ */
+ if (!ab->hw_params->host_alloc_ml_id) {
+ ret = ath12k_dp_peer_fixup_peer_id(ab, peer_addr,
+ peer_id);
+ if (ret)
+ ath12k_warn(ab,
+ "failed to fix up peer id %u for dp peer %pM: %d\n",
+ peer_id, peer_addr, ret);
+ }
}
void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c
index 2a2eae194007..09142dcb74f9 100644
--- a/drivers/net/wireless/ath/ath12k/dp_peer.c
+++ b/drivers/net/wireless/ath/ath12k/dp_peer.c
@@ -695,3 +695,55 @@ void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr)
if (rx_stats)
memset(rx_stats, 0, sizeof(*rx_stats));
}
+
+int ath12k_dp_peer_fixup_peer_id(struct ath12k_base *ab,
+ const u8 *peer_addr, u16 peer_id)
+{
+ struct ath12k_dp_link_peer *link_peer;
+ struct ath12k_dp_peer *dp_peer = NULL;
+ struct ath12k_hw_group *ag = ab->ag;
+ struct ath12k_dp_hw *dp_hw = NULL;
+ struct ath12k_hw *ah;
+ int i;
+
+ if (peer_id >= (ATH12K_PEER_ML_ID_VALID | ATH12K_MAX_MLO_PEERS))
+ return -EINVAL;
+
+ for (i = 0; i < ag->num_hw; i++) {
+ ah = ag->ah[i];
+ if (!ah)
+ continue;
+
+ spin_lock_bh(&ah->dp_hw.peer_lock);
+ dp_peer = ath12k_dp_peer_find_by_addr(&ah->dp_hw,
+ (u8 *)peer_addr);
+ if (dp_peer) {
+ dp_hw = &ah->dp_hw;
+ break;
+ }
+ spin_unlock_bh(&ah->dp_hw.peer_lock);
+ }
+
+ if (!dp_peer)
+ return -ENOENT;
+
+ /* dp_hw->peer_lock is held */
+
+ dp_peer->peer_id = peer_id;
+ rcu_assign_pointer(dp_hw->dp_peers[peer_id], dp_peer);
+
+ for (i = 0; i < ATH12K_NUM_MAX_LINKS; i++) {
+ link_peer = rcu_dereference_protected(dp_peer->link_peers[i],
+ lockdep_is_held(&dp_hw->peer_lock));
+ if (link_peer)
+ link_peer->ml_id = peer_id;
+ }
+
+ ath12k_sta_to_ahsta(dp_peer->sta)->ml_peer_id = peer_id;
+
+ spin_unlock_bh(&dp_hw->peer_lock);
+
+ complete(&ah->peer_ml_id_done);
+
+ return 0;
+}
diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h
index f5067e66f1e1..9842671b5475 100644
--- a/drivers/net/wireless/ath/ath12k/dp_peer.h
+++ b/drivers/net/wireless/ath/ath12k/dp_peer.h
@@ -180,4 +180,6 @@ struct ath12k_dp_peer *ath12k_dp_peer_find_by_peerid(struct ath12k_pdev_dp *dp_p
struct ath12k_dp_link_peer *
ath12k_dp_link_peer_find_by_peerid(struct ath12k_pdev_dp *dp_pdev, u16 peer_id);
void ath12k_dp_link_peer_free(struct ath12k_dp_link_peer *peer);
+int ath12k_dp_peer_fixup_peer_id(struct ath12k_base *ab, const u8 *peer_addr,
+ u16 peer_id);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 533109f9d5bd..e4c240f168e3 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -3855,9 +3855,11 @@ static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,
static int ath12k_mac_peer_assoc(struct ath12k *ar,
struct ath12k_wmi_peer_assoc_arg *peer_arg)
{
+ struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
int ret;
reinit_completion(&ar->peer_assoc_done);
+ reinit_completion(&ah->peer_ml_id_done);
ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
if (ret) {
@@ -3872,6 +3874,27 @@ static int ath12k_mac_peer_assoc(struct ath12k *ar,
return -ETIMEDOUT;
}
+ /*
+ * For devices where the firmware allocates the MLD peer ID, the host
+ * learns the real ID only from the MLO_RX_PEER_MAP HTT event, which is
+ * handled in a softirq (BH workqueue) context that cannot take the
+ * wiphy lock. Block here, while still holding the wiphy lock, until
+ * that event has fixed up the ID. This serialises the fixup against
+ * all other wiphy-locked ml_peer_id accesses.
+ *
+ * The firmware sends the event only once, in response to the assoc-link
+ * peer assoc, so block only for that link.
+ */
+ if (!ah->host_alloc_ml_id &&
+ peer_arg->is_assoc &&
+ peer_arg->ml.enabled &&
+ peer_arg->ml.assoc_link &&
+ !wait_for_completion_timeout(&ah->peer_ml_id_done, 1 * HZ)) {
+ ath12k_warn(ar->ab, "failed to get MLO peer map event for %pM vdev %i\n",
+ peer_arg->peer_mac, peer_arg->vdev_id);
+ return -ETIMEDOUT;
+ }
+
return 0;
}
@@ -15332,6 +15355,7 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag,
ah->num_radio = num_pdev_map;
mutex_init(&ah->hw_mutex);
+ init_completion(&ah->peer_ml_id_done);
spin_lock_init(&ah->dp_hw.peer_lock);
INIT_LIST_HEAD(&ah->dp_hw.dp_peers_list);
--
2.25.1
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH ath-current v2 1/8] wifi: ath12k: fix out-of-bounds clear_bit in ath12k_mac_dp_peer_cleanup()
2026-07-20 6:43 ` [PATCH ath-current v2 1/8] wifi: ath12k: fix out-of-bounds clear_bit in ath12k_mac_dp_peer_cleanup() Baochen Qiang
@ 2026-07-23 15:45 ` Jeff Johnson
2026-07-23 15:50 ` Jeff Johnson
0 siblings, 1 reply; 12+ messages in thread
From: Jeff Johnson @ 2026-07-23 15:45 UTC (permalink / raw)
To: Baochen Qiang, Jeff Johnson; +Cc: linux-wireless, ath12k
On 7/19/2026 11:43 PM, Baochen Qiang wrote:
> ath12k_mac_dp_peer_cleanup() clears the ML peer ID slot on the
> free_ml_peer_id_map bitmap by indexing it with dp_peer->peer_id. That is
> wrong: dp_peer->peer_id for an MLO peer always carries the
> ATH12K_PEER_ML_ID_VALID bit (BIT(13)), so clear_bit() is invoked with
> index >= 0x2000, which is far outside the bitmap of ATH12K_MAX_MLO_PEERS
> (256) bits and corrupts memory adjacent to ah->free_ml_peer_id_map. The
> intended bitmap entry also never gets cleared, so subsequent
> ath12k_peer_ml_alloc() calls eventually run out of IDs.
>
> The ID without the VALID bit is what ath12k_peer_ml_alloc() returned and
> is stored in ahsta->ml_peer_id. Use that instead.
>
> While there, also reset ahsta->ml_peer_id to ATH12K_MLO_PEER_ID_INVALID so
> the bitmap and ahsta->ml_peer_id stay in sync;
nit s/;/./
>
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3
>
> Fixes: ee16dcf573d5 ("wifi: ath12k: Define ath12k_dp_peer structure & APIs for create & delete")
> Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath12k/mac.c | 5 ++++-
> 1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 490c134c1f29..b7eba8ea981b 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -1283,8 +1283,11 @@ void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah)
> spin_lock_bh(&dp_hw->peer_lock);
> list_for_each_entry_safe(dp_peer, tmp, &dp_hw->dp_peers_list, list) {
> if (dp_peer->is_mlo) {
> + struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(dp_peer->sta);
> +
> rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
> - clear_bit(dp_peer->peer_id, ah->free_ml_peer_id_map);
> + clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
> + ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
so this now matches the code at the end of ath12k_mac_ml_station_remove() and
in the cleanup section of ath12k_mac_op_sta_state(), so perhaps that should be
refactored into a helper function in the future
> }
>
> list_move(&dp_peer->list, &peers);
>
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH ath-current v2 1/8] wifi: ath12k: fix out-of-bounds clear_bit in ath12k_mac_dp_peer_cleanup()
2026-07-23 15:45 ` Jeff Johnson
@ 2026-07-23 15:50 ` Jeff Johnson
0 siblings, 0 replies; 12+ messages in thread
From: Jeff Johnson @ 2026-07-23 15:50 UTC (permalink / raw)
To: Baochen Qiang, Jeff Johnson; +Cc: linux-wireless, ath12k
On 7/23/2026 8:45 AM, Jeff Johnson wrote:
>> + clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
>> + ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
>
> so this now matches the code at the end of ath12k_mac_ml_station_remove() and
> in the cleanup section of ath12k_mac_op_sta_state(), so perhaps that should be
> refactored into a helper function in the future
which I now see in patch 3/8 :)
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID
2026-07-20 6:43 [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Baochen Qiang
` (7 preceding siblings ...)
2026-07-20 6:43 ` [PATCH ath-current v2 8/8] wifi: ath12k: resolve PENDING ML peer ID from MLO_PEER_MAP HTT event Baochen Qiang
@ 2026-07-23 17:21 ` Jeff Johnson
8 siblings, 0 replies; 12+ messages in thread
From: Jeff Johnson @ 2026-07-23 17:21 UTC (permalink / raw)
To: Baochen Qiang, Jeff Johnson; +Cc: linux-wireless, ath12k
On 7/19/2026 11:43 PM, Baochen Qiang wrote:
> ath12k currently assumes the host allocates the MLD peer ID and passes
> it down to firmware via WMI_PEER_ASSOC_CMDID. This works on QCN9274
> but breaks WCN7850/QCC2072, whose firmware always picks the ID itself
> and reports it back through HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP. As a
> result dp_hw->dp_peers[] is never populated for MLO peers and the data
> path lookup fails. On QCC2072 the firmware additionally crashes on MLO
> disconnect when ATH12K_WMI_FLAG_MLO_PEER_ID_VALID was set in the peer
> assoc command.
>
> Add a host_alloc_ml_id hw_param to branch behavior, defer the
> dp_peers[] publish to the HTT event for firmware-allocated chips, and
> propagate the firmware-assigned ID through the existing host
> bookkeeping when it arrives.
>
> Patch summary:
>
> 1: fix for an out-of-bounds clear_bit() in
> ath12k_mac_dp_peer_cleanup().
> 2: group peer assoc send-and-wait into a helper
> 3: refactor, keep ATH12K_PEER_ML_ID_VALID set in ahsta->ml_peer_id
> so later patches do not have to OR or mask it at every call site;
> 4: parse the HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP message;
> 5: introduce hw_param host_alloc_ml_id, set true on QCN9274 family
> and false on WCN7850/QCC2072;
> 6: on host_alloc_ml_id == false, leave peer_id_valid unset and send
> ml_peer_id == 0 in WMI_PEER_ASSOC_CMDID;
> 7: on host_alloc_ml_id == false, mark ahsta->ml_peer_id and
> dp_peer->peer_id as ATH12K_MLO_PEER_ID_PENDING and skip the
> dp_hw->dp_peers[] publish until the firmware reports the ID;
> 8: in the MLO_RX_PEER_MAP handler, propagate the firmware-assigned
> ID into dp_peer->peer_id, every dp_link_peer in
> dp_peer->link_peers[], and ahsta->ml_peer_id, all under
> dp_hw->peer_lock.
>
> ---
> Changes in v2:
> - patch 5/8: initialize ret before goto err handling in ath12k_mac_allocate()
> - Link to v1: https://lore.kernel.org/r/20260713-ath12k-fw-allocated-ml-peer-id-v1-0-d0a2a1a519eb@oss.qualcomm.com
>
> ---
> Baochen Qiang (8):
> wifi: ath12k: fix out-of-bounds clear_bit in ath12k_mac_dp_peer_cleanup()
> wifi: ath12k: factor out peer assoc send-and-wait into a helper
> wifi: ath12k: keep ATH12K_PEER_ML_ID_VALID set in ath12k_sta::ml_peer_id
> wifi: ath12k: add support for HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP
> wifi: ath12k: introduce host_alloc_ml_id hardware parameter
> wifi: ath12k: do not advertise MLD peer ID for firmware-allocate devices
> wifi: ath12k: defer dp_peer registration when firmware allocates MLD peer ID
> wifi: ath12k: resolve PENDING ML peer ID from MLO_PEER_MAP HTT event
>
> drivers/net/wireless/ath/ath12k/core.c | 2 +
> drivers/net/wireless/ath/ath12k/core.h | 3 +
> drivers/net/wireless/ath/ath12k/dp_htt.c | 49 +++++++++
> drivers/net/wireless/ath/ath12k/dp_htt.h | 12 +++
> drivers/net/wireless/ath/ath12k/dp_peer.c | 75 +++++++++++--
> drivers/net/wireless/ath/ath12k/dp_peer.h | 2 +
> drivers/net/wireless/ath/ath12k/hw.h | 2 +
> drivers/net/wireless/ath/ath12k/mac.c | 165 ++++++++++++++++++++---------
> drivers/net/wireless/ath/ath12k/peer.c | 31 +++++-
> drivers/net/wireless/ath/ath12k/peer.h | 1 +
> drivers/net/wireless/ath/ath12k/wifi7/hw.c | 12 +++
> 11 files changed, 293 insertions(+), 61 deletions(-)
> ---
> base-commit: 951dc0a744e4dc8490935316d3b76e23990bde3c
> change-id: 20260527-ath12k-fw-allocated-ml-peer-id-2b456891157f
>
> Best regards,
This version LGTM other than the one commit text nit I can fix.
Will wait for Ramesh's RB tag to pick it up
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-07-23 17:21 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-20 6:43 [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 1/8] wifi: ath12k: fix out-of-bounds clear_bit in ath12k_mac_dp_peer_cleanup() Baochen Qiang
2026-07-23 15:45 ` Jeff Johnson
2026-07-23 15:50 ` Jeff Johnson
2026-07-20 6:43 ` [PATCH ath-current v2 2/8] wifi: ath12k: factor out peer assoc send-and-wait into a helper Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 3/8] wifi: ath12k: keep ATH12K_PEER_ML_ID_VALID set in ath12k_sta::ml_peer_id Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 4/8] wifi: ath12k: add support for HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 5/8] wifi: ath12k: introduce host_alloc_ml_id hardware parameter Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 6/8] wifi: ath12k: do not advertise MLD peer ID for firmware-allocate devices Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 7/8] wifi: ath12k: defer dp_peer registration when firmware allocates MLD peer ID Baochen Qiang
2026-07-20 6:43 ` [PATCH ath-current v2 8/8] wifi: ath12k: resolve PENDING ML peer ID from MLO_PEER_MAP HTT event Baochen Qiang
2026-07-23 17:21 ` [PATCH ath-current v2 0/8] wifi: ath12k: support firmware-allocated MLD peer ID Jeff Johnson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox