Commit 7b0c70d9 authored by Karthikeyan Periyasamy's avatar Karthikeyan Periyasamy Committed by Kalle Valo

ath11k: Add peer rhash table support

When more clients (128) are connected, the UL data traffic
KPI measurement is low compared to single client. This issue
is due to more CPU cycles spent on the peer lookup operation
with more clients. So reduce the peer lookup operation by
modifying the linear based lookup operation into the rhash
based lookup operation. This improve the peak throughput
measurement. Since this is a software algorithm change, it is
applicable for all the platforms.

TCP UL 128 Clients test case Observation (64bit system):
Previous: ~550 Mbps
Now	: ~860 Mbps

Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01067-QCAHKSWPL_SILICONZ-1
Signed-off-by: default avatarKarthikeyan Periyasamy <quic_periyasa@quicinc.com>
Signed-off-by: default avatarKalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/1644036628-5334-1-git-send-email-quic_periyasa@quicinc.com
parent 9d97114d
// SPDX-License-Identifier: BSD-3-Clause-Clear // SPDX-License-Identifier: BSD-3-Clause-Clear
/* /*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -1680,6 +1680,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, ...@@ -1680,6 +1680,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
goto err_free_wq; goto err_free_wq;
mutex_init(&ab->core_lock); mutex_init(&ab->core_lock);
mutex_init(&ab->tbl_mtx_lock);
spin_lock_init(&ab->base_lock); spin_lock_init(&ab->base_lock);
mutex_init(&ab->vdev_id_11d_lock); mutex_init(&ab->vdev_id_11d_lock);
init_completion(&ab->reset_complete); init_completion(&ab->reset_complete);
......
/* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* SPDX-License-Identifier: BSD-3-Clause-Clear */
/* /*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/ */
#ifndef ATH11K_CORE_H #ifndef ATH11K_CORE_H
...@@ -12,6 +13,7 @@ ...@@ -12,6 +13,7 @@
#include <linux/bitfield.h> #include <linux/bitfield.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/rhashtable.h>
#include "qmi.h" #include "qmi.h"
#include "htc.h" #include "htc.h"
#include "wmi.h" #include "wmi.h"
...@@ -803,6 +805,18 @@ struct ath11k_base { ...@@ -803,6 +805,18 @@ struct ath11k_base {
struct ath11k_pdev __rcu *pdevs_active[MAX_RADIOS]; struct ath11k_pdev __rcu *pdevs_active[MAX_RADIOS];
struct ath11k_hal_reg_capabilities_ext hal_reg_cap[MAX_RADIOS]; struct ath11k_hal_reg_capabilities_ext hal_reg_cap[MAX_RADIOS];
unsigned long long free_vdev_map; unsigned long long free_vdev_map;
/* To synchronize rhash tbl write operation */
struct mutex tbl_mtx_lock;
/* The rhashtable containing struct ath11k_peer keyed by mac addr */
struct rhashtable *rhead_peer_addr;
struct rhashtable_params rhash_peer_addr_param;
/* The rhashtable containing struct ath11k_peer keyed by id */
struct rhashtable *rhead_peer_id;
struct rhashtable_params rhash_peer_id_param;
struct list_head peers; struct list_head peers;
wait_queue_head_t peer_mapping_wq; wait_queue_head_t peer_mapping_wq;
u8 mac_addr[ETH_ALEN]; u8 mac_addr[ETH_ALEN];
......
// SPDX-License-Identifier: BSD-3-Clause-Clear // SPDX-License-Identifier: BSD-3-Clause-Clear
/* /*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/ */
#include <net/mac80211.h> #include <net/mac80211.h>
...@@ -875,13 +875,16 @@ void ath11k_mac_peer_cleanup_all(struct ath11k *ar) ...@@ -875,13 +875,16 @@ void ath11k_mac_peer_cleanup_all(struct ath11k *ar)
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
mutex_lock(&ab->tbl_mtx_lock);
spin_lock_bh(&ab->base_lock); spin_lock_bh(&ab->base_lock);
list_for_each_entry_safe(peer, tmp, &ab->peers, list) { list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
ath11k_peer_rx_tid_cleanup(ar, peer); ath11k_peer_rx_tid_cleanup(ar, peer);
ath11k_peer_rhash_delete(ab, peer);
list_del(&peer->list); list_del(&peer->list);
kfree(peer); kfree(peer);
} }
spin_unlock_bh(&ab->base_lock); spin_unlock_bh(&ab->base_lock);
mutex_unlock(&ab->tbl_mtx_lock);
ar->num_peers = 0; ar->num_peers = 0;
ar->num_stations = 0; ar->num_stations = 0;
...@@ -4554,6 +4557,7 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, ...@@ -4554,6 +4557,7 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
} }
ath11k_mac_dec_num_stations(arvif, sta); ath11k_mac_dec_num_stations(arvif, sta);
mutex_lock(&ar->ab->tbl_mtx_lock);
spin_lock_bh(&ar->ab->base_lock); spin_lock_bh(&ar->ab->base_lock);
peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr); peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
if (skip_peer_delete && peer) { if (skip_peer_delete && peer) {
...@@ -4561,12 +4565,14 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, ...@@ -4561,12 +4565,14 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
} else if (peer && peer->sta == sta) { } else if (peer && peer->sta == sta) {
ath11k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n", ath11k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",
vif->addr, arvif->vdev_id); vif->addr, arvif->vdev_id);
ath11k_peer_rhash_delete(ar->ab, peer);
peer->sta = NULL; peer->sta = NULL;
list_del(&peer->list); list_del(&peer->list);
kfree(peer); kfree(peer);
ar->num_peers--; ar->num_peers--;
} }
spin_unlock_bh(&ar->ab->base_lock); spin_unlock_bh(&ar->ab->base_lock);
mutex_unlock(&ar->ab->tbl_mtx_lock);
kfree(arsta->tx_stats); kfree(arsta->tx_stats);
arsta->tx_stats = NULL; arsta->tx_stats = NULL;
...@@ -8574,6 +8580,8 @@ void ath11k_mac_unregister(struct ath11k_base *ab) ...@@ -8574,6 +8580,8 @@ void ath11k_mac_unregister(struct ath11k_base *ab)
__ath11k_mac_unregister(ar); __ath11k_mac_unregister(ar);
} }
ath11k_peer_rhash_tbl_destroy(ab);
} }
static int __ath11k_mac_register(struct ath11k *ar) static int __ath11k_mac_register(struct ath11k *ar)
...@@ -8802,6 +8810,10 @@ int ath11k_mac_register(struct ath11k_base *ab) ...@@ -8802,6 +8810,10 @@ int ath11k_mac_register(struct ath11k_base *ab)
ab->cc_freq_hz = IPQ8074_CC_FREQ_HERTZ; ab->cc_freq_hz = IPQ8074_CC_FREQ_HERTZ;
ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1; ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1;
ret = ath11k_peer_rhash_tbl_init(ab);
if (ret)
return ret;
for (i = 0; i < ab->num_radios; i++) { for (i = 0; i < ab->num_radios; i++) {
pdev = &ab->pdevs[i]; pdev = &ab->pdevs[i];
ar = pdev->ar; ar = pdev->ar;
...@@ -8831,6 +8843,8 @@ int ath11k_mac_register(struct ath11k_base *ab) ...@@ -8831,6 +8843,8 @@ int ath11k_mac_register(struct ath11k_base *ab)
__ath11k_mac_unregister(ar); __ath11k_mac_unregister(ar);
} }
ath11k_peer_rhash_tbl_destroy(ab);
return ret; return ret;
} }
......
This diff is collapsed.
/* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* SPDX-License-Identifier: BSD-3-Clause-Clear */
/* /*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/ */
#ifndef ATH11K_PEER_H #ifndef ATH11K_PEER_H
...@@ -20,6 +21,11 @@ struct ath11k_peer { ...@@ -20,6 +21,11 @@ struct ath11k_peer {
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
struct dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; struct dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];
/* peer id based rhashtable list pointer */
struct rhash_head rhash_id;
/* peer addr based rhashtable list pointer */
struct rhash_head rhash_addr;
/* Info used in MMIC verification of /* Info used in MMIC verification of
* RX fragments * RX fragments
*/ */
...@@ -47,5 +53,7 @@ int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id, ...@@ -47,5 +53,7 @@ int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id,
const u8 *addr); const u8 *addr);
struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab, struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab,
int vdev_id); int vdev_id);
int ath11k_peer_rhash_tbl_init(struct ath11k_base *ab);
void ath11k_peer_rhash_tbl_destroy(struct ath11k_base *ab);
int ath11k_peer_rhash_delete(struct ath11k_base *ab, struct ath11k_peer *peer);
#endif /* _PEER_H_ */ #endif /* _PEER_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment