| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- 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 <[email protected]>
- Closes: https://lore.kernel.org/all/[email protected]/
- Signed-off-by: P Praneesh <[email protected]>
- Tested-by: Tim Harvey <[email protected]>
- Link: https://patch.msgid.link/[email protected]
- Signed-off-by: Jeff Johnson <[email protected]>
- --- 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);
|