]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath12k: Fix MSDU buffer types handling in RX error path
authorSarika Sharma <sarika.sharma@oss.qualcomm.com>
Tue, 30 Sep 2025 09:15:50 +0000 (14:45 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Wed, 15 Oct 2025 23:37:53 +0000 (16:37 -0700)
Currently, packets received on the REO exception ring from
unassociated peers are of MSDU buffer type, while the driver expects
link descriptor type packets. These packets are not parsed further due
to a return check on packet type in ath12k_hal_desc_reo_parse_err(),
but the associated skb is not freed. This may lead to kernel
crashes and buffer leaks.

Hence to fix, update the RX error handler to explicitly drop
MSDU buffer type packets received on the REO exception ring.
This prevents further processing of invalid packets and ensures
stability in the RX error handling path.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1

Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Sarika Sharma <sarika.sharma@oss.qualcomm.com>
Reviewed-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20250930091551.3305312-2-sarika.sharma@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/dp_rx.c
drivers/net/wireless/ath/ath12k/hal_rx.c

index 5e5c14a70316de366784a10d1169bd714706f56d..99d29eda26cf1dcd204aeec8a451b2621b147bc7 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: BSD-3-Clause-Clear
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
  */
 
 #include <linux/ieee80211.h>
@@ -3781,6 +3781,48 @@ exit:
        return 0;
 }
 
+static int ath12k_dp_h_msdu_buffer_type(struct ath12k_base *ab,
+                                       struct list_head *list,
+                                       struct hal_reo_dest_ring *desc)
+{
+       struct ath12k_rx_desc_info *desc_info;
+       struct ath12k_skb_rxcb *rxcb;
+       struct sk_buff *msdu;
+       u64 desc_va;
+
+       desc_va = (u64)le32_to_cpu(desc->buf_va_hi) << 32 |
+                 le32_to_cpu(desc->buf_va_lo);
+       desc_info = (struct ath12k_rx_desc_info *)(uintptr_t)desc_va;
+       if (!desc_info) {
+               u32 cookie;
+
+               cookie = le32_get_bits(desc->buf_addr_info.info1,
+                                      BUFFER_ADDR_INFO1_SW_COOKIE);
+               desc_info = ath12k_dp_get_rx_desc(ab, cookie);
+               if (!desc_info) {
+                       ath12k_warn(ab, "Invalid cookie in manual descriptor retrieval: 0x%x\n",
+                                   cookie);
+                       return -EINVAL;
+               }
+       }
+
+       if (desc_info->magic != ATH12K_DP_RX_DESC_MAGIC) {
+               ath12k_warn(ab, "rx exception, magic check failed with value: %u\n",
+                           desc_info->magic);
+               return -EINVAL;
+       }
+
+       msdu = desc_info->skb;
+       desc_info->skb = NULL;
+       list_add_tail(&desc_info->list, list);
+       rxcb = ATH12K_SKB_RXCB(msdu);
+       dma_unmap_single(ab->dev, rxcb->paddr, msdu->len + skb_tailroom(msdu),
+                        DMA_FROM_DEVICE);
+       dev_kfree_skb_any(msdu);
+
+       return 0;
+}
+
 int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
                             int budget)
 {
@@ -3825,6 +3867,26 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
                drop = false;
                ab->device_stats.err_ring_pkts++;
 
+               hw_link_id = le32_get_bits(reo_desc->info0,
+                                          HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
+               device_id = hw_links[hw_link_id].device_id;
+               partner_ab = ath12k_ag_to_ab(ag, device_id);
+
+               /* Below case is added to handle data packet from un-associated clients.
+                * As it is expected that AST lookup will fail for
+                * un-associated station's data packets.
+                */
+               if (le32_get_bits(reo_desc->info0, HAL_REO_DEST_RING_INFO0_BUFFER_TYPE) ==
+                   HAL_REO_DEST_RING_BUFFER_TYPE_MSDU) {
+                       if (!ath12k_dp_h_msdu_buffer_type(partner_ab,
+                                                         &rx_desc_used_list[device_id],
+                                                         reo_desc)) {
+                               num_buffs_reaped[device_id]++;
+                               tot_n_bufs_reaped++;
+                       }
+                       goto next_desc;
+               }
+
                ret = ath12k_hal_desc_reo_parse_err(ab, reo_desc, &paddr,
                                                    &desc_bank);
                if (ret) {
@@ -3833,11 +3895,6 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
                        continue;
                }
 
-               hw_link_id = le32_get_bits(reo_desc->info0,
-                                          HAL_REO_DEST_RING_INFO0_SRC_LINK_ID);
-               device_id = hw_links[hw_link_id].device_id;
-               partner_ab = ath12k_ag_to_ab(ag, device_id);
-
                pdev_id = ath12k_hw_mac_id_to_pdev_id(partner_ab->hw_params,
                                                      hw_links[hw_link_id].pdev_idx);
                ar = partner_ab->pdevs[pdev_id].ar;
@@ -3886,6 +3943,7 @@ int ath12k_dp_rx_process_err(struct ath12k_base *ab, struct napi_struct *napi,
                        }
                }
 
+next_desc:
                if (tot_n_bufs_reaped >= quota) {
                        tot_n_bufs_reaped = quota;
                        goto exit;
index 669096278fdd48aef47fe299552ae5e73b0b3acb..c4443ca05cd653fbf369dba6cda2226db8497d2c 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: BSD-3-Clause-Clear
 /*
  * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
  */
 
 #include "debug.h"
@@ -323,7 +323,7 @@ int ath12k_hal_desc_reo_parse_err(struct ath12k_base *ab,
 {
        enum hal_reo_dest_ring_push_reason push_reason;
        enum hal_reo_dest_ring_error_code err_code;
-       u32 cookie, val;
+       u32 cookie;
 
        push_reason = le32_get_bits(desc->info0,
                                    HAL_REO_DEST_RING_INFO0_PUSH_REASON);
@@ -338,12 +338,6 @@ int ath12k_hal_desc_reo_parse_err(struct ath12k_base *ab,
                return -EINVAL;
        }
 
-       val = le32_get_bits(desc->info0, HAL_REO_DEST_RING_INFO0_BUFFER_TYPE);
-       if (val != HAL_REO_DEST_RING_BUFFER_TYPE_LINK_DESC) {
-               ath12k_warn(ab, "expected buffer type link_desc");
-               return -EINVAL;
-       }
-
        ath12k_hal_rx_reo_ent_paddr_get(ab, &desc->buf_addr_info, paddr, &cookie);
        *desc_bank = u32_get_bits(cookie, DP_LINK_DESC_BANK_MASK);