002-wifi-ath11k-use-dma-alloc-noncoherent-for-rx-tid-buffer-allocation.patch 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. wifi: ath11k: Use dma_alloc_noncoherent for rx_tid buffer allocation
  2. Currently, the driver allocates cacheable DMA buffers for the rx_tid
  3. structure using kzalloc() and dma_map_single(). These buffers are
  4. long-lived and can persist for the lifetime of the peer, which is not
  5. advisable. Instead of using kzalloc() and dma_map_single() for allocating
  6. cacheable DMA buffers, utilize the dma_alloc_noncoherent() helper for the
  7. allocation of long-lived cacheable DMA buffers, such as the peer's rx_tid.
  8. Since dma_alloc_noncoherent() returns unaligned physical and virtual
  9. addresses, align them internally before use within the driver. This
  10. ensures proper allocation of non-coherent memory through the kernel
  11. helper.
  12. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1
  13. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
  14. Signed-off-by: P Praneesh <[email protected]>
  15. --- a/drivers/net/wireless/ath/ath11k/dp.h
  16. +++ b/drivers/net/wireless/ath/ath11k/dp.h
  17. @@ -1,7 +1,7 @@
  18. /* SPDX-License-Identifier: BSD-3-Clause-Clear */
  19. /*
  20. * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
  21. - * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  22. + * Copyright (c) 2021-2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved.
  23. */
  24. #ifndef ATH11K_DP_H
  25. @@ -20,7 +20,6 @@ struct ath11k_ext_irq_grp;
  26. struct dp_rx_tid {
  27. u8 tid;
  28. - u32 *vaddr;
  29. dma_addr_t paddr;
  30. u32 size;
  31. u32 ba_win_sz;
  32. @@ -37,6 +36,9 @@ struct dp_rx_tid {
  33. /* Timer info related to fragments */
  34. struct timer_list frag_timer;
  35. struct ath11k_base *ab;
  36. + u32 *vaddr_unaligned;
  37. + dma_addr_t paddr_unaligned;
  38. + u32 unaligned_size;
  39. };
  40. #define DP_REO_DESC_FREE_THRESHOLD 64
  41. --- a/drivers/net/wireless/ath/ath11k/dp_rx.c
  42. +++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
  43. @@ -1,7 +1,7 @@
  44. // SPDX-License-Identifier: BSD-3-Clause-Clear
  45. /*
  46. * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
  47. - * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
  48. + * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
  49. */
  50. #include <linux/ieee80211.h>
  51. @@ -675,11 +675,11 @@ void ath11k_dp_reo_cmd_list_cleanup(stru
  52. list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) {
  53. list_del(&cmd->list);
  54. rx_tid = &cmd->data;
  55. - if (rx_tid->vaddr) {
  56. - dma_unmap_single(ab->dev, rx_tid->paddr,
  57. - rx_tid->size, DMA_BIDIRECTIONAL);
  58. - kfree(rx_tid->vaddr);
  59. - rx_tid->vaddr = NULL;
  60. + if (rx_tid->vaddr_unaligned) {
  61. + dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
  62. + rx_tid->vaddr_unaligned,
  63. + rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
  64. + rx_tid->vaddr_unaligned = NULL;
  65. }
  66. kfree(cmd);
  67. }
  68. @@ -689,11 +689,11 @@ void ath11k_dp_reo_cmd_list_cleanup(stru
  69. list_del(&cmd_cache->list);
  70. dp->reo_cmd_cache_flush_count--;
  71. rx_tid = &cmd_cache->data;
  72. - if (rx_tid->vaddr) {
  73. - dma_unmap_single(ab->dev, rx_tid->paddr,
  74. - rx_tid->size, DMA_BIDIRECTIONAL);
  75. - kfree(rx_tid->vaddr);
  76. - rx_tid->vaddr = NULL;
  77. + if (rx_tid->vaddr_unaligned) {
  78. + dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
  79. + rx_tid->vaddr_unaligned,
  80. + rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
  81. + rx_tid->vaddr_unaligned = NULL;
  82. }
  83. kfree(cmd_cache);
  84. }
  85. @@ -708,11 +708,11 @@ static void ath11k_dp_reo_cmd_free(struc
  86. if (status != HAL_REO_CMD_SUCCESS)
  87. ath11k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n",
  88. rx_tid->tid, status);
  89. - if (rx_tid->vaddr) {
  90. - dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size,
  91. - DMA_BIDIRECTIONAL);
  92. - kfree(rx_tid->vaddr);
  93. - rx_tid->vaddr = NULL;
  94. + if (rx_tid->vaddr_unaligned) {
  95. + dma_free_noncoherent(dp->ab->dev, rx_tid->unaligned_size,
  96. + rx_tid->vaddr_unaligned,
  97. + rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
  98. + rx_tid->vaddr_unaligned = NULL;
  99. }
  100. }
  101. @@ -749,10 +749,10 @@ static void ath11k_dp_reo_cache_flush(st
  102. if (ret) {
  103. ath11k_err(ab, "failed to send HAL_REO_CMD_FLUSH_CACHE cmd, tid %d (%d)\n",
  104. rx_tid->tid, ret);
  105. - dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
  106. - DMA_BIDIRECTIONAL);
  107. - kfree(rx_tid->vaddr);
  108. - rx_tid->vaddr = NULL;
  109. + dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
  110. + rx_tid->vaddr_unaligned,
  111. + rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
  112. + rx_tid->vaddr_unaligned = NULL;
  113. }
  114. }
  115. @@ -802,10 +802,10 @@ static void ath11k_dp_rx_tid_del_func(st
  116. return;
  117. free_desc:
  118. - dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
  119. - DMA_BIDIRECTIONAL);
  120. - kfree(rx_tid->vaddr);
  121. - rx_tid->vaddr = NULL;
  122. + dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
  123. + rx_tid->vaddr_unaligned,
  124. + rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
  125. + rx_tid->vaddr_unaligned = NULL;
  126. }
  127. void ath11k_peer_rx_tid_delete(struct ath11k *ar,
  128. @@ -831,14 +831,16 @@ void ath11k_peer_rx_tid_delete(struct at
  129. if (ret != -ESHUTDOWN)
  130. ath11k_err(ar->ab, "failed to send HAL_REO_CMD_UPDATE_RX_QUEUE cmd, tid %d (%d)\n",
  131. tid, ret);
  132. - dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size,
  133. - DMA_BIDIRECTIONAL);
  134. - kfree(rx_tid->vaddr);
  135. - rx_tid->vaddr = NULL;
  136. + dma_free_noncoherent(ar->ab->dev, rx_tid->unaligned_size,
  137. + rx_tid->vaddr_unaligned,
  138. + rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
  139. + rx_tid->vaddr_unaligned = NULL;
  140. }
  141. rx_tid->paddr = 0;
  142. + rx_tid->paddr_unaligned = 0;
  143. rx_tid->size = 0;
  144. + rx_tid->unaligned_size = 0;
  145. }
  146. static int ath11k_dp_rx_link_desc_return(struct ath11k_base *ab,
  147. @@ -982,10 +984,9 @@ static void ath11k_dp_rx_tid_mem_free(st
  148. if (!rx_tid->active)
  149. goto unlock_exit;
  150. - dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
  151. - DMA_BIDIRECTIONAL);
  152. - kfree(rx_tid->vaddr);
  153. - rx_tid->vaddr = NULL;
  154. + dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, rx_tid->vaddr_unaligned,
  155. + rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
  156. + rx_tid->vaddr_unaligned = NULL;
  157. rx_tid->active = false;
  158. @@ -1000,9 +1001,8 @@ int ath11k_peer_rx_tid_setup(struct ath1
  159. struct ath11k_base *ab = ar->ab;
  160. struct ath11k_peer *peer;
  161. struct dp_rx_tid *rx_tid;
  162. - u32 hw_desc_sz;
  163. - u32 *addr_aligned;
  164. - void *vaddr;
  165. + u32 hw_desc_sz, *vaddr;
  166. + void *vaddr_unaligned;
  167. dma_addr_t paddr;
  168. int ret;
  169. @@ -1050,37 +1050,34 @@ int ath11k_peer_rx_tid_setup(struct ath1
  170. else
  171. hw_desc_sz = ath11k_hal_reo_qdesc_size(DP_BA_WIN_SZ_MAX, tid);
  172. - vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1, GFP_ATOMIC);
  173. - if (!vaddr) {
  174. + rx_tid->unaligned_size = hw_desc_sz + HAL_LINK_DESC_ALIGN - 1;
  175. + vaddr_unaligned = dma_alloc_noncoherent(ab->dev, rx_tid->unaligned_size, &paddr,
  176. + DMA_BIDIRECTIONAL, GFP_ATOMIC);
  177. + if (!vaddr_unaligned) {
  178. spin_unlock_bh(&ab->base_lock);
  179. return -ENOMEM;
  180. }
  181. - addr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN);
  182. -
  183. - ath11k_hal_reo_qdesc_setup(addr_aligned, tid, ba_win_sz,
  184. - ssn, pn_type);
  185. -
  186. - paddr = dma_map_single(ab->dev, addr_aligned, hw_desc_sz,
  187. - DMA_BIDIRECTIONAL);
  188. -
  189. - ret = dma_mapping_error(ab->dev, paddr);
  190. - if (ret) {
  191. - spin_unlock_bh(&ab->base_lock);
  192. - ath11k_warn(ab, "failed to setup dma map for peer %pM rx tid %d: %d\n",
  193. - peer_mac, tid, ret);
  194. - goto err_mem_free;
  195. - }
  196. -
  197. - rx_tid->vaddr = vaddr;
  198. - rx_tid->paddr = paddr;
  199. + rx_tid->vaddr_unaligned = vaddr_unaligned;
  200. + vaddr = PTR_ALIGN(vaddr_unaligned, HAL_LINK_DESC_ALIGN);
  201. + rx_tid->paddr_unaligned = paddr;
  202. + rx_tid->paddr = rx_tid->paddr_unaligned + ((unsigned long)vaddr -
  203. + (unsigned long)rx_tid->vaddr_unaligned);
  204. + ath11k_hal_reo_qdesc_setup(vaddr, tid, ba_win_sz, ssn, pn_type);
  205. rx_tid->size = hw_desc_sz;
  206. rx_tid->active = true;
  207. + /* After dma_alloc_noncoherent, vaddr is being modified for reo qdesc setup.
  208. + * Since these changes are not reflected in the device, driver now needs to
  209. + * explicitly call dma_sync_single_for_device.
  210. + */
  211. + dma_sync_single_for_device(ab->dev, rx_tid->paddr,
  212. + rx_tid->size,
  213. + DMA_TO_DEVICE);
  214. spin_unlock_bh(&ab->base_lock);
  215. - ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac,
  216. - paddr, tid, 1, ba_win_sz);
  217. + ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, rx_tid->paddr,
  218. + tid, 1, ba_win_sz);
  219. if (ret) {
  220. ath11k_warn(ar->ab, "failed to setup rx reorder queue for peer %pM tid %d: %d\n",
  221. peer_mac, tid, ret);
  222. @@ -1088,12 +1085,6 @@ int ath11k_peer_rx_tid_setup(struct ath1
  223. }
  224. return ret;
  225. -
  226. -err_mem_free:
  227. - kfree(rx_tid->vaddr);
  228. - rx_tid->vaddr = NULL;
  229. -
  230. - return ret;
  231. }
  232. int ath11k_dp_rx_ampdu_start(struct ath11k *ar,