xref: /dpdk/drivers/net/hinic/base/hinic_pmd_wq.c (revision 1b7b9f170fcebbbd0708fab554dcb5a7badef8cf)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Huawei Technologies Co., Ltd
3  */
4 
5 #include "hinic_compat.h"
6 #include "hinic_pmd_hwdev.h"
7 #include "hinic_pmd_wq.h"
8 
free_wq_pages(struct hinic_hwdev * hwdev,struct hinic_wq * wq)9 static void free_wq_pages(struct hinic_hwdev *hwdev, struct hinic_wq *wq)
10 {
11 	dma_free_coherent(hwdev, wq->wq_buf_size, (void *)wq->queue_buf_vaddr,
12 			(dma_addr_t)wq->queue_buf_paddr);
13 
14 	wq->queue_buf_paddr = 0;
15 	wq->queue_buf_vaddr = 0;
16 }
17 
alloc_wq_pages(struct hinic_hwdev * hwdev,struct hinic_wq * wq,unsigned int socket_id)18 static int alloc_wq_pages(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
19 			unsigned int socket_id)
20 {
21 	dma_addr_t dma_addr = 0;
22 
23 	wq->queue_buf_vaddr = (u64)(u64 *)
24 		dma_zalloc_coherent_aligned256k(hwdev, wq->wq_buf_size,
25 						&dma_addr, socket_id);
26 	if (!wq->queue_buf_vaddr) {
27 		PMD_DRV_LOG(ERR, "Failed to allocate wq page");
28 		return -ENOMEM;
29 	}
30 
31 	if (!ADDR_256K_ALIGNED(dma_addr)) {
32 		PMD_DRV_LOG(ERR, "Wqe pages is not 256k aligned!");
33 		dma_free_coherent(hwdev, wq->wq_buf_size,
34 				  (void *)wq->queue_buf_vaddr,
35 				  dma_addr);
36 		return -ENOMEM;
37 	}
38 	wq->queue_buf_paddr = dma_addr;
39 
40 	return 0;
41 }
42 
hinic_wq_allocate(struct hinic_hwdev * hwdev,struct hinic_wq * wq,u32 wqebb_shift,u16 q_depth,unsigned int socket_id)43 int hinic_wq_allocate(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
44 		      u32 wqebb_shift, u16 q_depth, unsigned int socket_id)
45 {
46 	int err;
47 
48 	if (q_depth & (q_depth - 1)) {
49 		PMD_DRV_LOG(ERR, "WQ q_depth isn't power of 2");
50 		return -EINVAL;
51 	}
52 
53 	wq->wqebb_size = 1 << wqebb_shift;
54 	wq->wqebb_shift = wqebb_shift;
55 	wq->wq_buf_size = ((u32)q_depth) << wqebb_shift;
56 	wq->q_depth = q_depth;
57 
58 	if (wq->wq_buf_size > (HINIC_PAGE_SIZE << HINIC_PAGE_SIZE_DPDK)) {
59 		PMD_DRV_LOG(ERR, "Invalid q_depth %u which one page_size can not hold",
60 			q_depth);
61 		return -EINVAL;
62 	}
63 
64 	err = alloc_wq_pages(hwdev, wq, socket_id);
65 	if (err) {
66 		PMD_DRV_LOG(ERR, "Failed to allocate wq pages");
67 		return err;
68 	}
69 
70 	wq->cons_idx = 0;
71 	wq->prod_idx = 0;
72 	wq->delta = q_depth;
73 	wq->mask = q_depth - 1;
74 
75 	return 0;
76 }
77 
hinic_wq_free(struct hinic_hwdev * hwdev,struct hinic_wq * wq)78 void hinic_wq_free(struct hinic_hwdev *hwdev, struct hinic_wq *wq)
79 {
80 	free_wq_pages(hwdev, wq);
81 }
82 
hinic_put_wqe(struct hinic_wq * wq,int num_wqebbs)83 void hinic_put_wqe(struct hinic_wq *wq, int num_wqebbs)
84 {
85 	wq->cons_idx += num_wqebbs;
86 	wq->delta += num_wqebbs;
87 }
88 
hinic_read_wqe(struct hinic_wq * wq,int num_wqebbs,u16 * cons_idx)89 void *hinic_read_wqe(struct hinic_wq *wq, int num_wqebbs, u16 *cons_idx)
90 {
91 	u16 curr_cons_idx;
92 
93 	if ((wq->delta + num_wqebbs) > wq->q_depth)
94 		return NULL;
95 
96 	curr_cons_idx = (u16)(wq->cons_idx);
97 
98 	curr_cons_idx = MASKED_WQE_IDX(wq, curr_cons_idx);
99 
100 	*cons_idx = curr_cons_idx;
101 
102 	return WQ_WQE_ADDR(wq, (u32)(*cons_idx));
103 }
104 
hinic_cmdq_alloc(struct hinic_wq * wq,struct hinic_hwdev * hwdev,int cmdq_blocks,u32 wq_buf_size,u32 wqebb_shift,u16 q_depth)105 int hinic_cmdq_alloc(struct hinic_wq *wq, struct hinic_hwdev *hwdev,
106 		     int cmdq_blocks, u32 wq_buf_size, u32 wqebb_shift,
107 		     u16 q_depth)
108 {
109 	int i, j, err = -ENOMEM;
110 
111 	/* validate q_depth is power of 2 & wqebb_size is not 0 */
112 	for (i = 0; i < cmdq_blocks; i++) {
113 		wq[i].wqebb_size = 1 << wqebb_shift;
114 		wq[i].wqebb_shift = wqebb_shift;
115 		wq[i].wq_buf_size = wq_buf_size;
116 		wq[i].q_depth = q_depth;
117 
118 		err = alloc_wq_pages(hwdev, &wq[i], SOCKET_ID_ANY);
119 		if (err) {
120 			PMD_DRV_LOG(ERR, "Failed to alloc CMDQ blocks");
121 			goto cmdq_block_err;
122 		}
123 
124 		wq[i].cons_idx = 0;
125 		wq[i].prod_idx = 0;
126 		wq[i].delta = q_depth;
127 
128 		wq[i].mask = q_depth - 1;
129 	}
130 
131 	return 0;
132 
133 cmdq_block_err:
134 	for (j = 0; j < i; j++)
135 		free_wq_pages(hwdev, &wq[j]);
136 
137 	return err;
138 }
139 
hinic_cmdq_free(struct hinic_hwdev * hwdev,struct hinic_wq * wq,int cmdq_blocks)140 void hinic_cmdq_free(struct hinic_hwdev *hwdev, struct hinic_wq *wq,
141 		     int cmdq_blocks)
142 {
143 	int i;
144 
145 	for (i = 0; i < cmdq_blocks; i++)
146 		free_wq_pages(hwdev, &wq[i]);
147 }
148 
hinic_wq_wqe_pg_clear(struct hinic_wq * wq)149 void hinic_wq_wqe_pg_clear(struct hinic_wq *wq)
150 {
151 	wq->cons_idx = 0;
152 	wq->prod_idx = 0;
153 
154 	memset((void *)wq->queue_buf_vaddr, 0, wq->wq_buf_size);
155 }
156 
hinic_get_wqe(struct hinic_wq * wq,int num_wqebbs,u16 * prod_idx)157 void *hinic_get_wqe(struct hinic_wq *wq, int num_wqebbs, u16 *prod_idx)
158 {
159 	u16 curr_prod_idx;
160 
161 	wq->delta -= num_wqebbs;
162 	curr_prod_idx = wq->prod_idx;
163 	wq->prod_idx += num_wqebbs;
164 	*prod_idx = MASKED_WQE_IDX(wq, curr_prod_idx);
165 
166 	return WQ_WQE_ADDR(wq, (u32)(*prod_idx));
167 }
168 
169 /**
170  * hinic_set_sge - set dma area in scatter gather entry
171  * @sge: scatter gather entry
172  * @addr: dma address
173  * @len: length of relevant data in the dma address
174  **/
hinic_set_sge(struct hinic_sge * sge,dma_addr_t addr,u32 len)175 void hinic_set_sge(struct hinic_sge *sge, dma_addr_t addr, u32 len)
176 {
177 	sge->hi_addr = upper_32_bits(addr);
178 	sge->lo_addr = lower_32_bits(addr);
179 	sge->len  = len;
180 }
181