Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2021 Marvell International Ltd.
3 : : */
4 : :
5 : : #include <rte_vect.h>
6 : :
7 : : #include "cnxk_dmadev.h"
8 : :
9 : : static __plt_always_inline void
10 : : __dpi_cpy_scalar(uint64_t *src, uint64_t *dst, uint8_t n)
11 : : {
12 : : uint8_t i;
13 : :
14 [ # # # # : 0 : for (i = 0; i < n; i++)
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
15 : 0 : dst[i] = src[i];
16 : : }
17 : :
18 : : #if defined(RTE_ARCH_ARM64)
19 : : static __plt_always_inline void
20 : : __dpi_cpy_vector(uint64_t *src, uint64_t *dst, uint8_t n)
21 : : {
22 : : uint64x2_t vec;
23 : : uint8_t i;
24 : :
25 : : for (i = 0; i < n; i += 2) {
26 : : vec = vld1q_u64((const uint64_t *)&src[i]);
27 : : vst1q_u64(&dst[i], vec);
28 : : }
29 : : }
30 : :
31 : : static __plt_always_inline void
32 : : __dpi_cpy_vector_sg(const struct rte_dma_sge *src, uint64_t *dst, uint16_t n)
33 : : {
34 : : uint64x2_t mask = {0xFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL};
35 : : uint64x2_t vec;
36 : : uint8_t i;
37 : :
38 : : for (i = 0; i < n; i++) {
39 : : vec = vld1q_u64((const uint64_t *)&src[i]);
40 : : vec = vextq_u64(vec, vec, 1);
41 : : vec = vandq_u64(vec, mask);
42 : : vst1q_u64(dst, vec);
43 : : dst += 2;
44 : : }
45 : : }
46 : :
47 : : static __plt_always_inline uint8_t
48 : : __dpi_cpy_vector_sg_lmt(const struct rte_dma_sge *src, uint64_t *dst, uint16_t n, uint16_t lmt)
49 : : {
50 : : uint64x2_t mask = {0xFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL};
51 : : uint64x2_t vec;
52 : : uint8_t i;
53 : :
54 : : for (i = 0; i < n && lmt; i++) {
55 : : vec = vld1q_u64((const uint64_t *)&src[i]);
56 : : vec = vextq_u64(vec, vec, 1);
57 : : vec = vandq_u64(vec, mask);
58 : : vst1q_u64(dst, vec);
59 : : dst += 2;
60 : : lmt -= 2;
61 : : }
62 : :
63 : : return i;
64 : : }
65 : : #else
66 : : static __plt_always_inline void
67 : : __dpi_cpy_scalar_sg(const struct rte_dma_sge *src, uint64_t *dst, uint16_t n)
68 : : {
69 : : uint8_t i;
70 : :
71 [ # # # # : 0 : for (i = 0; i < n; i++) {
# # # # #
# # # # #
# # ]
72 : 0 : *dst++ = src[i].length;
73 : 0 : *dst++ = src[i].addr;
74 : : }
75 : : }
76 : :
77 : : static __plt_always_inline uint8_t
78 : : __dpi_cpy_scalar_sg_lmt(const struct rte_dma_sge *src, uint64_t *dst, uint16_t n, uint16_t lmt)
79 : : {
80 : : uint8_t i;
81 : :
82 [ # # # # : 0 : for (i = 0; i < n && lmt; i++) {
# # # # #
# # # # #
# # ]
83 : 0 : *dst++ = src[i].length;
84 : 0 : *dst++ = src[i].addr;
85 : 0 : lmt -= 2;
86 : : }
87 : :
88 : : return i;
89 : : }
90 : : #endif
91 : :
92 : : static __plt_always_inline void
93 : : __dpi_cpy(uint64_t *src, uint64_t *dst, uint8_t n)
94 : : {
95 : : #if defined(RTE_ARCH_ARM64)
96 : : __dpi_cpy_vector(src, dst, n);
97 : : #else
98 : : __dpi_cpy_scalar(src, dst, n);
99 : : #endif
100 : : }
101 : :
102 : : static __plt_always_inline void
103 : : __dpi_cpy_sg(const struct rte_dma_sge *src, uint64_t *dst, uint16_t n)
104 : : {
105 : : #if defined(RTE_ARCH_ARM64)
106 : : __dpi_cpy_vector_sg(src, dst, n);
107 : : #else
108 : : __dpi_cpy_scalar_sg(src, dst, n);
109 : : #endif
110 : : }
111 : :
112 : : static __plt_always_inline uint8_t
113 : : __dpi_cpy_sg_lmt(const struct rte_dma_sge *src, uint64_t *dst, uint16_t n, uint16_t lmt)
114 : : {
115 : : #if defined(RTE_ARCH_ARM64)
116 : : return __dpi_cpy_vector_sg_lmt(src, dst, n, lmt);
117 : : #else
118 : : return __dpi_cpy_scalar_sg_lmt(src, dst, n, lmt);
119 : : #endif
120 : : }
121 : :
122 : : static __plt_always_inline int
123 : : __dpi_queue_write_single(struct cnxk_dpi_vf_s *dpi, uint64_t *cmd)
124 : : {
125 : 0 : uint64_t *ptr = dpi->chunk_base;
126 : :
127 : : /* Check if command fits in the current chunk. */
128 [ # # ]: 0 : if (dpi->chunk_head + CNXK_DPI_DW_PER_SINGLE_CMD < dpi->chunk_size_m1) {
129 : 0 : ptr += dpi->chunk_head;
130 : :
131 : : __dpi_cpy_scalar(cmd, ptr, CNXK_DPI_DW_PER_SINGLE_CMD);
132 : 0 : dpi->chunk_head += CNXK_DPI_DW_PER_SINGLE_CMD;
133 : : } else {
134 : 0 : uint64_t *new_buff = NULL;
135 : : int count;
136 : :
137 [ # # # # : 0 : if (rte_mempool_get(dpi->chunk_pool, (void **)&new_buff) < 0) {
# # # # ]
138 : 0 : plt_dpi_dbg("Failed to alloc next buffer from NPA");
139 : 0 : return -ENOSPC;
140 : : }
141 : :
142 : : /*
143 : : * Figure out how many cmd words will fit in the current chunk
144 : : * and copy them.
145 : : */
146 : 0 : count = dpi->chunk_size_m1 - dpi->chunk_head;
147 : 0 : ptr += dpi->chunk_head;
148 : :
149 : 0 : __dpi_cpy_scalar(cmd, ptr, count);
150 : :
151 : 0 : ptr += count;
152 : 0 : *ptr = (uint64_t)new_buff;
153 : : ptr = new_buff;
154 : :
155 : : /* Copy the remaining cmd words to new chunk. */
156 : 0 : __dpi_cpy_scalar(cmd + count, ptr, CNXK_DPI_DW_PER_SINGLE_CMD - count);
157 : :
158 : 0 : dpi->chunk_base = new_buff;
159 : 0 : dpi->chunk_head = CNXK_DPI_DW_PER_SINGLE_CMD - count;
160 : : }
161 : :
162 : : return 0;
163 : : }
164 : :
165 : : static __plt_always_inline int
166 : : __dpi_queue_write_sg(struct cnxk_dpi_vf_s *dpi, uint64_t *hdr, const struct rte_dma_sge *src,
167 : : const struct rte_dma_sge *dst, uint16_t nb_src, uint16_t nb_dst)
168 : : {
169 : 0 : uint8_t cmd_len = CNXK_DPI_CMD_LEN(nb_src, nb_dst);
170 : 0 : uint64_t *ptr = dpi->chunk_base;
171 : :
172 : : /* Check if command fits in the current chunk. */
173 : 0 : if (dpi->chunk_head + cmd_len < dpi->chunk_size_m1) {
174 : 0 : ptr += dpi->chunk_head;
175 : :
176 : : __dpi_cpy(hdr, ptr, CNXK_DPI_HDR_LEN);
177 : 0 : ptr += CNXK_DPI_HDR_LEN;
178 : : __dpi_cpy_sg(src, ptr, nb_src);
179 : 0 : ptr += (nb_src << 1);
180 : : __dpi_cpy_sg(dst, ptr, nb_dst);
181 : :
182 : 0 : dpi->chunk_head += cmd_len;
183 : : } else {
184 : 0 : uint64_t *new_buff = NULL, *buf;
185 : : uint16_t count;
186 : :
187 [ # # # # : 0 : if (rte_mempool_get(dpi->chunk_pool, (void **)&new_buff) < 0) {
# # # # ]
188 : 0 : plt_dpi_dbg("Failed to alloc next buffer from NPA");
189 : 0 : return -ENOSPC;
190 : : }
191 : :
192 : : /*
193 : : * Figure out how many cmd words will fit in the current chunk
194 : : * and copy them, copy the rest to the new buffer.
195 : : */
196 : 0 : count = dpi->chunk_size_m1 - dpi->chunk_head;
197 : 0 : ptr += dpi->chunk_head;
198 : 0 : buf = new_buff;
199 [ # # # # ]: 0 : if (count <= 4) {
200 : 0 : __dpi_cpy(hdr, ptr, count);
201 : 0 : ptr += count;
202 : : __dpi_cpy(&hdr[count], buf, 4);
203 : 0 : buf += (4 - count);
204 : : } else {
205 : : uint8_t i;
206 : :
207 : : __dpi_cpy(hdr, ptr, 4);
208 : 0 : ptr += 4;
209 : 0 : count -= 4;
210 : :
211 : : i = __dpi_cpy_sg_lmt(src, ptr, nb_src, count);
212 : 0 : src += i;
213 : 0 : nb_src -= i;
214 : 0 : count -= (i << 1);
215 : 0 : ptr += (i << 1);
216 : :
217 : : i = __dpi_cpy_sg_lmt(dst, ptr, nb_dst, count);
218 : 0 : dst += i;
219 : 0 : nb_dst -= i;
220 : 0 : ptr += (i << 1);
221 : : }
222 : 0 : *ptr = (uint64_t)new_buff;
223 : :
224 : 0 : __dpi_cpy_sg(src, buf, nb_src);
225 : 0 : buf += (nb_src << 1);
226 : :
227 : 0 : __dpi_cpy_sg(dst, buf, nb_dst);
228 : 0 : buf += (nb_dst << 1);
229 : :
230 : 0 : dpi->chunk_base = new_buff;
231 : 0 : dpi->chunk_head = buf - new_buff;
232 : : }
233 : :
234 : : return 0;
235 : : }
236 : :
237 : : int
238 : 0 : cnxk_dmadev_copy(void *dev_private, uint16_t vchan, rte_iova_t src, rte_iova_t dst, uint32_t length,
239 : : uint64_t flags)
240 : : {
241 : : struct cnxk_dpi_vf_s *dpivf = dev_private;
242 : 0 : struct cnxk_dpi_conf *dpi_conf = &dpivf->conf[vchan];
243 : : uint64_t cmd[CNXK_DPI_DW_PER_SINGLE_CMD];
244 : : struct cnxk_dpi_compl_s *comp_ptr;
245 : : int rc;
246 : :
247 [ # # ]: 0 : if (unlikely(((dpi_conf->c_desc.tail + 1) & dpi_conf->c_desc.max_cnt) ==
248 : : dpi_conf->c_desc.head))
249 : : return -ENOSPC;
250 : :
251 : 0 : comp_ptr = dpi_conf->c_desc.compl_ptr[dpi_conf->c_desc.tail];
252 : 0 : CNXK_DPI_STRM_INC(dpi_conf->c_desc, tail);
253 : :
254 : 0 : cmd[0] = (1UL << 54) | (1UL << 48);
255 : 0 : cmd[1] = dpi_conf->cmd.u | ((flags & RTE_DMA_OP_FLAG_AUTO_FREE) << 37);
256 : 0 : cmd[2] = (uint64_t)comp_ptr;
257 : 0 : cmd[4] = length;
258 : 0 : cmd[6] = length;
259 : :
260 : : /*
261 : : * For inbound case, src pointers are last pointers.
262 : : * For all other cases, src pointers are first pointers.
263 : : */
264 [ # # ]: 0 : if (((dpi_conf->cmd.u >> 48) & DPI_HDR_XTYPE_MASK) == DPI_XTYPE_INBOUND) {
265 : 0 : cmd[5] = dst;
266 : 0 : cmd[7] = src;
267 : : } else {
268 : 0 : cmd[5] = src;
269 : 0 : cmd[7] = dst;
270 : : }
271 : :
272 : : rc = __dpi_queue_write_single(dpivf, cmd);
273 [ # # ]: 0 : if (unlikely(rc)) {
274 [ # # ]: 0 : CNXK_DPI_STRM_DEC(dpi_conf->c_desc, tail);
275 : 0 : return rc;
276 : : }
277 : :
278 [ # # ]: 0 : if (flags & RTE_DMA_OP_FLAG_SUBMIT) {
279 : : rte_wmb();
280 : 0 : plt_write64(dpi_conf->pnum_words + CNXK_DPI_DW_PER_SINGLE_CMD,
281 : : dpivf->rdpi.rbase + DPI_VDMA_DBELL);
282 : 0 : dpi_conf->stats.submitted += dpi_conf->pending + 1;
283 : 0 : dpi_conf->pnum_words = 0;
284 : 0 : dpi_conf->pending = 0;
285 : : } else {
286 : 0 : dpi_conf->pnum_words += CNXK_DPI_DW_PER_SINGLE_CMD;
287 : 0 : dpi_conf->pending++;
288 : : }
289 : :
290 : 0 : return dpi_conf->desc_idx++;
291 : : }
292 : :
293 : : int
294 : 0 : cnxk_dmadev_copy_sg(void *dev_private, uint16_t vchan, const struct rte_dma_sge *src,
295 : : const struct rte_dma_sge *dst, uint16_t nb_src, uint16_t nb_dst, uint64_t flags)
296 : : {
297 : : struct cnxk_dpi_vf_s *dpivf = dev_private;
298 : 0 : struct cnxk_dpi_conf *dpi_conf = &dpivf->conf[vchan];
299 : : const struct rte_dma_sge *fptr, *lptr;
300 : : struct cnxk_dpi_compl_s *comp_ptr;
301 : : uint64_t hdr[4];
302 : : int rc;
303 : :
304 [ # # ]: 0 : if (unlikely(((dpi_conf->c_desc.tail + 1) & dpi_conf->c_desc.max_cnt) ==
305 : : dpi_conf->c_desc.head))
306 : : return -ENOSPC;
307 : :
308 : 0 : comp_ptr = dpi_conf->c_desc.compl_ptr[dpi_conf->c_desc.tail];
309 : 0 : CNXK_DPI_STRM_INC(dpi_conf->c_desc, tail);
310 : :
311 : 0 : hdr[1] = dpi_conf->cmd.u | ((flags & RTE_DMA_OP_FLAG_AUTO_FREE) << 37);
312 : 0 : hdr[2] = (uint64_t)comp_ptr;
313 : :
314 : : /*
315 : : * For inbound case, src pointers are last pointers.
316 : : * For all other cases, src pointers are first pointers.
317 : : */
318 [ # # ]: 0 : if (((dpi_conf->cmd.u >> 48) & DPI_HDR_XTYPE_MASK) == DPI_XTYPE_INBOUND) {
319 : : fptr = dst;
320 : : lptr = src;
321 : : RTE_SWAP(nb_src, nb_dst);
322 : : } else {
323 : : fptr = src;
324 : : lptr = dst;
325 : : }
326 : 0 : hdr[0] = ((uint64_t)nb_dst << 54) | (uint64_t)nb_src << 48;
327 : :
328 [ # # ]: 0 : rc = __dpi_queue_write_sg(dpivf, hdr, fptr, lptr, nb_src, nb_dst);
329 [ # # ]: 0 : if (unlikely(rc)) {
330 [ # # ]: 0 : CNXK_DPI_STRM_DEC(dpi_conf->c_desc, tail);
331 : 0 : return rc;
332 : : }
333 : :
334 [ # # ]: 0 : if (flags & RTE_DMA_OP_FLAG_SUBMIT) {
335 : : rte_wmb();
336 : 0 : plt_write64(dpi_conf->pnum_words + CNXK_DPI_CMD_LEN(nb_src, nb_dst),
337 : : dpivf->rdpi.rbase + DPI_VDMA_DBELL);
338 : 0 : dpi_conf->stats.submitted += dpi_conf->pending + 1;
339 : 0 : dpi_conf->pnum_words = 0;
340 : 0 : dpi_conf->pending = 0;
341 : : } else {
342 : 0 : dpi_conf->pnum_words += CNXK_DPI_CMD_LEN(nb_src, nb_dst);
343 : 0 : dpi_conf->pending++;
344 : : }
345 : :
346 : 0 : return dpi_conf->desc_idx++;
347 : : }
348 : :
349 : : int
350 : 0 : cn10k_dmadev_copy(void *dev_private, uint16_t vchan, rte_iova_t src, rte_iova_t dst,
351 : : uint32_t length, uint64_t flags)
352 : : {
353 : : struct cnxk_dpi_vf_s *dpivf = dev_private;
354 : 0 : struct cnxk_dpi_conf *dpi_conf = &dpivf->conf[vchan];
355 : : uint64_t cmd[CNXK_DPI_DW_PER_SINGLE_CMD];
356 : : struct cnxk_dpi_compl_s *comp_ptr;
357 : : int rc;
358 : :
359 [ # # ]: 0 : if (unlikely(((dpi_conf->c_desc.tail + 1) & dpi_conf->c_desc.max_cnt) ==
360 : : dpi_conf->c_desc.head))
361 : : return -ENOSPC;
362 : :
363 : 0 : comp_ptr = dpi_conf->c_desc.compl_ptr[dpi_conf->c_desc.tail];
364 : 0 : CNXK_DPI_STRM_INC(dpi_conf->c_desc, tail);
365 : :
366 : 0 : cmd[0] = dpi_conf->cmd.u | (1U << 6) | 1U;
367 : 0 : cmd[1] = (uint64_t)comp_ptr;
368 : 0 : cmd[2] = (1UL << 47) | ((flags & RTE_DMA_OP_FLAG_AUTO_FREE) << 43);
369 : 0 : cmd[4] = length;
370 : 0 : cmd[5] = src;
371 : 0 : cmd[6] = length;
372 [ # # ]: 0 : cmd[7] = dst;
373 : :
374 : : rc = __dpi_queue_write_single(dpivf, cmd);
375 [ # # ]: 0 : if (unlikely(rc)) {
376 [ # # ]: 0 : CNXK_DPI_STRM_DEC(dpi_conf->c_desc, tail);
377 : 0 : return rc;
378 : : }
379 : :
380 [ # # ]: 0 : if (flags & RTE_DMA_OP_FLAG_SUBMIT) {
381 : : rte_wmb();
382 : 0 : plt_write64(dpi_conf->pnum_words + CNXK_DPI_DW_PER_SINGLE_CMD,
383 : : dpivf->rdpi.rbase + DPI_VDMA_DBELL);
384 : 0 : dpi_conf->stats.submitted += dpi_conf->pending + 1;
385 : 0 : dpi_conf->pnum_words = 0;
386 : 0 : dpi_conf->pending = 0;
387 : : } else {
388 : 0 : dpi_conf->pnum_words += 8;
389 : 0 : dpi_conf->pending++;
390 : : }
391 : :
392 : 0 : return dpi_conf->desc_idx++;
393 : : }
394 : :
395 : : int
396 : 0 : cn10k_dmadev_copy_sg(void *dev_private, uint16_t vchan, const struct rte_dma_sge *src,
397 : : const struct rte_dma_sge *dst, uint16_t nb_src, uint16_t nb_dst,
398 : : uint64_t flags)
399 : : {
400 : : struct cnxk_dpi_vf_s *dpivf = dev_private;
401 : 0 : struct cnxk_dpi_conf *dpi_conf = &dpivf->conf[vchan];
402 : : struct cnxk_dpi_compl_s *comp_ptr;
403 : : uint64_t hdr[4];
404 : : int rc;
405 : :
406 [ # # ]: 0 : if (unlikely(((dpi_conf->c_desc.tail + 1) & dpi_conf->c_desc.max_cnt) ==
407 : : dpi_conf->c_desc.head))
408 : : return -ENOSPC;
409 : :
410 : 0 : comp_ptr = dpi_conf->c_desc.compl_ptr[dpi_conf->c_desc.tail];
411 : 0 : CNXK_DPI_STRM_INC(dpi_conf->c_desc, tail);
412 : :
413 : 0 : hdr[0] = dpi_conf->cmd.u | (nb_dst << 6) | nb_src;
414 : 0 : hdr[1] = (uint64_t)comp_ptr;
415 : 0 : hdr[2] = (1UL << 47) | ((flags & RTE_DMA_OP_FLAG_AUTO_FREE) << 43);
416 : :
417 [ # # ]: 0 : rc = __dpi_queue_write_sg(dpivf, hdr, src, dst, nb_src, nb_dst);
418 [ # # ]: 0 : if (unlikely(rc)) {
419 [ # # ]: 0 : CNXK_DPI_STRM_DEC(dpi_conf->c_desc, tail);
420 : 0 : return rc;
421 : : }
422 : :
423 [ # # ]: 0 : if (flags & RTE_DMA_OP_FLAG_SUBMIT) {
424 : : rte_wmb();
425 : 0 : plt_write64(dpi_conf->pnum_words + CNXK_DPI_CMD_LEN(nb_src, nb_dst),
426 : : dpivf->rdpi.rbase + DPI_VDMA_DBELL);
427 : 0 : dpi_conf->stats.submitted += dpi_conf->pending + 1;
428 : 0 : dpi_conf->pnum_words = 0;
429 : 0 : dpi_conf->pending = 0;
430 : : } else {
431 : 0 : dpi_conf->pnum_words += CNXK_DPI_CMD_LEN(nb_src, nb_dst);
432 : 0 : dpi_conf->pending++;
433 : : }
434 : :
435 : 0 : return dpi_conf->desc_idx++;
436 : : }
|