Files
openwrt-ipq/package/kernel/mac80211/patches/nss/subsys/785-wifi-mac80211-Add-mac-hw-flag-to-avoid-queue-skb.patch
Sean Khan 01277800ab ath11k_nss: Refresh patches for backports 6.12.6
Rebased against upstream commit 87033
mac80211: improve single-wiphy multi-radio support

Signed-off-by: Sean Khan <datapronix@protonmail.com>

ath11k_nss: Refresh patches against rebase 53eab61

Author:     Felix Fietkau <nbd@nbd.name>
AuthorDate: Mon Nov 18 11:21:02 2024 +0100
Commit:     Felix Fietkau <nbd@nbd.name>
CommitDate: Mon Nov 18 11:44:44 2024 +0100

    mac80211: backport some upstream fixes

    Fix various issues, including potential crashes

    Signed-off-by: Felix Fietkau <nbd@nbd.name>

Signed-off-by: Sean Khan <datapronix@protonmail.com>

ath11k_nss: Fix patches for backports 6.12.6

Signed-off-by: Sean Khan <datapronix@protonmail.com>

ath11k_nss: Refresh patches for backports 6.12.6

Signed-off-by: Sean Khan <datapronix@protonmail.com>
2025-02-28 16:38:08 -05:00

343 lines
10 KiB
Diff

From ca28b8b125c27063b9b4bc60bb85206ca8e0d403 Mon Sep 17 00:00:00 2001
From: Yuvasree Sivasankaran <quic_ysivasan@quicinc.com>
Date: Thu, 31 Aug 2023 10:59:33 +0530
Subject: [PATCH] wifi: mac80211: Add mac hw flag to avoid queue skb
Queue SKB in mac80211 become mandatory from latest 6.1 kernel. Because of
this queuing, there will be performance degradation. Add hw flag option
to enable tx queue in Driver/Hardware.
Driver/hardware can register for HAS_TX_QUEUE HW flag and avoid tx queuing
in mac80211.
Add same HW flag checks to avoid accessing skb queues which will be
NULL or invalid and also NULL checks for sta txqs for NULL or invalid
access.
Signed-off-by: Yuvasree Sivasankaran <quic_ysivasan@quicinc.com>
---
include/net/mac80211.h | 1 +
net/mac80211/debugfs.c | 1 +
net/mac80211/tx.c | 18 ++++++++++++++----
4 files changed, 17 insertions(+), 4 deletions(-)
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2882,6 +2882,9 @@ struct ieee80211_txq {
*
* @IEEE80211_HW_SUPPORTS_TID_CLASS_OFFLOAD: Hardware suports tid calssification offload.
*
+ * @IEE80211_HW_HAS_TX_QUEUE: Hardware/drivers has tx queue, does skb queuing itself,
+ * the stack will not do tx queuing.
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -2945,6 +2948,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_NSS_OFFLOAD,
IEEE80211_HW_SUPPORTS_MESH_NSS_OFFLOAD,
IEEE80211_HW_SUPPORTS_TID_CLASS_OFFLOAD,
+ IEEE80211_HW_HAS_TX_QUEUE,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -512,6 +512,7 @@ static const char *hw_flag_names[] = {
FLAG(SUPPORTS_NSS_OFFLOAD),
FLAG(SUPPORTS_MESH_NSS_OFFLOAD),
FLAG(SUPPORTS_TID_CLASS_OFFLOAD),
+ FLAG(HAS_TX_QUEUE),
#undef FLAG
};
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1601,6 +1601,9 @@ int ieee80211_txq_setup_flows(struct iee
bool supp_vht = false;
enum nl80211_band band;
+ if (ieee80211_hw_check(&local->hw, HAS_TX_QUEUE))
+ return 0;
+
ret = fq_init(fq, 4096);
if (ret)
return ret;
@@ -1648,6 +1651,9 @@ void ieee80211_txq_teardown_flows(struct
{
struct fq *fq = &local->fq;
+ if (ieee80211_hw_check(&local->hw, HAS_TX_QUEUE))
+ return;
+
kvfree(local->cvars);
local->cvars = NULL;
@@ -1664,7 +1670,8 @@ static bool ieee80211_queue_skb(struct i
struct ieee80211_vif *vif;
struct txq_info *txqi;
- if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ if (ieee80211_hw_check(&local->hw, HAS_TX_QUEUE) ||
+ sdata->vif.type == NL80211_IFTYPE_MONITOR)
return false;
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
@@ -4353,7 +4360,8 @@ void __ieee80211_subif_start_xmit(struct
}
}
- skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
+ if (unlikely(!ieee80211_hw_check(&local->hw, HAS_TX_QUEUE)))
+ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
ieee80211_aggr_check(sdata, sta, skb);
if (sta) {
@@ -4707,8 +4715,10 @@ static void ieee80211_8023_xmit(struct i
bool multicast;
u8 tid;
- queue = ieee80211_select_queue(sdata, sta, skb);
- skb_set_queue_mapping(skb, queue);
+ if (unlikely(!ieee80211_hw_check(&local->hw, HAS_TX_QUEUE))) {
+ queue = ieee80211_select_queue(sdata, sta, skb);
+ skb_set_queue_mapping(skb, queue);
+ }
multicast = is_multicast_ether_addr(ra);
@@ -6429,9 +6439,12 @@ int ieee80211_tx_control_port(struct wip
}
if (!IS_ERR(sta)) {
- u16 queue = ieee80211_select_queue(sdata, sta, skb);
- skb_set_queue_mapping(skb, queue);
+ if (!ieee80211_hw_check(&local->hw, HAS_TX_QUEUE)) {
+ u16 queue = ieee80211_select_queue(sdata, sta, skb);
+
+ skb_set_queue_mapping(skb, queue);
+ }
/*
* for MLO STA, the SA should be the AP MLD address, but
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -4601,6 +4601,9 @@ static int ieee80211_get_txq_stats(struc
struct ieee80211_sub_if_data *sdata;
int ret = 0;
+ if (ieee80211_hw_check(&local->hw, HAS_TX_QUEUE))
+ return 1;
+
spin_lock_bh(&local->fq.lock);
rcu_read_lock();
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -1003,7 +1003,10 @@ struct ieee80211_hw *ieee80211_alloc_hw_
atomic_set(&local->agg_queue_stop[i], 0);
}
tasklet_setup(&local->tx_pending_tasklet, ieee80211_tx_pending);
- tasklet_setup(&local->wake_txqs_tasklet, ieee80211_wake_txqs);
+
+ if (!ieee80211_hw_check(&local->hw, HAS_TX_QUEUE))
+ tasklet_setup(&local->wake_txqs_tasklet, ieee80211_wake_txqs);
+
tasklet_setup(&local->tasklet, ieee80211_tasklet_handler);
skb_queue_head_init(&local->skb_queue);
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1588,6 +1588,9 @@ static void sta_ps_start(struct sta_info
ieee80211_clear_fast_xmit(sta);
+ if (!sta->sta.txq[0])
+ return;
+
for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
struct ieee80211_txq *txq = sta->sta.txq[tid];
struct txq_info *txqi = to_txq_info(txq);
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -118,15 +118,17 @@ void ieee80211_purge_sta_txqs(struct sta
struct ieee80211_local *local = sta->sdata->local;
int i;
- for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
- struct txq_info *txqi;
+ if (sta->sta.txq[0]) {
+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
+ struct txq_info *txqi;
- if (!sta->sta.txq[i])
- continue;
+ if (!sta->sta.txq[i])
+ continue;
- txqi = to_txq_info(sta->sta.txq[i]);
+ txqi = to_txq_info(sta->sta.txq[i]);
- ieee80211_txq_purge(local, txqi);
+ ieee80211_txq_purge(local, txqi);
+ }
}
}
@@ -436,7 +438,9 @@ void sta_info_free(struct ieee80211_loca
sta_dbg(sta->sdata, "Destroyed STA %pM\n", sta->sta.addr);
- kfree(to_txq_info(sta->sta.txq[0]));
+ if (sta->sta.txq[0])
+ kfree(to_txq_info(sta->sta.txq[0]));
+
kfree(rcu_dereference_raw(sta->sta.rates));
#ifdef CPTCFG_MAC80211_MESH
kfree(sta->mesh);
@@ -537,8 +541,6 @@ __sta_info_alloc(struct ieee80211_sub_if
struct ieee80211_local *local = sdata->local;
struct ieee80211_hw *hw = &local->hw;
struct sta_info *sta;
- void *txq_data;
- int size;
int i;
sta = kzalloc(sizeof(*sta) + hw->sta_data_size, gfp);
@@ -611,18 +613,22 @@ __sta_info_alloc(struct ieee80211_sub_if
sta->last_connected = ktime_get_seconds();
- size = sizeof(struct txq_info) +
- ALIGN(hw->txq_data_size, sizeof(void *));
- txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp);
- if (!txq_data)
- goto free;
+ if (!ieee80211_hw_check(&local->hw, HAS_TX_QUEUE)) {
+ void *txq_data;
+ int size = sizeof(struct txq_info) +
+ ALIGN(hw->txq_data_size, sizeof(void *));
+
+ txq_data = kcalloc(ARRAY_SIZE(sta->sta.txq), size, gfp);
+ if (!txq_data)
+ goto free;
- for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
- struct txq_info *txq = txq_data + i * size;
+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
+ struct txq_info *txq = txq_data + i * size;
- /* might not do anything for the (bufferable) MMPDU TXQ */
- ieee80211_txq_init(sdata, sta, txq, i);
+ /* might not do anything for the (bufferable) MMPDU TXQ */
+ ieee80211_txq_init(sdata, sta, txq, i);
+ }
}
if (sta_prepare_rate_control(local, sta, gfp))
@@ -696,7 +702,8 @@ __sta_info_alloc(struct ieee80211_sub_if
return sta;
free_txq:
- kfree(to_txq_info(sta->sta.txq[0]));
+ if (sta->sta.txq[0])
+ kfree(to_txq_info(sta->sta.txq[0]));
free:
sta_info_free_link(&sta->deflink);
#ifdef CPTCFG_MAC80211_MESH
@@ -1715,11 +1722,13 @@ void ieee80211_sta_ps_deliver_wakeup(str
if (!ieee80211_hw_check(&local->hw, AP_LINK_PS))
drv_sta_notify(local, sdata, STA_NOTIFY_AWAKE, &sta->sta);
- for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
- if (!sta->sta.txq[i] || !txq_has_queue(sta->sta.txq[i]))
- continue;
+ if (!ieee80211_hw_check(&local->hw, HAS_TX_QUEUE)) {
+ for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
+ if (!sta->sta.txq[i] || !txq_has_queue(sta->sta.txq[i]))
+ continue;
- schedule_and_wake_txq(local, to_txq_info(sta->sta.txq[i]));
+ schedule_and_wake_txq(local, to_txq_info(sta->sta.txq[i]));
+ }
}
skb_queue_head_init(&pending);
@@ -2134,6 +2143,9 @@ ieee80211_sta_ps_deliver_response(struct
* TIM recalculation.
*/
+ if (!sta->sta.txq[0])
+ return;
+
for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
if (!sta->sta.txq[tid] ||
!(driver_release_tids & BIT(tid)) ||
@@ -2568,7 +2580,7 @@ static void sta_set_tidstats(struct sta_
tidstats->tx_msdu_failed = sta->deflink.status_stats.msdu_failed[tid];
}
- if (tid < IEEE80211_NUM_TIDS) {
+ if (!ieee80211_hw_check(&local->hw, HAS_TX_QUEUE) && tid < IEEE80211_NUM_TIDS) {
spin_lock_bh(&local->fq.lock);
rcu_read_lock();
@@ -2897,6 +2909,9 @@ unsigned long ieee80211_sta_last_active(
static void sta_update_codel_params(struct sta_info *sta, u32 thr)
{
+ if (ieee80211_hw_check(&sta->sdata->local->hw, HAS_TX_QUEUE))
+ return;
+
if (thr && thr < STA_SLOW_THRESHOLD * sta->local->num_sta) {
sta->cparams.target = MS2TIME(50);
sta->cparams.interval = MS2TIME(300);
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -162,6 +162,9 @@ static ssize_t sta_aqm_read(struct file
bufsz + buf - p,
"tid ac backlog-bytes backlog-packets new-flows drops marks overlimit collisions tx-bytes tx-packets flags\n");
+ if (!ieee80211_hw_check(&local->hw, HAS_TX_QUEUE))
+ goto skip_txq_info;
+
for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
if (!sta->sta.txq[i])
continue;
@@ -186,6 +189,7 @@ static ssize_t sta_aqm_read(struct file
test_bit(IEEE80211_TXQ_DIRTY, &txqi->flags) ? " DIRTY" : "");
}
+skip_txq_info:
rcu_read_unlock();
spin_unlock_bh(&local->fq.lock);
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -814,7 +814,8 @@ bool ieee80211_mesh_xmit_fast(struct iee
if (!skb)
return true;
- skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
+ if (unlikely(!ieee80211_hw_check(&sdata->local->hw, HAS_TX_QUEUE)))
+ skb_set_queue_mapping(skb, ieee80211_select_queue(sdata, sta, skb));
meshhdr = (struct ieee80211s_hdr *)entry->hdr;
if ((meshhdr->flags & MESH_FLAGS_AE) == MESH_FLAGS_AE_A5_A6) {
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -470,10 +470,8 @@ static void __ieee80211_wake_queue(struc
* release someone's lock, but it is fine because all the callers of
* __ieee80211_wake_queue call it right before releasing the lock.
*/
- if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER)
+ if (!ieee80211_hw_check(&local->hw, HAS_TX_QUEUE))
tasklet_schedule(&local->wake_txqs_tasklet);
- else
- _ieee80211_wake_txqs(local, flags);
}
void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,