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
hinic3_queue_pages_init(struct hinic3_queue_pages * qpages,u32 q_depth,u32 page_size,u32 elem_size)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
__queue_pages_free(struct hinic3_hwdev * hwdev,struct hinic3_queue_pages * qpages,u32 pg_cnt)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
hinic3_queue_pages_free(struct hinic3_hwdev * hwdev,struct hinic3_queue_pages * qpages)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
hinic3_queue_pages_alloc(struct hinic3_hwdev * hwdev,struct hinic3_queue_pages * qpages,u32 align)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