1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved. 3 4 #include <linux/device.h> 5 6 #include "hinic3_hwdev.h" 7 #include "hinic3_queue_common.h" 8 9 void hinic3_queue_pages_init(struct hinic3_queue_pages *qpages, u32 q_depth, 10 u32 page_size, u32 elem_size) 11 { 12 u32 elem_per_page; 13 14 elem_per_page = min(page_size / elem_size, q_depth); 15 16 qpages->pages = NULL; 17 qpages->page_size = page_size; 18 qpages->num_pages = max(q_depth / elem_per_page, 1); 19 qpages->elem_size_shift = ilog2(elem_size); 20 qpages->elem_per_pg_shift = ilog2(elem_per_page); 21 } 22 23 static void __queue_pages_free(struct hinic3_hwdev *hwdev, 24 struct hinic3_queue_pages *qpages, u32 pg_cnt) 25 { 26 while (pg_cnt > 0) { 27 pg_cnt--; 28 hinic3_dma_free_coherent_align(hwdev->dev, 29 qpages->pages + pg_cnt); 30 } 31 kfree(qpages->pages); 32 qpages->pages = NULL; 33 } 34 35 void hinic3_queue_pages_free(struct hinic3_hwdev *hwdev, 36 struct hinic3_queue_pages *qpages) 37 { 38 __queue_pages_free(hwdev, qpages, qpages->num_pages); 39 } 40 41 int hinic3_queue_pages_alloc(struct hinic3_hwdev *hwdev, 42 struct hinic3_queue_pages *qpages, u32 align) 43 { 44 u32 pg_idx; 45 int err; 46 47 qpages->pages = kcalloc(qpages->num_pages, sizeof(qpages->pages[0]), 48 GFP_KERNEL); 49 if (!qpages->pages) 50 return -ENOMEM; 51 52 if (align == 0) 53 align = qpages->page_size; 54 55 for (pg_idx = 0; pg_idx < qpages->num_pages; pg_idx++) { 56 err = hinic3_dma_zalloc_coherent_align(hwdev->dev, 57 qpages->page_size, 58 align, 59 GFP_KERNEL, 60 qpages->pages + pg_idx); 61 if (err) { 62 __queue_pages_free(hwdev, qpages, pg_idx); 63 return err; 64 } 65 } 66 67 return 0; 68 } 69