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