[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