From 6c058117bdd85caa6ad5e4e842e1cc869bd478da Mon Sep 17 00:00:00 2001 From: P Praneesh Date: Sun, 19 Mar 2023 13:19:02 +0530 Subject: [PATCH] ath12k: Add framework to use different hashmap for MLO/NON-MLO peers Currently driver specifies the same rx hash value in HAL_REO1_DEST_RING_CTRL_IX_2 and HAL_REO1_DEST_RING_CTRL_IX_3 registers. Based on this value, driver's rx reo destination rings are utilised by the HW. Using same rx ring mask across the ML and non ML peer degrades the performance. To handle both type of peers, adding framework to optimise the performance of a system that includes both ML and Non ML peers. For non ML peers, value written in IX2 registers are used and for ML peers, value wirtten in IX3 registers are used. Default routing configuration inside the ath12k_dp_peer_setup() doesnt help to detect the ML peer due to sta->valid_links missed to have other links in the first link STA state change from NONE to AUTH state. so it failed to configure ATH12K_DP_LMAC_PEER_ID_MLO instead it configured as ATH12K_DP_LMAC_PEER_ID_LEGACY. which lead to fetch the ix2 register for REO indication. so low throughput seen in ML KPI testcases. So fix this issue by configuring the same peer default routing configuration again when the STA move from AUTH to ASSOC state. Now we able to get the correct valid links from sta->valid_links. With this change, Observed 400Mbps improvement with SLO clients. Signed-off-by: P Praneesh --- drivers/net/wireless/ath/ath12k/dp.c | 39 +++++++++++++++++++++++---- drivers/net/wireless/ath/ath12k/dp.h | 3 ++- drivers/net/wireless/ath/ath12k/mac.c | 2 +- 3 files changed, 37 insertions(+), 7 deletions(-) --- a/drivers/net/wireless/ath/ath12k/dp.c +++ b/drivers/net/wireless/ath/ath12k/dp.c @@ -14,6 +14,10 @@ #include "peer.h" #include "dp_mon.h" +#define ATH12K_DP_LMAC_PEER_ID_LEGACY 2 +#define ATH12K_DP_LMAC_PEER_ID_MLO 3 +#define ATH12K_DP_PEER_ROUTING_LMAC_ID_MASK GENMASK(7,6) + static void ath12k_dp_htt_htc_tx_complete(struct ath12k_base *ab, struct sk_buff *skb) { @@ -47,30 +51,55 @@ void ath12k_dp_peer_cleanup(struct ath12 spin_unlock_bh(&ab->base_lock); } -int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr) +int ath12k_dp_peer_default_route_setup(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta) { struct ath12k_base *ab = ar->ab; - struct ath12k_peer *peer; - u32 reo_dest; - int ret = 0, tid; + struct ieee80211_sta *sta; + u32 reo_dest, param_value; + u32 lmac_peer_routing_id = ATH12K_DP_LMAC_PEER_ID_LEGACY; + int ret; - /* TODO setup resources only for primary link peer for ML case */ + sta = container_of((void *)arsta->ahsta, struct ieee80211_sta, drv_priv); /* 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, - WMI_PEER_SET_DEFAULT_ROUTING, - DP_RX_HASH_ENABLE | (reo_dest << 1)); + param_value = (reo_dest << 1 | DP_RX_HASH_ENABLE); + + /* For MLO supported peers and it has multi link capablity, use MLO conf */ + if (hweight16(sta->valid_links) > 1) + lmac_peer_routing_id = ATH12K_DP_LMAC_PEER_ID_MLO; + param_value |= FIELD_PREP(ATH12K_DP_PEER_ROUTING_LMAC_ID_MASK, + lmac_peer_routing_id); + + ret = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id, + WMI_PEER_SET_DEFAULT_ROUTING, param_value); if (ret) { ath12k_warn(ab, "failed to set default routing %d peer :%pM vdev_id :%d\n", - ret, addr, vdev_id); + ret, arsta->addr, arvif->vdev_id); return ret; } + ath12k_dbg(ab, ATH12K_DBG_DP_RX, "peer %pM set def route id %d sta_link %d\n", + arsta->addr, lmac_peer_routing_id, + hweight16(sta->valid_links)); + + return 0; +} + +int ath12k_dp_peer_setup(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta) +{ + struct ath12k_base *ab = ar->ab; + struct ath12k_peer *peer; + int ret = 0, tid; + + /* TODO setup resources only for primary link peer for ML case */ + 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, arsta->addr, arvif->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); @@ -78,7 +107,7 @@ int ath12k_dp_peer_setup(struct ath12k * } } - ret = ath12k_dp_rx_peer_frag_setup(ar, addr, vdev_id); + ret = ath12k_dp_rx_peer_frag_setup(ar, arsta->addr, arvif->vdev_id); if (ret) { ath12k_warn(ab, "failed to setup rx defrag context\n"); tid--; @@ -92,7 +121,7 @@ int ath12k_dp_peer_setup(struct ath12k * peer_clean: spin_lock_bh(&ab->base_lock); - peer = ath12k_peer_find(ab, vdev_id, addr); + peer = ath12k_peer_find(ab, arvif->vdev_id, arsta->addr); if (!peer) { ath12k_warn(ab, "failed to find the peer to del rx tid\n"); spin_unlock_bh(&ab->base_lock); --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -16,6 +16,7 @@ struct ath12k_base; struct ath12k_peer; struct ath12k_dp; struct ath12k_link_vif; +struct ath12k_link_sta; struct hal_tcl_status_ring; struct ath12k_ext_irq_grp; @@ -2172,7 +2173,11 @@ void ath12k_dp_pdev_pre_alloc(struct ath void ath12k_dp_pdev_free(struct ath12k_base *ab); int ath12k_dp_tx_htt_srng_setup(struct ath12k_base *ab, u32 ring_id, int mac_id, enum hal_ring_type ring_type); -int ath12k_dp_peer_setup(struct ath12k *ar, int vdev_id, const u8 *addr); +int ath12k_dp_peer_default_route_setup(struct ath12k *ar, + struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta); +int ath12k_dp_peer_setup(struct ath12k *ar, struct ath12k_link_vif *arvif, + struct ath12k_link_sta *arsta); 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, --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -6620,7 +6620,7 @@ static int ath12k_mac_station_add(struct } } - ret = ath12k_dp_peer_setup(ar, arvif->vdev_id, arsta->addr); + ret = ath12k_dp_peer_setup(ar, arvif, arsta); if (ret) { ath12k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n", arsta->addr, arvif->vdev_id, ret); @@ -6871,14 +6871,18 @@ static int ath12k_mac_handle_link_sta_st ath12k_mac_free_unassign_link_sta(arvif->ahvif->ah, arsta->ahsta, arsta->link_id); } else if (old_state == IEEE80211_STA_AUTH && - new_state == IEEE80211_STA_ASSOC && - (vif->type == NL80211_IFTYPE_AP || + new_state == IEEE80211_STA_ASSOC) { + + ath12k_dp_peer_default_route_setup(ar, arvif, arsta); + + if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_MESH_POINT || - vif->type == NL80211_IFTYPE_ADHOC)) { - ret = ath12k_station_assoc(ar, arvif, arsta, false); - if (ret) - ath12k_warn(ar->ab, "Failed to associate station: %pM\n", - arsta->addr); + vif->type == NL80211_IFTYPE_ADHOC) { + ret = ath12k_station_assoc(ar, arvif, arsta, false); + if (ret) + ath12k_warn(ar->ab, "Failed to associate station: %pM\n", + arsta->addr); + } } else if (old_state == IEEE80211_STA_ASSOC && new_state == IEEE80211_STA_AUTHORIZED) { ret = ath12k_station_authorize(ar, arvif, arsta);