
Backport two commits to resolve issues with ath1kk causing it to fail driver registration on iommuless systems with DRAM outside of 32bit addressing such as a 4GiB imx8mm: commit 1bcd20981834 ("wifi: ath11k: Fix DMA buffer allocation to resolve SWIOTLB issues") commit eeadc6baf8b3 ("wifi: ath11k: Use dma_alloc_noncoherent for rx_tid buffer allocation") Signed-off-by: Tim Harvey <tharvey@gateworks.com> Link: https://github.com/openwrt/openwrt/pull/17751 Signed-off-by: Robert Marko <robimarko@gmail.com> (cherry picked from commit fa50e53aa92e4db9dfe091e7dd55c3fc2024ad13)
92 lines
3.4 KiB
Diff
92 lines
3.4 KiB
Diff
wifi: ath11k: Fix DMA buffer allocation to resolve SWIOTLB issues
|
|
Currently, the driver allocates cacheable DMA buffers for rings like
|
|
HAL_REO_DST and HAL_WBM2SW_RELEASE. The buffers for HAL_WBM2SW_RELEASE
|
|
are large (1024 KiB), exceeding the SWIOTLB slot size of 256 KiB. This
|
|
leads to "swiotlb buffer is full" error messages on systems without an
|
|
IOMMU that use SWIOTLB, causing driver initialization failures. The driver
|
|
calls dma_map_single() with these large buffers obtained from kzalloc(),
|
|
resulting in ring initialization errors on systems without an IOMMU that
|
|
use SWIOTLB.
|
|
|
|
To address these issues, replace the flawed buffer allocation mechanism
|
|
with the appropriate DMA API. Specifically, use dma_alloc_noncoherent()
|
|
for cacheable DMA buffers, ensuring proper freeing of buffers with
|
|
dma_free_noncoherent().
|
|
|
|
Error log:
|
|
[ 10.194343] ath11k_pci 0000:04:00.0: swiotlb buffer is full (sz:1048583 bytes), total 32768 (slots), used 2529 (slots)
|
|
[ 10.194406] ath11k_pci 0000:04:00.0: failed to set up tcl_comp ring (0) :-12
|
|
[ 10.194781] ath11k_pci 0000:04:00.0: failed to init DP: -12
|
|
|
|
Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
|
|
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
|
|
|
|
Reported-by: Tim Harvey <tharvey@gateworks.com>
|
|
Closes: https://lore.kernel.org/all/20241210041133.GA17116@lst.de/
|
|
Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
|
|
Tested-by: Tim Harvey <tharvey@gateworks.com>
|
|
Link: https://patch.msgid.link/20250119164219.647059-2-quic_ppranees@quicinc.com
|
|
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
|
|
--- a/drivers/net/wireless/ath/ath11k/dp.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/dp.c
|
|
@@ -1,7 +1,7 @@
|
|
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
|
/*
|
|
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
|
|
- * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
+ * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
|
|
*/
|
|
|
|
#include <crypto/hash.h>
|
|
@@ -104,14 +104,12 @@ void ath11k_dp_srng_cleanup(struct ath11
|
|
if (!ring->vaddr_unaligned)
|
|
return;
|
|
|
|
- if (ring->cached) {
|
|
- dma_unmap_single(ab->dev, ring->paddr_unaligned, ring->size,
|
|
- DMA_FROM_DEVICE);
|
|
- kfree(ring->vaddr_unaligned);
|
|
- } else {
|
|
+ if (ring->cached)
|
|
+ dma_free_noncoherent(ab->dev, ring->size, ring->vaddr_unaligned,
|
|
+ ring->paddr_unaligned, DMA_FROM_DEVICE);
|
|
+ else
|
|
dma_free_coherent(ab->dev, ring->size, ring->vaddr_unaligned,
|
|
ring->paddr_unaligned);
|
|
- }
|
|
|
|
ring->vaddr_unaligned = NULL;
|
|
}
|
|
@@ -249,25 +247,14 @@ int ath11k_dp_srng_setup(struct ath11k_b
|
|
default:
|
|
cached = false;
|
|
}
|
|
-
|
|
- if (cached) {
|
|
- ring->vaddr_unaligned = kzalloc(ring->size, GFP_KERNEL);
|
|
- if (!ring->vaddr_unaligned)
|
|
- return -ENOMEM;
|
|
-
|
|
- ring->paddr_unaligned = dma_map_single(ab->dev,
|
|
- ring->vaddr_unaligned,
|
|
- ring->size,
|
|
- DMA_FROM_DEVICE);
|
|
- if (dma_mapping_error(ab->dev, ring->paddr_unaligned)) {
|
|
- kfree(ring->vaddr_unaligned);
|
|
- ring->vaddr_unaligned = NULL;
|
|
- return -ENOMEM;
|
|
- }
|
|
- }
|
|
}
|
|
|
|
- if (!cached)
|
|
+ if (cached)
|
|
+ ring->vaddr_unaligned = dma_alloc_noncoherent(ab->dev, ring->size,
|
|
+ &ring->paddr_unaligned,
|
|
+ DMA_FROM_DEVICE,
|
|
+ GFP_KERNEL);
|
|
+ else
|
|
ring->vaddr_unaligned = dma_alloc_coherent(ab->dev, ring->size,
|
|
&ring->paddr_unaligned,
|
|
GFP_KERNEL);
|