aboutsummaryrefslogtreecommitdiffstats
path: root/package/kernel/mac80211/patches/ath11k/0065-wifi-ath11k-fix-tx-status-reporting-in-encap-offload.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/kernel/mac80211/patches/ath11k/0065-wifi-ath11k-fix-tx-status-reporting-in-encap-offload.patch')
-rw-r--r--package/kernel/mac80211/patches/ath11k/0065-wifi-ath11k-fix-tx-status-reporting-in-encap-offload.patch119
1 files changed, 119 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/ath11k/0065-wifi-ath11k-fix-tx-status-reporting-in-encap-offload.patch b/package/kernel/mac80211/patches/ath11k/0065-wifi-ath11k-fix-tx-status-reporting-in-encap-offload.patch
new file mode 100644
index 0000000000..e2fe419158
--- /dev/null
+++ b/package/kernel/mac80211/patches/ath11k/0065-wifi-ath11k-fix-tx-status-reporting-in-encap-offload.patch
@@ -0,0 +1,119 @@
+From 6257c702264c44d74c6b71f0c62a7665da2dc356 Mon Sep 17 00:00:00 2001
+From: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
+Date: Mon, 17 Apr 2023 13:35:02 +0300
+Subject: [PATCH] wifi: ath11k: fix tx status reporting in encap offload mode
+
+ieee80211_tx_status() treats packets in 802.11 frame format and
+tries to extract sta address from packet header. When tx encap
+offload is enabled, this becomes invalid operation. Hence, switch
+to using ieee80211_tx_status_ext() after filling in station
+address for handling both 802.11 and 802.3 frames.
+
+Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
+
+Signed-off-by: Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com>
+Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
+Link: https://lore.kernel.org/r/20230403195738.25367-2-quic_pradeepc@quicinc.com
+---
+ drivers/net/wireless/ath/ath11k/dp.h | 4 +++
+ drivers/net/wireless/ath/ath11k/dp_tx.c | 33 ++++++++++++++++++++++++-
+ drivers/net/wireless/ath/ath11k/dp_tx.h | 1 +
+ 3 files changed, 37 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath11k/dp.h
++++ b/drivers/net/wireless/ath/ath11k/dp.h
+@@ -303,12 +303,16 @@ struct ath11k_dp {
+
+ #define HTT_TX_WBM_COMP_STATUS_OFFSET 8
+
++#define HTT_INVALID_PEER_ID 0xffff
++
+ /* HTT tx completion is overlaid in wbm_release_ring */
+ #define HTT_TX_WBM_COMP_INFO0_STATUS GENMASK(12, 9)
+ #define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13)
+ #define HTT_TX_WBM_COMP_INFO0_REINJECT_REASON GENMASK(16, 13)
+
+ #define HTT_TX_WBM_COMP_INFO1_ACK_RSSI GENMASK(31, 24)
++#define HTT_TX_WBM_COMP_INFO2_SW_PEER_ID GENMASK(15, 0)
++#define HTT_TX_WBM_COMP_INFO2_VALID BIT(21)
+
+ struct htt_tx_wbm_completion {
+ u32 info0;
+--- a/drivers/net/wireless/ath/ath11k/dp_tx.c
++++ b/drivers/net/wireless/ath/ath11k/dp_tx.c
+@@ -316,10 +316,12 @@ ath11k_dp_tx_htt_tx_complete_buf(struct
+ struct dp_tx_ring *tx_ring,
+ struct ath11k_dp_htt_wbm_tx_status *ts)
+ {
++ struct ieee80211_tx_status status = { 0 };
+ struct sk_buff *msdu;
+ struct ieee80211_tx_info *info;
+ struct ath11k_skb_cb *skb_cb;
+ struct ath11k *ar;
++ struct ath11k_peer *peer;
+
+ spin_lock(&tx_ring->tx_idr_lock);
+ msdu = idr_remove(&tx_ring->txbuf_idr, ts->msdu_id);
+@@ -341,6 +343,11 @@ ath11k_dp_tx_htt_tx_complete_buf(struct
+
+ dma_unmap_single(ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
+
++ if (!skb_cb->vif) {
++ dev_kfree_skb_any(msdu);
++ return;
++ }
++
+ memset(&info->status, 0, sizeof(info->status));
+
+ if (ts->acked) {
+@@ -355,7 +362,23 @@ ath11k_dp_tx_htt_tx_complete_buf(struct
+ }
+ }
+
+- ieee80211_tx_status(ar->hw, msdu);
++ spin_lock_bh(&ab->base_lock);
++ peer = ath11k_peer_find_by_id(ab, ts->peer_id);
++ if (!peer || !peer->sta) {
++ ath11k_dbg(ab, ATH11K_DBG_DATA,
++ "dp_tx: failed to find the peer with peer_id %d\n",
++ ts->peer_id);
++ spin_unlock_bh(&ab->base_lock);
++ dev_kfree_skb_any(msdu);
++ return;
++ }
++ spin_unlock_bh(&ab->base_lock);
++
++ status.sta = peer->sta;
++ status.info = info;
++ status.skb = msdu;
++
++ ieee80211_tx_status_ext(ar->hw, &status);
+ }
+
+ static void
+@@ -379,7 +402,15 @@ ath11k_dp_tx_process_htt_tx_complete(str
+ ts.msdu_id = msdu_id;
+ ts.ack_rssi = FIELD_GET(HTT_TX_WBM_COMP_INFO1_ACK_RSSI,
+ status_desc->info1);
++
++ if (FIELD_GET(HTT_TX_WBM_COMP_INFO2_VALID, status_desc->info2))
++ ts.peer_id = FIELD_GET(HTT_TX_WBM_COMP_INFO2_SW_PEER_ID,
++ status_desc->info2);
++ else
++ ts.peer_id = HTT_INVALID_PEER_ID;
++
+ ath11k_dp_tx_htt_tx_complete_buf(ab, tx_ring, &ts);
++
+ break;
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_REINJ:
+ case HAL_WBM_REL_HTT_TX_COMP_STATUS_INSPECT:
+--- a/drivers/net/wireless/ath/ath11k/dp_tx.h
++++ b/drivers/net/wireless/ath/ath11k/dp_tx.h
+@@ -13,6 +13,7 @@ struct ath11k_dp_htt_wbm_tx_status {
+ u32 msdu_id;
+ bool acked;
+ int ack_rssi;
++ u16 peer_id;
+ };
+
+ void ath11k_dp_tx_update_txcompl(struct ath11k *ar, struct hal_tx_status *ts);