[PATCH ath-next v4 11/11] wifi: ath12k: use link_id_map to resolve RX link id for all devices
Rameshkumar Sundaram
rameshkumar.sundaram at oss.qualcomm.com
Mon Nov 9 22:07:11 PST 2026
On 11/2/2026 12:08 PM, Baochen Qiang wrote:
> Commit a2fe9dc70f3b ("wifi: ath12k: Fix low MLO RX throughput on
> WCN7850") added a set_rx_link_id() op so that each device could resolve
> the RX link id in its own way: QCN9274/IPQ5332 index
> dp_peer->link_id_map[] with the hw_link_id, while WCN7850/QCC2072 walk
> dp_peer->link_peers[] and match by peer_id, tracked with a link_peers_map
> bitmap.
>
> Now that ath12k_skb_rxcb::drv_link_id carries the driver link id for all
> devices (the hw_link_id on QCN9274/IPQ5332 and the logical link id on
> WCN7850/QCC2072) and ath12k_dp_peer::link_id_map maps it to the IEEE80211
> link id, the RX path can resolve the link id uniformly.
>
> Revert the set_rx_link_id() machinery and the link_peers_map bitmap, and
> derive the link id directly from link_id_map[drv_link_id] in
> ath12k_dp_rx_deliver_msdu() for all devices. The NULL dp_peer guard added
> to ath12k_mac_peer_cleanup_all() is kept as it is an independent fix.
>
Fixes: a2fe9dc70f3b ("wifi: ath12k: Fix low MLO RX throughput on
WCN7850") ??
> Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3
> Tested-on: QCC2072 hw1.0 PCI WLAN.COL.1.0.c2-00068-QCACOLSWPL_V1_TO_SILICONZ-1
>
> Signed-off-by: Baochen Qiang <baochen.qiang at oss.qualcomm.com>
> ---
> drivers/net/wireless/ath/ath12k/dp_peer.c | 4 ----
> drivers/net/wireless/ath/ath12k/dp_peer.h | 1 -
> drivers/net/wireless/ath/ath12k/dp_rx.c | 8 ++-----
> drivers/net/wireless/ath/ath12k/hw.h | 18 ----------------
> drivers/net/wireless/ath/ath12k/mac.c | 2 --
> drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c | 30 ---------------------------
> drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h | 6 ------
> drivers/net/wireless/ath/ath12k/wifi7/hw.c | 3 ---
> 8 files changed, 2 insertions(+), 70 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c
> index ee3cdd7ca460..ff88c694e1e3 100644
> --- a/drivers/net/wireless/ath/ath12k/dp_peer.c
> +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c
> @@ -658,8 +658,6 @@ int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw,
> peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id);
>
> rcu_assign_pointer(dp_peer->link_peers[peer->link_id], peer);
> - WRITE_ONCE(dp_peer->link_peers_map,
> - READ_ONCE(dp_peer->link_peers_map) | BIT(peer->link_id));
>
> rcu_assign_pointer(dp_hw->dp_peers[peerid_index], dp_peer);
>
> @@ -728,8 +726,6 @@ void ath12k_dp_link_peer_unassign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_
> peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id);
>
> rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL);
> - WRITE_ONCE(dp_peer->link_peers_map,
> - READ_ONCE(dp_peer->link_peers_map) & ~BIT(peer->link_id));
>
> rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL);
>
> diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h
> index c2d060de88ea..2ac4c6c6d535 100644
> --- a/drivers/net/wireless/ath/ath12k/dp_peer.h
> +++ b/drivers/net/wireless/ath/ath12k/dp_peer.h
> @@ -159,7 +159,6 @@ struct ath12k_dp_peer {
>
> /* Info used in MMIC verification of * RX fragments */
> struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
> - unsigned long link_peers_map;
> struct ath12k_dp_link_peer __rcu *link_peers[ATH12K_NUM_MAX_LINKS];
> struct ath12k_reoq_buf reoq_bufs[IEEE80211_NUM_TIDS + 1];
> struct ath12k_dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
> diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
> index f11810c6e0d4..52838ade1b1d 100644
> --- a/drivers/net/wireless/ath/ath12k/dp_rx.c
> +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
> @@ -1370,13 +1370,9 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc
>
> if (pubsta) {
> if (pubsta->valid_links) {
> - int link_id =
> - ath12k_hw_get_rx_link_id(dp->hw_params, peer,
> - rxcb, status);
> + int link_id = peer->link_id_map[rxcb->drv_link_id];
>
> - if (link_id >= 0)
> - link_pubsta =
> - rcu_dereference(pubsta->link[link_id]);
> + link_pubsta = rcu_dereference(pubsta->link[link_id]);
> } else {
> link_pubsta = &pubsta->deflink;
> }
> diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h
> index 106d858efc44..3a7d1959f19f 100644
> --- a/drivers/net/wireless/ath/ath12k/hw.h
> +++ b/drivers/net/wireless/ath/ath12k/hw.h
> @@ -13,10 +13,6 @@
> #include "wmi.h"
> #include "hal.h"
>
> -struct ath12k_dp_peer;
> -struct ath12k_skb_rxcb;
> -struct ieee80211_rx_status;
> -
> /* Target configuration defines */
>
> /* Num VDEVS per radio */
> @@ -255,9 +251,6 @@ struct ath12k_hw_ops {
> bool (*dp_srng_is_tx_comp_ring)(int ring_num);
> bool (*is_frame_link_agnostic)(struct ath12k_link_vif *arvif,
> struct ieee80211_mgmt *mgmt);
> - int (*get_rx_link_id)(struct ath12k_dp_peer *dp_peer,
> - struct ath12k_skb_rxcb *rxcb,
> - struct ieee80211_rx_status *status);
> };
>
> static inline
> @@ -288,17 +281,6 @@ static inline int ath12k_hw_mac_id_to_srng_id(const struct ath12k_hw_params *hw,
> return 0;
> }
>
> -static inline int ath12k_hw_get_rx_link_id(const struct ath12k_hw_params *hw,
> - struct ath12k_dp_peer *dp_peer,
> - struct ath12k_skb_rxcb *rxcb,
> - struct ieee80211_rx_status *status)
> -{
> - if (hw->hw_ops->get_rx_link_id)
> - return hw->hw_ops->get_rx_link_id(dp_peer, rxcb, status);
> -
> - return -1;
> -}
> -
> struct ath12k_fw_ie {
> __le32 id;
> __le32 len;
> diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
> index 01c048046290..4ac31cb9a5dc 100644
> --- a/drivers/net/wireless/ath/ath12k/mac.c
> +++ b/drivers/net/wireless/ath/ath12k/mac.c
> @@ -1241,8 +1241,6 @@ void ath12k_mac_peer_cleanup_all(struct ath12k *ar)
> if (dp_peer) {
> peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id);
> rcu_assign_pointer(dp_peer->link_peers[peer->link_id], NULL);
> - WRITE_ONCE(dp_peer->link_peers_map,
> - READ_ONCE(dp_peer->link_peers_map) & ~BIT(peer->link_id));
> rcu_assign_pointer(dp_hw->dp_peers[peerid_index], NULL);
> }
> spin_unlock_bh(&dp_hw->peer_lock);
> diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
> index 4132578085cc..473887ed4bb1 100644
> --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
> +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.c
> @@ -2374,33 +2374,3 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
>
> return tlv_tag == HAL_RX_MPDU_START;
> }
> -
> -int
> -ath12k_wifi7_dp_rx_get_link_id_qcn9274(struct ath12k_dp_peer *dp_peer,
> - struct ath12k_skb_rxcb *rxcb,
> - struct ieee80211_rx_status *status)
> -{
> - return dp_peer->link_id_map[rxcb->drv_link_id];
> -}
> -
> -int
> -ath12k_wifi7_dp_rx_get_link_id_wcn7850(struct ath12k_dp_peer *dp_peer,
> - struct ath12k_skb_rxcb *rxcb,
> - struct ieee80211_rx_status *status)
> -{
> - struct ath12k_dp_link_peer *link_peer;
> - unsigned long links_map;
> - int i;
> -
> - RCU_LOCKDEP_WARN(!rcu_read_lock_held(),
> - "ath12k set rx link id called without rcu lock");
> -
> - links_map = READ_ONCE(dp_peer->link_peers_map);
> - for_each_set_bit(i, &links_map, ATH12K_NUM_MAX_LINKS) {
> - link_peer = rcu_dereference(dp_peer->link_peers[i]);
> - if (link_peer && link_peer->peer_id == rxcb->peer_id)
> - return link_peer->link_id;
> - }
> -
> - return -1;
> -}
> diff --git a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h
> index 8a16fb3dd005..3da80da19ced 100644
> --- a/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h
> +++ b/drivers/net/wireless/ath/ath12k/wifi7/dp_rx.h
> @@ -59,10 +59,4 @@ ath12k_wifi7_dp_rxdesc_mpdu_valid(struct ath12k_base *ab,
> struct hal_rx_desc *rx_desc);
> int ath12k_wifi7_dp_rx_tid_delete_handler(struct ath12k_base *ab,
> struct ath12k_dp_rx_tid_rxq *rx_tid);
> -int ath12k_wifi7_dp_rx_get_link_id_qcn9274(struct ath12k_dp_peer *dp_peer,
> - struct ath12k_skb_rxcb *rxcb,
> - struct ieee80211_rx_status *status);
> -int ath12k_wifi7_dp_rx_get_link_id_wcn7850(struct ath12k_dp_peer *dp_peer,
> - struct ath12k_skb_rxcb *rxcb,
> - struct ieee80211_rx_status *status);
> #endif
> diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> index b073282e5525..080ead233106 100644
> --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
> @@ -159,7 +159,6 @@ static const struct ath12k_hw_ops qcn9274_ops = {
> .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_qcn9274,
> .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_qcn9274,
> .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_qcn9274,
> - .get_rx_link_id = ath12k_wifi7_dp_rx_get_link_id_qcn9274,
> };
>
> static const struct ath12k_hw_ops wcn7850_ops = {
> @@ -170,7 +169,6 @@ static const struct ath12k_hw_ops wcn7850_ops = {
> .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850,
> .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850,
> .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850,
> - .get_rx_link_id = ath12k_wifi7_dp_rx_get_link_id_wcn7850,
> };
>
> static const struct ath12k_hw_ops qcc2072_ops = {
> @@ -181,7 +179,6 @@ static const struct ath12k_hw_ops qcc2072_ops = {
> .get_ring_selector = ath12k_wifi7_hw_get_ring_selector_wcn7850,
> .dp_srng_is_tx_comp_ring = ath12k_wifi7_dp_srng_is_comp_ring_wcn7850,
> .is_frame_link_agnostic = ath12k_wifi7_is_frame_link_agnostic_wcn7850,
> - .get_rx_link_id = ath12k_wifi7_dp_rx_get_link_id_wcn7850,
> };
>
> #define ATH12K_TX_RING_MASK_0 0x1
>
--
Ramesh
More information about the ath12k
mailing list