mirror of
https://github.com/optim-enterprises-bv/openwrt-ipq.git
synced 2025-11-02 03:08:31 +00:00
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>
343 lines
10 KiB
Diff
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,
|