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 ;
804804free_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
811811void 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
844846static 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