wlan-ap-Telecominfraproject/feeds/ipq95xx/mac80211/patches/qca/353-ath11k-ignore-frags-from-uninitialized-peer-in-dp.patch
John Crispin 144c5d00f4 ipq95xx/mac80211: update to ATH12.3-CS
Signed-off-by: John Crispin <john@phrozen.org>
2024-02-28 18:56:21 +01:00

120 lines
3.8 KiB
Diff

From 0ab84604de1db0f589f7303507f38148ba8f3f04 Mon Sep 17 00:00:00 2001
From: Nagarajan Maran <quic_nmaran@quicinc.com>
Date: Tue, 28 Jun 2022 11:31:50 +0530
Subject: [PATCH] ath11k: Ignore frags from uninitialized peer in dp
In certain scenario, fragmented packet is received for self peer,
for which rx_tid and rx_frags are not initialized in datapath.
While handling this fragment, crash is observed as the
rx_frag list is uninitialised and when we walk in
ath11k_dp_rx_h_sort_frags, skb null leads to exception.
To address this, before processing received fragments we
check dp_setup_done flag is set to ensure that peer
has completed its dp peer setup for fragment queue,
else ignore processing the fragments.
Also, __fls would have an undefined behavior if the argument
is passed as "0". Hence, added changes to handle the same.
Below is the call trace of the crash:
CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.164 #0
Hardware name: Qualcomm Technologies, Inc. IPQ6018/AP-CP01-C1 (DT)
pstate: a0400005 (NzCv daif +PAN -UAO)
pc : ath11k_dp_process_rx_err+0x550/0x1084 [ath11k]
lr : ath11k_dp_process_rx_err+0x4e0/0x1084 [ath11k]
Call trace:
ath11k_dp_process_rx_err+0x550/0x1084 [ath11k]
ath11k_dp_service_srng+0x70/0x370 [ath11k]
0xffffffc009693a04
__napi_poll+0x30/0xa4
net_rx_action+0x118/0x270
__do_softirq+0x10c/0x244
irq_exit+0x64/0xb4
__handle_domain_irq+0x88/0xac
gic_handle_irq+0x74/0xbc
el1_irq+0xf0/0x1c0
arch_cpu_idle+0x10/0x18
do_idle+0x104/0x248
cpu_startup_entry+0x20/0x64
rest_init+0xd0/0xdc
arch_call_rest_init+0xc/0x14
start_kernel+0x480/0x4b8
Code: f9400281 f94066a2 91405021 b94a0023 (f9406401)
Signed-off-by: Harshitha Prem <quic_hprem@quicinc.com>
Signed-off-by: Nagarajan Maran <quic_nmaran@quicinc.com>
---
drivers/net/wireless/ath/ath11k/dp.c | 3 ++-
drivers/net/wireless/ath/ath11k/dp_rx.c | 11 ++++++++++-
drivers/net/wireless/ath/ath11k/peer.h | 2 ++
3 files changed, 14 insertions(+), 2 deletions(-)
--- a/drivers/net/wireless/ath/ath11k/dp.c
+++ b/drivers/net/wireless/ath/ath11k/dp.c
@@ -36,6 +36,7 @@ void ath11k_dp_peer_cleanup(struct ath11
ath11k_peer_rx_tid_cleanup(ar, peer);
crypto_free_shash(peer->tfm_mmic);
+ peer->dp_setup_done = false;
spin_unlock_bh(&ab->base_lock);
}
@@ -76,7 +77,8 @@ int ath11k_dp_peer_setup(struct ath11k *
ret = ath11k_peer_rx_frag_setup(ar, addr, vdev_id);
if (ret) {
ath11k_warn(ab, "failed to setup rx defrag context\n");
- return ret;
+ tid--;
+ goto peer_clean;
}
/* TODO: Setup other peer specific resource used in data path */
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -4123,6 +4123,7 @@ int ath11k_peer_rx_frag_setup(struct ath
}
peer->tfm_mmic = tfm;
+ peer->dp_setup_done = true;
spin_unlock_bh(&ab->base_lock);
return 0;
@@ -4569,6 +4570,14 @@ static int ath11k_dp_rx_frag_h_mpdu(stru
ret = -ENOENT;
goto out_unlock;
}
+
+ if (!peer->dp_setup_done) {
+ ath11k_warn(ab, "The peer %pM [%d] has not initialized its datapath\n",
+ peer->addr, peer_id);
+ ret = -ENOENT;
+ goto out_unlock;
+ }
+
rx_tid = &peer->rx_tid[tid];
if ((!skb_queue_empty(&rx_tid->rx_frags) && seqno != rx_tid->cur_sn) ||
@@ -4584,7 +4593,7 @@ static int ath11k_dp_rx_frag_h_mpdu(stru
goto out_unlock;
}
- if (frag_no > __fls(rx_tid->rx_frag_bitmap))
+ if (!rx_tid->rx_frag_bitmap || (frag_no > __fls(rx_tid->rx_frag_bitmap)))
__skb_queue_tail(&rx_tid->rx_frags, msdu);
else
ath11k_dp_rx_h_sort_frags(ar, &rx_tid->rx_frags, msdu);
--- a/drivers/net/wireless/ath/ath11k/peer.h
+++ b/drivers/net/wireless/ath/ath11k/peer.h
@@ -98,6 +98,8 @@ struct ath11k_peer {
bool delayba_flag;
bool peer_logging_enabled;
bool delete_in_progress;
+ /* Peer's datapath set flag */
+ bool dp_setup_done;
};
void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id);