1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. 3 4 #include <linux/delay.h> 5 #include <linux/dma-mapping.h> 6 7 #include "hinic3_common.h" 8 9 int hinic3_dma_zalloc_coherent_align(struct device *dev, u32 size, u32 align, 10 gfp_t flag, 11 struct hinic3_dma_addr_align *mem_align) 12 { 13 dma_addr_t paddr, align_paddr; 14 void *vaddr, *align_vaddr; 15 u32 real_size = size; 16 17 vaddr = dma_alloc_coherent(dev, real_size, &paddr, flag); 18 if (!vaddr) 19 return -ENOMEM; 20 21 align_paddr = ALIGN(paddr, align); 22 if (align_paddr == paddr) { 23 align_vaddr = vaddr; 24 goto out; 25 } 26 27 dma_free_coherent(dev, real_size, vaddr, paddr); 28 29 /* realloc memory for align */ 30 real_size = size + align; 31 vaddr = dma_alloc_coherent(dev, real_size, &paddr, flag); 32 if (!vaddr) 33 return -ENOMEM; 34 35 align_paddr = ALIGN(paddr, align); 36 align_vaddr = vaddr + (align_paddr - paddr); 37 38 out: 39 mem_align->real_size = real_size; 40 mem_align->ori_vaddr = vaddr; 41 mem_align->ori_paddr = paddr; 42 mem_align->align_vaddr = align_vaddr; 43 mem_align->align_paddr = align_paddr; 44 45 return 0; 46 } 47 48 void hinic3_dma_free_coherent_align(struct device *dev, 49 struct hinic3_dma_addr_align *mem_align) 50 { 51 dma_free_coherent(dev, mem_align->real_size, 52 mem_align->ori_vaddr, mem_align->ori_paddr); 53 } 54