Wi-Fi 8 link peers can keep the firmware peer id invalid while the REO queue LUT is indexed by the host-allocated global dp_peer id. If RX TID setup uses only the link peer id, station add can fail before REOQ LUT programming. Thread the resolved dp_peer through peer setup and RX TID setup, prefer the global dp_peer id on global-peer-id devices, and keep the pending REO update cleanup keyed by the same id. Cache the Wi-Fi 8 dp_peer on ath12k_sta with RCU accessors so later RX TID operations can find the global peer directly, and clear it during peer delete. Preserve the Wi-Fi 8 stale saved link descriptor guard too. Signed-off-by: Pradeep Kumar Chitrapu --- drivers/net/wireless/ath/ath12k/core.h | 2 + drivers/net/wireless/ath/ath12k/dp.c | 10 ++- drivers/net/wireless/ath/ath12k/dp.h | 4 +- drivers/net/wireless/ath/ath12k/dp_cmn.h | 6 ++ drivers/net/wireless/ath/ath12k/dp_peer.c | 14 +++ drivers/net/wireless/ath/ath12k/dp_peer.h | 4 +- drivers/net/wireless/ath/ath12k/dp_rx.c | 108 +++++++++++++++++++----- drivers/net/wireless/ath/ath12k/dp_rx.h | 8 +- drivers/net/wireless/ath/ath12k/mac.c | 15 +++- drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c | 16 +++- drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c | 15 +++- 11 files changed, 169 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 337cb4b1c386..1cd388f613f1 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -537,6 +537,8 @@ struct ath12k_sta { u8 assoc_link_id; u16 ml_peer_id; u16 dp_peer_id; + /* Opaque RCU pointer to ath12k_dp_peer */ + void __rcu *dp_peer; bool is_mlo; u16 free_logical_link_idx_map; diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c index 4ab5daccd4f2..496eabe61119 100644 --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c @@ -44,7 +44,8 @@ void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr) spin_unlock_bh(&dp->dp_lock); } -int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr) +int ath12k_dp_peer_setup(struct ath12k *ar, struct ath12k_dp_peer *dp_peer, + int vdev_id, const u8 *addr) { struct ath12k_base *ab = ar->ab; struct ath12k_dp_link_peer *peer; @@ -52,6 +53,9 @@ int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr) int ret = 0, tid; struct ath12k_dp *dp = ath12k_ab_to_dp(ab); + if (!dp_peer) + return -ENOENT; + /* NOTE: reo_dest ring id starts from 1 unlike mac_id which starts from 0 */ reo_dest = ar->dp.mac_id + 1; ret = ath12k_wmi_set_peer_param(ar, addr, vdev_id, @@ -65,8 +69,8 @@ int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr) } for (tid = 0; tid <= IEEE80211_NUM_TIDS; tid++) { - ret = ath12k_dp_rx_peer_tid_setup(ar, addr, vdev_id, tid, 1, 0, - HAL_PN_TYPE_NONE); + ret = ath12k_dp_rx_peer_tid_setup(ar, dp_peer, addr, vdev_id, + tid, 1, 0, HAL_PN_TYPE_NONE); if (ret) { ath12k_warn(ab, "failed to setup rxd tid queue for tid %d: %d\n", tid, ret); diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h index 9dba68f78808..36e2704f309b 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -17,6 +17,7 @@ struct ath12k_base; struct ath12k_hw; struct ath12k_dp_link_peer; +struct ath12k_dp_peer; struct ath12k_dp; struct ath12k_vif; struct ath12k_link_vif; @@ -969,7 +970,8 @@ static inline void ath12k_dp_arch_dp_link_vif_configure(struct ath12k_dp *dp, void ath12k_dp_partner_cc_init(struct ath12k_base *ab); int ath12k_dp_pdev_alloc(struct ath12k_base *ab); void ath12k_dp_pdev_pre_alloc(struct ath12k *ar); -int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr); +int ath12k_dp_peer_setup(struct ath12k *ar, struct ath12k_dp_peer *dp_peer, + int vdev_id, const u8 *addr); void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr); void ath12k_dp_srng_cleanup(struct ath12k_base *ab, struct dp_srng *ring); int ath12k_dp_srng_setup(struct ath12k_base *ab, struct dp_srng *ring, diff --git a/drivers/net/wireless/ath/ath12k/dp_cmn.h b/drivers/net/wireless/ath/ath12k/dp_cmn.h index 7075963251d2..79a3ad05900c 100644 --- a/drivers/net/wireless/ath/ath12k/dp_cmn.h +++ b/drivers/net/wireless/ath/ath12k/dp_cmn.h @@ -12,6 +12,9 @@ #define ATH12K_DP_REO_DST_RING_MAX MIN(NR_CPUS, 5) struct ath12k_hw_group; +struct ath12k_dp_peer; +struct ath12k_sta; +struct wiphy; /* * ML Peer IDs start from 8192, assuming max SLO clients count 1536, @@ -145,4 +148,7 @@ ath12k_dp_link_peer_get_sta_rate_info_stats(struct ath12k_dp *dp, const u8 *addr void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr); u16 ath12k_dp_peer_get_peer_id(struct ath12k_dp_hw *dp_hw, u8 *addr); u16 ath12k_dp_peer_get_sta_id(struct ath12k_dp_hw *dp_hw, u8 *addr); +struct ath12k_dp_peer * +ath12k_sta_get_dp_peer_wiphy_locked(struct wiphy *wiphy, + struct ath12k_sta *ahsta); #endif diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c index 58b8b3ab5f4b..e4e2eb0719e8 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.c +++ b/drivers/net/wireless/ath/ath12k/dp_peer.c @@ -522,6 +522,11 @@ int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw, * For WiFi7, peer_id is assigned by firmware via the HTT peer map * event before this point. */ + if (dp->global_peer_id_supported && dp_peer->is_mlo) { + peer->ml_id = dp_peer->peer_id; + peer->mlo = true; + } + if (peer->peer_id != ATH12K_MLO_PEER_ID_INVALID) { peerid_index = ath12k_dp_peer_get_peerid_index(dp, peer->peer_id); rcu_assign_pointer(dp_hw->dp_peers[peerid_index], dp_peer); @@ -655,6 +660,15 @@ void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr) memset(rx_stats, 0, sizeof(*rx_stats)); } +struct ath12k_dp_peer * +ath12k_sta_get_dp_peer_wiphy_locked(struct wiphy *wiphy, + struct ath12k_sta *ahsta) +{ + lockdep_assert_wiphy(wiphy); + + return wiphy_dereference(wiphy, ahsta->dp_peer); +} + /** * ath12k_dp_peer_cleanup_all() - Clean up all datapath link peers for a radio. * @ar: radio instance whose peers to clean up diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h index 5ef14ed24113..19f6a47acbb1 100644 --- a/drivers/net/wireless/ath/ath12k/dp_peer.h +++ b/drivers/net/wireless/ath/ath12k/dp_peer.h @@ -159,8 +159,8 @@ struct ath12k_dp_peer { /* Info used in MMIC verification of * RX fragments */ struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; 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]; + struct ath12k_reoq_buf reoq_bufs[ATH12K_MAX_TIDS]; + struct ath12k_dp_rx_tid rx_tid[ATH12K_MAX_TIDS]; struct ath12k_dp_peer_ext_ctx *peer_ext_ctx; bool is_vdev_peer; diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index 47a7ec58446a..14755f653f38 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -13,6 +13,7 @@ #include "hw.h" #include "dp_rx.h" #include "dp_tx.h" +#include "dp_cmn.h" #include "peer.h" #include "dp_mon.h" #include "debugfs_htt_stats.h" @@ -529,6 +530,50 @@ static int ath12k_dp_rx_tid_delete_handler(struct ath12k_base *ab, return ath12k_dp_arch_rx_tid_delete_handler(dp, rx_tid); } +static bool ath12k_dp_rx_peer_id_valid(u16 peer_id) +{ + return peer_id != ATH12K_MLO_PEER_ID_INVALID; +} + +static u16 ath12k_dp_rx_tid_peer_id(struct ath12k_dp *dp, + struct ath12k_dp_peer *dp_peer, + struct ath12k_dp_link_peer *peer) +{ + if (dp->global_peer_id_supported) { + if (dp_peer && ath12k_dp_rx_peer_id_valid(dp_peer->peer_id)) + return dp_peer->peer_id; + + if (peer->dp_peer && + ath12k_dp_rx_peer_id_valid(peer->dp_peer->peer_id)) + return peer->dp_peer->peer_id; + + if (peer->mlo && ath12k_dp_rx_peer_id_valid(peer->ml_id)) + return peer->ml_id; + } + + if (peer->peer_id != ATH12K_MLO_PEER_ID_INVALID) + return peer->peer_id; + + if (dp_peer && ath12k_dp_rx_peer_id_valid(dp_peer->peer_id)) + return dp_peer->peer_id; + + if (peer->dp_peer && ath12k_dp_rx_peer_id_valid(peer->dp_peer->peer_id)) + return peer->dp_peer->peer_id; + + return ATH12K_MLO_PEER_ID_INVALID; +} + +static u16 ath12k_dp_rx_reo_peer_id(struct ath12k_dp *dp, + struct ath12k_dp_peer *dp_peer, + struct ath12k_dp_link_peer *peer) +{ + if (!dp->global_peer_id_supported && peer->mlo && + peer->ml_id != ATH12K_MLO_PEER_ID_INVALID) + return peer->ml_id; + + return ath12k_dp_rx_tid_peer_id(dp, dp_peer, peer); +} + void ath12k_dp_mark_tid_as_inactive(struct ath12k_dp *dp, int peer_id, u8 tid) { struct dp_reo_update_rx_queue_elem *elem; @@ -573,6 +618,7 @@ void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_dp_link_peer } static int ath12k_dp_prepare_reo_update_elem(struct ath12k_dp *dp, + struct ath12k_dp_peer *dp_peer, struct ath12k_dp_link_peer *peer, struct ath12k_dp_rx_tid *rx_tid) { @@ -587,9 +633,11 @@ static int ath12k_dp_prepare_reo_update_elem(struct ath12k_dp *dp, if (!elem) return -ENOMEM; - elem->peer_id = peer->peer_id; - elem->is_ml_peer = peer->mlo; - elem->ml_peer_id = peer->ml_id; + elem->peer_id = ath12k_dp_rx_tid_peer_id(dp, dp_peer, peer); + elem->is_ml_peer = !dp->global_peer_id_supported && peer->mlo && + peer->ml_id != ATH12K_MLO_PEER_ID_INVALID; + elem->ml_peer_id = elem->is_ml_peer ? peer->ml_id : + ATH12K_MLO_PEER_ID_INVALID; ath12k_dp_init_rx_tid_rxq(&elem->rx_tid, rx_tid, (peer->rx_tid_active_bitmask & (1 << rx_tid->tid))); @@ -601,8 +649,10 @@ static int ath12k_dp_prepare_reo_update_elem(struct ath12k_dp *dp, return 0; } -int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id, - u8 tid, u32 ba_win_sz, u16 ssn, +int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, + struct ath12k_dp_peer *dp_peer, + const u8 *peer_mac, int vdev_id, u8 tid, + u32 ba_win_sz, u16 ssn, enum hal_pn_type pn_type) { struct ath12k_base *ab = ar->ab; @@ -610,17 +660,27 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ struct ath12k_dp_link_peer *peer; struct ath12k_dp_rx_tid *rx_tid; dma_addr_t paddr_aligned; + u16 reo_peer_id; int ret; spin_lock_bh(&dp->dp_lock); peer = ath12k_dp_link_peer_find_by_vdev_and_addr(dp, vdev_id, peer_mac); - if (!peer || !peer->dp_peer) { + if (!peer) { spin_unlock_bh(&dp->dp_lock); ath12k_warn(ab, "failed to find the peer to set up rx tid\n"); return -ENOENT; } + if (!dp_peer) + dp_peer = peer->dp_peer; + + if (!dp_peer) { + spin_unlock_bh(&dp->dp_lock); + ath12k_warn(ab, "failed to find dp peer to set up rx tid\n"); + return -ENOENT; + } + if (ab->hw_params->dp_primary_link_only && !peer->primary_link) { spin_unlock_bh(&dp->dp_lock); @@ -634,14 +694,22 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ return -EINVAL; } - if (peer->peer_id > DP_MAX_PEER_ID || tid > IEEE80211_NUM_TIDS) { - ath12k_warn(ab, "peer id of peer %d or tid %d doesn't allow reoq setup\n", - peer->peer_id, tid); + reo_peer_id = ath12k_dp_rx_reo_peer_id(dp, dp_peer, peer); + + if ((reo_peer_id & ~ATH12K_PEER_ML_ID_VALID) > DP_MAX_PEER_ID || + tid > IEEE80211_NUM_TIDS) { + ath12k_warn(ab, + "reo peer id %d or tid %d doesn't allow reoq setup global %d dp_peer_id %u link_dp_peer_id %u link_peer_id %u ml_id %u mlo %d primary %d\n", + reo_peer_id, tid, dp->global_peer_id_supported, + dp_peer ? dp_peer->peer_id : ATH12K_MLO_PEER_ID_INVALID, + peer->dp_peer ? peer->dp_peer->peer_id : + ATH12K_MLO_PEER_ID_INVALID, + peer->peer_id, peer->ml_id, peer->mlo, peer->primary_link); spin_unlock_bh(&dp->dp_lock); return -EINVAL; } - rx_tid = &peer->dp_peer->rx_tid[tid]; + rx_tid = &dp_peer->rx_tid[tid]; /* Update the tid queue if it is already setup */ if (peer->rx_tid_active_bitmask & (1 << tid)) { ret = ath12k_dp_arch_peer_rx_tid_reo_update(dp, peer, rx_tid, @@ -672,7 +740,7 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ rx_tid->ba_win_sz = ba_win_sz; - ret = ath12k_dp_arch_rx_assign_reoq(dp, peer->dp_peer, rx_tid, ssn, pn_type); + ret = ath12k_dp_arch_rx_assign_reoq(dp, dp_peer, rx_tid, ssn, pn_type); if (ret) { spin_unlock_bh(&dp->dp_lock); ath12k_warn(ab, "failed to assign reoq buf for rx tid %u\n", tid); @@ -686,7 +754,7 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ * allocating during tid delete is that, if any alloc fail in update_rxq_list * we may not be able to delete the tid vaddr/paddr and may lead to leak */ - ret = ath12k_dp_prepare_reo_update_elem(dp, peer, rx_tid); + ret = ath12k_dp_prepare_reo_update_elem(dp, dp_peer, peer, rx_tid); if (ret) { ath12k_warn(ab, "failed to alloc update_rxq_list for rx tid %u\n", tid); ath12k_dp_rx_tid_cleanup(ab, &rx_tid->qbuf); @@ -699,12 +767,8 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ /* Update the REO queue LUT at the corresponding peer id * and tid with qaddr. */ - if (peer->mlo) - ath12k_dp_arch_peer_rx_tid_qref_setup(dp, peer->ml_id, tid, - paddr_aligned); - else - ath12k_dp_arch_peer_rx_tid_qref_setup(dp, peer->peer_id, tid, - paddr_aligned); + ath12k_dp_arch_peer_rx_tid_qref_setup(dp, reo_peer_id, tid, + paddr_aligned); spin_unlock_bh(&dp->dp_lock); } else { @@ -724,6 +788,7 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar, struct ath12k_base *ab = ar->ab; struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta); struct ath12k_link_sta *arsta; + struct ath12k_dp_peer *dp_peer; int vdev_id; int ret; @@ -736,7 +801,12 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar, vdev_id = arsta->arvif->vdev_id; - ret = ath12k_dp_rx_peer_tid_setup(ar, arsta->addr, vdev_id, + dp_peer = ath12k_sta_get_dp_peer_wiphy_locked(ath12k_ar_to_hw(ar)->wiphy, + ahsta); + if (!dp_peer) + return -ENOENT; + + ret = ath12k_dp_rx_peer_tid_setup(ar, dp_peer, arsta->addr, vdev_id, params->tid, params->buf_size, params->ssn, arsta->ahsta->pn_type); if (ret) diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h index f523ac48747f..a76b79549924 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.h +++ b/drivers/net/wireless/ath/ath12k/dp_rx.h @@ -10,8 +10,10 @@ #include "debug.h" #define DP_MAX_NWIFI_HDR_LEN 30 +#define ATH12K_MAX_TIDS (IEEE80211_NUM_TIDS + 1) struct hal_reo_status; +struct ath12k_dp_peer; struct ath12k_reoq_buf { void *vaddr; @@ -232,8 +234,10 @@ int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif, void ath12k_dp_rx_peer_tid_cleanup(struct ath12k *ar, struct ath12k_dp_link_peer *peer); void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar, struct ath12k_dp_link_peer *peer, u8 tid); -int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_id, - u8 tid, u32 ba_win_sz, u16 ssn, +int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, + struct ath12k_dp_peer *dp_peer, + const u8 *peer_mac, int vdev_id, u8 tid, + u32 ba_win_sz, u16 ssn, enum hal_pn_type pn_type); int ath12k_dp_rxdma_ring_buf_setup(struct ath12k_base *ab, struct dp_rxdma_ring *rx_ring); diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 77343469ccca..37c17a97d5aa 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -7177,6 +7177,7 @@ static int ath12k_mac_station_add(struct ath12k *ar, struct ath12k_wmi_peer_create_arg peer_param = {}; int ret; struct ath12k_link_sta *temp_arsta; + struct ath12k_dp_peer *dp_peer; lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy); @@ -7235,7 +7236,19 @@ static int ath12k_mac_station_add(struct ath12k *ar, } } - ret = ath12k_dp_peer_setup(ar, arvif->vdev_id, arsta->addr); + dp_peer = ath12k_sta_get_dp_peer_wiphy_locked(ath12k_ar_to_hw(ar)->wiphy, + arsta->ahsta); + if (!dp_peer || dp_peer->peer_id == ATH12K_MLO_PEER_ID_INVALID) { + spin_lock_bh(&ar->ah->dp_hw.peer_lock); + dp_peer = ath12k_dp_peer_find_by_addr_and_sta(&ar->ah->dp_hw, + sta->addr, sta); + if (!dp_peer) + dp_peer = ath12k_dp_peer_find_by_addr_and_sta(&ar->ah->dp_hw, + arsta->addr, + sta); + spin_unlock_bh(&ar->ah->dp_hw.peer_lock); + } + ret = ath12k_dp_peer_setup(ar, dp_peer, arvif->vdev_id, arsta->addr); if (ret) { ath12k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n", arsta->addr, arvif->vdev_id, ret); diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c b/drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c index a89086ca15c1..2006a862feb2 100644 --- a/drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c +++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_peer.c @@ -319,7 +319,8 @@ int ath12k_wifi8_dp_peer_create(struct ath12k_hw *ah, u8 *addr, struct ath12k_dp_hw *dp_hw = &ah->dp_hw; struct ath12k_sta *ahsta = NULL; - ahsta = ath12k_sta_to_ahsta(params->sta); + if (params->sta) + ahsta = ath12k_sta_to_ahsta(params->sta); spin_lock_bh(&dp_hw->peer_lock); dp_peer = ath12k_dp_peer_find_by_addr(dp_hw, addr); @@ -375,7 +376,10 @@ int ath12k_wifi8_dp_peer_create(struct ath12k_hw *ah, u8 *addr, dp_peer->hw_link_id = params->hw_link_id; } else { dp_peer->assoc_hw_link_id = params->hw_link_id; - ahsta->dp_peer_id = dp_peer->peer_id; + if (ahsta) { + ahsta->dp_peer_id = dp_peer->peer_id; + rcu_assign_pointer(ahsta->dp_peer, dp_peer); + } } dp_peer->is_sta_bss_peer = params->is_sta_bss_peer; @@ -410,15 +414,19 @@ void ath12k_wifi8_dp_peer_delete(struct ath12k_dp *dp, struct ath12k_hw *ah, u8 struct ath12k_base *central_ab = NULL; struct ath12k_dp_wifi8 *dp_wifi8 = NULL; struct hal_srng *srng = NULL; + struct ath12k_sta *ahsta; int i, ret; dp_hw_grp_wifi8 = ath12k_get_dp_hw_group_wifi8(dp->dp_hw_grp); spin_lock_bh(&dp_hw->peer_lock); - if (sta) + if (sta) { + ahsta = ath12k_sta_to_ahsta(sta); + rcu_assign_pointer(ahsta->dp_peer, NULL); dp_peer = ath12k_dp_peer_find_by_addr_and_sta(dp_hw, addr, sta); - else + } else { dp_peer = ath12k_dp_peer_find_by_addr(dp_hw, addr); + } if (!dp_peer) { spin_unlock_bh(&dp_hw->peer_lock); diff --git a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c index 0b8a9d32e125..c74f070c0d88 100644 --- a/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/wifi8/dp_rx.c @@ -364,11 +364,18 @@ void ath12k_wifi8_dp_rx_peer_tid_delete(struct ath12k_base *ab, u8 tid) { struct ath12k_dp *dp = ath12k_ab_to_dp(ab); + u16 peer_id = peer->peer_id; if (!(peer->rx_tid_active_bitmask & BIT(tid))) return; - ath12k_dp_mark_tid_as_inactive(dp, peer->peer_id, tid); + if (peer_id == ATH12K_MLO_PEER_ID_INVALID && peer->dp_peer) + peer_id = peer->dp_peer->peer_id; + + if (peer_id == ATH12K_MLO_PEER_ID_INVALID) + return; + + ath12k_dp_mark_tid_as_inactive(dp, peer_id, tid); ath12k_dp_rx_process_reo_cmd_update_rx_queue_list(dp); } @@ -517,6 +524,11 @@ void ath12k_wifi8_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid, lockdep_assert_held(&dp->dp_lock); if (rx_tid->dst_ring_desc) { + if ((unsigned long)rx_tid->dst_ring_desc < PAGE_SIZE) { + rx_tid->dst_ring_desc = NULL; + goto clear; + } + if (rel_link_desc) { buf_addr_info = &rx_tid->dst_ring_desc->buf_addr_info; ath12k_wifi8_dp_rx_link_desc_return(dp, buf_addr_info, @@ -527,6 +539,7 @@ void ath12k_wifi8_dp_rx_frags_cleanup(struct ath12k_dp_rx_tid *rx_tid, rx_tid->dst_ring_desc = NULL; } +clear: rx_tid->cur_sn = 0; rx_tid->last_frag_no = 0; rx_tid->rx_frag_bitmap = 0; -- 2.43.0