[PATCH 1/2] wifi: ath11k: Fix DMA buffer allocation to resolve SWIOTLB issues
Tim Harvey
tharvey at gateworks.com
Tue Jan 21 09:25:46 PST 2025
On Sun, Jan 19, 2025 at 8:42 AM P Praneesh <quic_ppranees at quicinc.com> wrote:
>
> 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 at gateworks.com>
> Closes: https://lore.kernel.org/all/20241210041133.GA17116@lst.de/
> Signed-off-by: P Praneesh <quic_ppranees at quicinc.com>
> ---
> drivers/net/wireless/ath/ath11k/dp.c | 35 +++++++++-------------------
> 1 file changed, 11 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath11k/dp.c b/drivers/net/wireless/ath/ath11k/dp.c
> index fbf666d0ecf1..f124b7329e1a 100644
> --- 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 ath11k_base *ab, struct dp_srng *ring)
> 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_base *ab, struct dp_srng *ring,
> 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);
> --
> 2.34.1
>
Thanks, this resolves the issue I reported. I tested this with qcn9074
on an imx8mm (no iommu) with 4GiB DRAM and verified swiotlb was not
being used and infrastructure mode worked fine.
Tested-By: Tim Harvey <tharvey at gateworks.com>
Best regards,
Tim
More information about the ath11k
mailing list