mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 19:03:39 +00:00
188 lines
6.5 KiB
Diff
188 lines
6.5 KiB
Diff
From 1b566d8fccb4c4d499c4e4c597ebd4c5474daa7c Mon Sep 17 00:00:00 2001
|
|
From: P Praneesh <quic_ppranees@quicinc.com>
|
|
Date: Tue, 13 Jun 2023 16:17:20 +0530
|
|
Subject: [PATCH] ath12k: add MLO group descriptor limit check in dp tx
|
|
|
|
Limit the tx data packet for per MLO group with the threshold
|
|
limit of 0xC000. Without the Tx limit check Multicast frames
|
|
send lead to out of memory in the system where HW capable of processing
|
|
more than the system memory profile.
|
|
|
|
Remove ATH12K_NUM_EAPOL_RESERVE from the ATH12K_DP_PDEV_TX_LIMIT calculation
|
|
because driver tx limit check allows all the EAPOL frames irrespective of the
|
|
pdev/group limit threshold.
|
|
|
|
Rename Threshold limit as Pdev tx threshold limit to make it relevant to the
|
|
functionality. Add member in soc dp stats to capture the group threshold limit.
|
|
|
|
Signed-off-by: Balamurugan Mahalingam <quic_bmahalin@quicinc.com>
|
|
Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
|
|
---
|
|
drivers/net/wireless/ath/ath12k/bondif.c | 14 ++------------
|
|
drivers/net/wireless/ath/ath12k/core.c | 1 +
|
|
drivers/net/wireless/ath/ath12k/core.h | 4 +++-
|
|
drivers/net/wireless/ath/ath12k/debugfs.c | 19 +++++++++++++++----
|
|
drivers/net/wireless/ath/ath12k/dp.h | 4 ++--
|
|
drivers/net/wireless/ath/ath12k/dp_tx.c | 4 ++++
|
|
drivers/net/wireless/ath/ath12k/mac.c | 20 ++++++++++++++------
|
|
7 files changed, 41 insertions(+), 25 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath12k/bondif.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/bondif.c
|
|
@@ -505,6 +505,7 @@ int ath12k_mcast_dp_tx(struct ath12k *ar
|
|
ath12k_dbg_dump(ab, ATH12K_DBG_DP_TX, NULL, "dp tx msdu: ", skb->data, skb->len);
|
|
arvif->link_stats.tx_enqueued++;
|
|
atomic_inc(&ar->dp.num_tx_pending);
|
|
+ atomic_inc(&ab->ag->num_dp_tx_pending);
|
|
|
|
return 0;
|
|
|
|
--- a/drivers/net/wireless/ath/ath12k/core.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/core.c
|
|
@@ -156,6 +156,7 @@ ath12k_core_hw_group_alloc(u8 id, u8 max
|
|
ag->id = id;
|
|
ag->num_chip = max_chip;
|
|
ag->mlo_capable = !!ath12k_mlo_capable;
|
|
+ atomic_set(&ag->num_dp_tx_pending, 0);
|
|
list_add(&ag->list, &ath12k_hw_groups);
|
|
mutex_init(&ag->mutex_lock);
|
|
mutex_init(&ag->mlomem_arena.mutex_lock);
|
|
--- a/drivers/net/wireless/ath/ath12k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath12k/core.h
|
|
@@ -1118,7 +1118,8 @@ struct ath12k_soc_dp_tx_err_stats {
|
|
/* TCL Ring Buffers unavailable */
|
|
u32 txbuf_na[DP_TCL_NUM_RING_MAX];
|
|
|
|
- u32 threshold_limit;
|
|
+ u32 pdev_threshold_limit;
|
|
+ u32 group_threshold_limit;
|
|
|
|
/* Other failures during dp_tx due to mem allocation failure
|
|
* idr unavailable etc.
|
|
@@ -1251,6 +1252,7 @@ struct ath12k_hw_group {
|
|
struct mutex mutex_lock;
|
|
struct ath12k_mgmt_rx_reo_context rx_reo;
|
|
struct ath12k_host_mlo_mem_arena mlomem_arena;
|
|
+ atomic_t num_dp_tx_pending;
|
|
};
|
|
|
|
/* Master structure to hold the hw data which may be used in core module */
|
|
--- a/drivers/net/wireless/ath/ath12k/debugfs.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/debugfs.c
|
|
@@ -1649,8 +1649,12 @@ static ssize_t ath12k_debugfs_dump_soc_d
|
|
i, soc_stats->tx_err.txbuf_na[i]);
|
|
|
|
len += scnprintf(buf + len, size - len,
|
|
- "\nThreshold limit: %d\n",
|
|
- soc_stats->tx_err.threshold_limit);
|
|
+ "\nTx Threshold limit: %d\n",
|
|
+ soc_stats->tx_err.pdev_threshold_limit);
|
|
+
|
|
+ len += scnprintf(buf + len, size - len,
|
|
+ "\nGroup Tx Threshold limit: %u\n",
|
|
+ soc_stats->tx_err.group_threshold_limit);
|
|
|
|
len += scnprintf(buf + len, size - len,
|
|
"\nMisc Transmit Failures: %d\n",
|
|
@@ -1726,14 +1730,17 @@ static ssize_t ath12k_debugfs_dump_soc_d
|
|
soc_stats->tx_completed[2],
|
|
soc_stats->tx_completed[3]);
|
|
|
|
- for (i = 0; i < 3; i++) {
|
|
|
|
+ len += scnprintf(buf + len, size - len,
|
|
+ "\nag tx_pending: %u\n",
|
|
+ atomic_read(&ab->ag->num_dp_tx_pending));
|
|
+
|
|
+ for (i = 1; i <= ab->num_radios; i++) {
|
|
ar = ath12k_mac_get_ar_by_pdev_id(ab, i);
|
|
if (ar) {
|
|
len += scnprintf(buf + len, size - len,
|
|
- "\ntx_pending [%d]: 0:%d\n",
|
|
- i,
|
|
- atomic_read(&ar->dp.num_tx_pending));
|
|
+ "\nar tx_pending [%d]: %u\n", i,
|
|
+ atomic_read(&ar->dp.num_tx_pending));
|
|
}
|
|
}
|
|
|
|
--- a/drivers/net/wireless/ath/ath12k/dp.h
|
|
+++ b/drivers/net/wireless/ath/ath12k/dp.h
|
|
@@ -276,8 +276,8 @@ struct ath12k_pdev_dp {
|
|
#define DP_REO_QREF_NUM GENMASK(31, 16)
|
|
#define DP_MAX_PEER_ID 2047
|
|
|
|
-#define ATH12K_NUM_EAPOL_RESERVE 1024
|
|
-#define ATH12K_DP_PDEV_TX_LIMIT (ATH12K_NUM_POOL_TX_DESC - ATH12K_NUM_EAPOL_RESERVE)
|
|
+#define ATH12K_DP_PDEV_TX_LIMIT ATH12K_NUM_POOL_TX_DESC
|
|
+#define ATH12K_DP_GROUP_TX_LIMIT 49152
|
|
|
|
/* Total size of the LUT is based on 2K peers, each having reference
|
|
* for 17tids, note each entry is of type ath12k_reo_queue_ref
|
|
--- a/drivers/net/wireless/ath/ath12k/dp_tx.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/dp_tx.c
|
|
@@ -363,6 +363,7 @@ int ath12k_dp_tx_direct(struct ath12k_li
|
|
spin_unlock_bh(&tcl_ring->lock);
|
|
|
|
atomic_inc(&ar->dp.num_tx_pending);
|
|
+ atomic_inc(&ab->ag->num_dp_tx_pending);
|
|
|
|
return 0;
|
|
|
|
@@ -657,6 +658,7 @@ int ath12k_dp_tx(struct ath12k *ar, stru
|
|
arvif->link_stats.tx_enqueued++;
|
|
|
|
atomic_inc(&ar->dp.num_tx_pending);
|
|
+ atomic_inc(&ab->ag->num_dp_tx_pending);
|
|
|
|
return 0;
|
|
|
|
@@ -682,6 +684,8 @@ fail_remove_tx_buf:
|
|
|
|
static inline void ath12k_dp_tx_decrement(struct ath12k *ar)
|
|
{
|
|
+ atomic_dec(&ar->ab->ag->num_dp_tx_pending);
|
|
+
|
|
if (atomic_read(&ar->flush_request)) {
|
|
if (atomic_dec_and_test(&ar->dp.num_tx_pending))
|
|
wake_up(&ar->tx_empty_waitq);
|
|
--- a/drivers/net/wireless/ath/ath12k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/mac.c
|
|
@@ -9062,14 +9062,22 @@ static u8 ath12k_mac_get_tx_link(struct
|
|
return link;
|
|
}
|
|
|
|
-static bool ath12k_mac_tx_check_max_limit(struct ath12k *ar, struct sk_buff *skb)
|
|
+bool ath12k_mac_tx_check_max_limit(struct ath12k *ar, struct sk_buff *skb)
|
|
{
|
|
+ struct ath12k_base *ab = ar->ab;
|
|
+
|
|
+ /* Allow EAPOL */
|
|
+ if (skb->protocol == cpu_to_be16(ETH_P_PAE))
|
|
+ return false;
|
|
+
|
|
+ if (atomic_read(&ab->ag->num_dp_tx_pending) > ATH12K_DP_GROUP_TX_LIMIT) {
|
|
+ ab->soc_stats.tx_err.group_threshold_limit++;
|
|
+ return true;
|
|
+ }
|
|
+
|
|
if (atomic_read(&ar->dp.num_tx_pending) > ATH12K_DP_PDEV_TX_LIMIT) {
|
|
- /* Allow EAPOL */
|
|
- if (!(skb->protocol == cpu_to_be16(ETH_P_PAE))) {
|
|
- ar->ab->soc_stats.tx_err.threshold_limit++;
|
|
- return true;
|
|
- }
|
|
+ ar->ab->soc_stats.tx_err.pdev_threshold_limit++;
|
|
+ return true;
|
|
}
|
|
|
|
return false;
|
|
--- a/drivers/net/wireless/ath/ath12k/mac.h
|
|
+++ b/drivers/net/wireless/ath/ath12k/mac.h
|
|
@@ -241,4 +241,5 @@ bool ath12k_mac_is_ml_arvif(struct ath12
|
|
u16 ath12k_calculate_subchannel_count(enum nl80211_chan_width width);
|
|
void ath12k_mac_background_dfs_event(struct ath12k *ar,
|
|
enum ath12k_background_dfs_events ev);
|
|
+bool ath12k_mac_tx_check_max_limit(struct ath12k *ar, struct sk_buff *skb);
|
|
#endif
|