Skip to content

Commit 0936946

Browse files
P Praneeshjfvogel
authored andcommitted
wifi: ath11k: Use dma_alloc_noncoherent for rx_tid buffer allocation
[ Upstream commit eeadc6b ] Currently, the driver allocates cacheable DMA buffers for the rx_tid structure using kzalloc() and dma_map_single(). These buffers are long-lived and can persist for the lifetime of the peer, which is not advisable. Instead of using kzalloc() and dma_map_single() for allocating cacheable DMA buffers, utilize the dma_alloc_noncoherent() helper for the allocation of long-lived cacheable DMA buffers, such as the peer's rx_tid. Since dma_alloc_noncoherent() returns unaligned physical and virtual addresses, align them internally before use within the driver. This ensures proper allocation of non-coherent memory through the kernel helper. 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 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]> Signed-off-by: Sasha Levin <[email protected]> (cherry picked from commit 115360031be90aa6cf11d718caf19fea94824285) Signed-off-by: Jack Vogel <[email protected]>
1 parent c950c90 commit 0936946

File tree

2 files changed

+58
-65
lines changed

2 files changed

+58
-65
lines changed

drivers/net/wireless/ath/ath11k/dp.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
22
/*
33
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4-
* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4+
* Copyright (c) 2021-2023, 2025 Qualcomm Innovation Center, Inc. All rights reserved.
55
*/
66

77
#ifndef ATH11K_DP_H
@@ -20,7 +20,6 @@ struct ath11k_ext_irq_grp;
2020

2121
struct dp_rx_tid {
2222
u8 tid;
23-
u32 *vaddr;
2423
dma_addr_t paddr;
2524
u32 size;
2625
u32 ba_win_sz;
@@ -37,6 +36,9 @@ struct dp_rx_tid {
3736
/* Timer info related to fragments */
3837
struct timer_list frag_timer;
3938
struct ath11k_base *ab;
39+
u32 *vaddr_unaligned;
40+
dma_addr_t paddr_unaligned;
41+
u32 unaligned_size;
4042
};
4143

4244
#define DP_REO_DESC_FREE_THRESHOLD 64

drivers/net/wireless/ath/ath11k/dp_rx.c

Lines changed: 54 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: BSD-3-Clause-Clear
22
/*
33
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
4-
* Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4+
* Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved.
55
*/
66

77
#include <linux/ieee80211.h>
@@ -675,11 +675,11 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab)
675675
list_for_each_entry_safe(cmd, tmp, &dp->reo_cmd_list, list) {
676676
list_del(&cmd->list);
677677
rx_tid = &cmd->data;
678-
if (rx_tid->vaddr) {
679-
dma_unmap_single(ab->dev, rx_tid->paddr,
680-
rx_tid->size, DMA_BIDIRECTIONAL);
681-
kfree(rx_tid->vaddr);
682-
rx_tid->vaddr = NULL;
678+
if (rx_tid->vaddr_unaligned) {
679+
dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
680+
rx_tid->vaddr_unaligned,
681+
rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
682+
rx_tid->vaddr_unaligned = NULL;
683683
}
684684
kfree(cmd);
685685
}
@@ -689,11 +689,11 @@ void ath11k_dp_reo_cmd_list_cleanup(struct ath11k_base *ab)
689689
list_del(&cmd_cache->list);
690690
dp->reo_cmd_cache_flush_count--;
691691
rx_tid = &cmd_cache->data;
692-
if (rx_tid->vaddr) {
693-
dma_unmap_single(ab->dev, rx_tid->paddr,
694-
rx_tid->size, DMA_BIDIRECTIONAL);
695-
kfree(rx_tid->vaddr);
696-
rx_tid->vaddr = NULL;
692+
if (rx_tid->vaddr_unaligned) {
693+
dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
694+
rx_tid->vaddr_unaligned,
695+
rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
696+
rx_tid->vaddr_unaligned = NULL;
697697
}
698698
kfree(cmd_cache);
699699
}
@@ -708,11 +708,11 @@ static void ath11k_dp_reo_cmd_free(struct ath11k_dp *dp, void *ctx,
708708
if (status != HAL_REO_CMD_SUCCESS)
709709
ath11k_warn(dp->ab, "failed to flush rx tid hw desc, tid %d status %d\n",
710710
rx_tid->tid, status);
711-
if (rx_tid->vaddr) {
712-
dma_unmap_single(dp->ab->dev, rx_tid->paddr, rx_tid->size,
713-
DMA_BIDIRECTIONAL);
714-
kfree(rx_tid->vaddr);
715-
rx_tid->vaddr = NULL;
711+
if (rx_tid->vaddr_unaligned) {
712+
dma_free_noncoherent(dp->ab->dev, rx_tid->unaligned_size,
713+
rx_tid->vaddr_unaligned,
714+
rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
715+
rx_tid->vaddr_unaligned = NULL;
716716
}
717717
}
718718

@@ -749,10 +749,10 @@ static void ath11k_dp_reo_cache_flush(struct ath11k_base *ab,
749749
if (ret) {
750750
ath11k_err(ab, "failed to send HAL_REO_CMD_FLUSH_CACHE cmd, tid %d (%d)\n",
751751
rx_tid->tid, ret);
752-
dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
753-
DMA_BIDIRECTIONAL);
754-
kfree(rx_tid->vaddr);
755-
rx_tid->vaddr = NULL;
752+
dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
753+
rx_tid->vaddr_unaligned,
754+
rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
755+
rx_tid->vaddr_unaligned = NULL;
756756
}
757757
}
758758

@@ -802,10 +802,10 @@ static void ath11k_dp_rx_tid_del_func(struct ath11k_dp *dp, void *ctx,
802802

803803
return;
804804
free_desc:
805-
dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
806-
DMA_BIDIRECTIONAL);
807-
kfree(rx_tid->vaddr);
808-
rx_tid->vaddr = NULL;
805+
dma_free_noncoherent(ab->dev, rx_tid->unaligned_size,
806+
rx_tid->vaddr_unaligned,
807+
rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
808+
rx_tid->vaddr_unaligned = NULL;
809809
}
810810

811811
void ath11k_peer_rx_tid_delete(struct ath11k *ar,
@@ -831,14 +831,16 @@ void ath11k_peer_rx_tid_delete(struct ath11k *ar,
831831
if (ret != -ESHUTDOWN)
832832
ath11k_err(ar->ab, "failed to send HAL_REO_CMD_UPDATE_RX_QUEUE cmd, tid %d (%d)\n",
833833
tid, ret);
834-
dma_unmap_single(ar->ab->dev, rx_tid->paddr, rx_tid->size,
835-
DMA_BIDIRECTIONAL);
836-
kfree(rx_tid->vaddr);
837-
rx_tid->vaddr = NULL;
834+
dma_free_noncoherent(ar->ab->dev, rx_tid->unaligned_size,
835+
rx_tid->vaddr_unaligned,
836+
rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
837+
rx_tid->vaddr_unaligned = NULL;
838838
}
839839

840840
rx_tid->paddr = 0;
841+
rx_tid->paddr_unaligned = 0;
841842
rx_tid->size = 0;
843+
rx_tid->unaligned_size = 0;
842844
}
843845

844846
static int ath11k_dp_rx_link_desc_return(struct ath11k_base *ab,
@@ -982,10 +984,9 @@ static void ath11k_dp_rx_tid_mem_free(struct ath11k_base *ab,
982984
if (!rx_tid->active)
983985
goto unlock_exit;
984986

985-
dma_unmap_single(ab->dev, rx_tid->paddr, rx_tid->size,
986-
DMA_BIDIRECTIONAL);
987-
kfree(rx_tid->vaddr);
988-
rx_tid->vaddr = NULL;
987+
dma_free_noncoherent(ab->dev, rx_tid->unaligned_size, rx_tid->vaddr_unaligned,
988+
rx_tid->paddr_unaligned, DMA_BIDIRECTIONAL);
989+
rx_tid->vaddr_unaligned = NULL;
989990

990991
rx_tid->active = false;
991992

@@ -1000,9 +1001,8 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
10001001
struct ath11k_base *ab = ar->ab;
10011002
struct ath11k_peer *peer;
10021003
struct dp_rx_tid *rx_tid;
1003-
u32 hw_desc_sz;
1004-
u32 *addr_aligned;
1005-
void *vaddr;
1004+
u32 hw_desc_sz, *vaddr;
1005+
void *vaddr_unaligned;
10061006
dma_addr_t paddr;
10071007
int ret;
10081008

@@ -1050,49 +1050,40 @@ int ath11k_peer_rx_tid_setup(struct ath11k *ar, const u8 *peer_mac, int vdev_id,
10501050
else
10511051
hw_desc_sz = ath11k_hal_reo_qdesc_size(DP_BA_WIN_SZ_MAX, tid);
10521052

1053-
vaddr = kzalloc(hw_desc_sz + HAL_LINK_DESC_ALIGN - 1, GFP_ATOMIC);
1054-
if (!vaddr) {
1053+
rx_tid->unaligned_size = hw_desc_sz + HAL_LINK_DESC_ALIGN - 1;
1054+
vaddr_unaligned = dma_alloc_noncoherent(ab->dev, rx_tid->unaligned_size, &paddr,
1055+
DMA_BIDIRECTIONAL, GFP_ATOMIC);
1056+
if (!vaddr_unaligned) {
10551057
spin_unlock_bh(&ab->base_lock);
10561058
return -ENOMEM;
10571059
}
10581060

1059-
addr_aligned = PTR_ALIGN(vaddr, HAL_LINK_DESC_ALIGN);
1060-
1061-
ath11k_hal_reo_qdesc_setup(addr_aligned, tid, ba_win_sz,
1062-
ssn, pn_type);
1063-
1064-
paddr = dma_map_single(ab->dev, addr_aligned, hw_desc_sz,
1065-
DMA_BIDIRECTIONAL);
1066-
1067-
ret = dma_mapping_error(ab->dev, paddr);
1068-
if (ret) {
1069-
spin_unlock_bh(&ab->base_lock);
1070-
ath11k_warn(ab, "failed to setup dma map for peer %pM rx tid %d: %d\n",
1071-
peer_mac, tid, ret);
1072-
goto err_mem_free;
1073-
}
1074-
1075-
rx_tid->vaddr = vaddr;
1076-
rx_tid->paddr = paddr;
1061+
rx_tid->vaddr_unaligned = vaddr_unaligned;
1062+
vaddr = PTR_ALIGN(vaddr_unaligned, HAL_LINK_DESC_ALIGN);
1063+
rx_tid->paddr_unaligned = paddr;
1064+
rx_tid->paddr = rx_tid->paddr_unaligned + ((unsigned long)vaddr -
1065+
(unsigned long)rx_tid->vaddr_unaligned);
1066+
ath11k_hal_reo_qdesc_setup(vaddr, tid, ba_win_sz, ssn, pn_type);
10771067
rx_tid->size = hw_desc_sz;
10781068
rx_tid->active = true;
10791069

1070+
/* After dma_alloc_noncoherent, vaddr is being modified for reo qdesc setup.
1071+
* Since these changes are not reflected in the device, driver now needs to
1072+
* explicitly call dma_sync_single_for_device.
1073+
*/
1074+
dma_sync_single_for_device(ab->dev, rx_tid->paddr,
1075+
rx_tid->size,
1076+
DMA_TO_DEVICE);
10801077
spin_unlock_bh(&ab->base_lock);
10811078

1082-
ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac,
1083-
paddr, tid, 1, ba_win_sz);
1079+
ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, peer_mac, rx_tid->paddr,
1080+
tid, 1, ba_win_sz);
10841081
if (ret) {
10851082
ath11k_warn(ar->ab, "failed to setup rx reorder queue for peer %pM tid %d: %d\n",
10861083
peer_mac, tid, ret);
10871084
ath11k_dp_rx_tid_mem_free(ab, peer_mac, vdev_id, tid);
10881085
}
10891086

1090-
return ret;
1091-
1092-
err_mem_free:
1093-
kfree(rx_tid->vaddr);
1094-
rx_tid->vaddr = NULL;
1095-
10961087
return ret;
10971088
}
10981089

0 commit comments

Comments
 (0)