Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2018-2022 NXP
3 : : */
4 : :
5 : : #include <rte_eal.h>
6 : : #include <bus_fslmc_driver.h>
7 : : #include <rte_dmadev.h>
8 : : #include <rte_dmadev_pmd.h>
9 : : #include <rte_kvargs.h>
10 : :
11 : : #include <mc/fsl_dpdmai.h>
12 : :
13 : : #include "rte_pmd_dpaa2_qdma.h"
14 : : #include "dpaa2_qdma.h"
15 : : #include "dpaa2_qdma_logs.h"
16 : :
17 : : #define DPAA2_QDMA_PREFETCH "prefetch"
18 : :
19 : : uint32_t dpaa2_coherent_no_alloc_cache;
20 : : uint32_t dpaa2_coherent_alloc_cache;
21 : :
22 : : static inline int
23 : : qdma_populate_fd_pci(phys_addr_t src, phys_addr_t dest,
24 : : uint32_t len, struct qbman_fd *fd,
25 : : struct rte_dpaa2_qdma_rbp *rbp, int ser)
26 : : {
27 : 0 : fd->simple_pci.saddr_lo = lower_32_bits((uint64_t) (src));
28 : 0 : fd->simple_pci.saddr_hi = upper_32_bits((uint64_t) (src));
29 : :
30 : 0 : fd->simple_pci.len_sl = len;
31 : :
32 : 0 : fd->simple_pci.bmt = 1;
33 : 0 : fd->simple_pci.fmt = 3;
34 : 0 : fd->simple_pci.sl = 1;
35 : 0 : fd->simple_pci.ser = ser;
36 : :
37 : 0 : fd->simple_pci.sportid = rbp->sportid; /*pcie 3 */
38 : 0 : fd->simple_pci.srbp = rbp->srbp;
39 : 0 : if (rbp->srbp)
40 : 0 : fd->simple_pci.rdttype = 0;
41 : : else
42 : 0 : fd->simple_pci.rdttype = dpaa2_coherent_alloc_cache;
43 : :
44 : : /*dest is pcie memory */
45 : 0 : fd->simple_pci.dportid = rbp->dportid; /*pcie 3 */
46 : 0 : fd->simple_pci.drbp = rbp->drbp;
47 [ # # ]: 0 : if (rbp->drbp)
48 : 0 : fd->simple_pci.wrttype = 0;
49 : : else
50 : 0 : fd->simple_pci.wrttype = dpaa2_coherent_no_alloc_cache;
51 : :
52 : 0 : fd->simple_pci.daddr_lo = lower_32_bits((uint64_t) (dest));
53 : 0 : fd->simple_pci.daddr_hi = upper_32_bits((uint64_t) (dest));
54 : :
55 : : return 0;
56 : : }
57 : :
58 : : static inline int
59 : : qdma_populate_fd_ddr(phys_addr_t src, phys_addr_t dest,
60 : : uint32_t len, struct qbman_fd *fd, int ser)
61 : : {
62 : 0 : fd->simple_ddr.saddr_lo = lower_32_bits((uint64_t) (src));
63 : 0 : fd->simple_ddr.saddr_hi = upper_32_bits((uint64_t) (src));
64 : :
65 : 0 : fd->simple_ddr.len = len;
66 : :
67 : 0 : fd->simple_ddr.bmt = 1;
68 : 0 : fd->simple_ddr.fmt = 3;
69 : 0 : fd->simple_ddr.sl = 1;
70 : 0 : fd->simple_ddr.ser = ser;
71 : : /**
72 : : * src If RBP=0 {NS,RDTTYPE[3:0]}: 0_1011
73 : : * Coherent copy of cacheable memory,
74 : : * lookup in downstream cache, no allocate
75 : : * on miss
76 : : */
77 : 0 : fd->simple_ddr.rns = 0;
78 : 0 : fd->simple_ddr.rdttype = dpaa2_coherent_alloc_cache;
79 : : /**
80 : : * dest If RBP=0 {NS,WRTTYPE[3:0]}: 0_0111
81 : : * Coherent write of cacheable memory,
82 : : * lookup in downstream cache, no allocate on miss
83 : : */
84 : 0 : fd->simple_ddr.wns = 0;
85 : 0 : fd->simple_ddr.wrttype = dpaa2_coherent_no_alloc_cache;
86 : :
87 : 0 : fd->simple_ddr.daddr_lo = lower_32_bits((uint64_t) (dest));
88 : 0 : fd->simple_ddr.daddr_hi = upper_32_bits((uint64_t) (dest));
89 : :
90 : : return 0;
91 : : }
92 : :
93 : : static void
94 : 0 : dpaa2_qdma_populate_fle(struct qbman_fle *fle,
95 : : uint64_t fle_iova,
96 : : struct rte_dpaa2_qdma_rbp *rbp,
97 : : uint64_t src, uint64_t dest,
98 : : size_t len, uint32_t flags, uint32_t fmt)
99 : : {
100 : : struct qdma_sdd *sdd;
101 : : uint64_t sdd_iova;
102 : :
103 : 0 : sdd = (struct qdma_sdd *)
104 : 0 : ((uintptr_t)(uint64_t)fle - QDMA_FLE_FLE_OFFSET +
105 : : QDMA_FLE_SDD_OFFSET);
106 : 0 : sdd_iova = fle_iova - QDMA_FLE_FLE_OFFSET + QDMA_FLE_SDD_OFFSET;
107 : :
108 : : /* first frame list to source descriptor */
109 : 0 : DPAA2_SET_FLE_ADDR(fle, sdd_iova);
110 : 0 : DPAA2_SET_FLE_LEN(fle, (2 * (sizeof(struct qdma_sdd))));
111 : :
112 : : /* source and destination descriptor */
113 [ # # # # ]: 0 : if (rbp && rbp->enable) {
114 : : /* source */
115 : 0 : sdd->read_cmd.portid = rbp->sportid;
116 : 0 : sdd->rbpcmd_simple.pfid = rbp->spfid;
117 : 0 : sdd->rbpcmd_simple.vfa = rbp->vfa;
118 : 0 : sdd->rbpcmd_simple.vfid = rbp->svfid;
119 : :
120 [ # # ]: 0 : if (rbp->srbp) {
121 : 0 : sdd->read_cmd.rbp = rbp->srbp;
122 : 0 : sdd->read_cmd.rdtype = DPAA2_RBP_MEM_RW;
123 : : } else {
124 : 0 : sdd->read_cmd.rdtype = dpaa2_coherent_no_alloc_cache;
125 : : }
126 : : sdd++;
127 : : /* destination */
128 : 0 : sdd->write_cmd.portid = rbp->dportid;
129 : 0 : sdd->rbpcmd_simple.pfid = rbp->dpfid;
130 : 0 : sdd->rbpcmd_simple.vfa = rbp->vfa;
131 : 0 : sdd->rbpcmd_simple.vfid = rbp->dvfid;
132 : :
133 [ # # ]: 0 : if (rbp->drbp) {
134 : 0 : sdd->write_cmd.rbp = rbp->drbp;
135 : 0 : sdd->write_cmd.wrttype = DPAA2_RBP_MEM_RW;
136 : : } else {
137 : 0 : sdd->write_cmd.wrttype = dpaa2_coherent_alloc_cache;
138 : : }
139 : :
140 : : } else {
141 : 0 : sdd->read_cmd.rdtype = dpaa2_coherent_no_alloc_cache;
142 : : sdd++;
143 : 0 : sdd->write_cmd.wrttype = dpaa2_coherent_alloc_cache;
144 : : }
145 : : fle++;
146 : : /* source frame list to source buffer */
147 [ # # ]: 0 : if (flags & RTE_DPAA2_QDMA_JOB_SRC_PHY) {
148 : 0 : DPAA2_SET_FLE_ADDR(fle, src);
149 : : #ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
150 : 0 : DPAA2_SET_FLE_BMT(fle);
151 : : #endif
152 : : } else {
153 : 0 : DPAA2_SET_FLE_ADDR(fle, DPAA2_VADDR_TO_IOVA(src));
154 : : }
155 : 0 : fle->word4.fmt = fmt;
156 : 0 : DPAA2_SET_FLE_LEN(fle, len);
157 : :
158 : : fle++;
159 : : /* destination frame list to destination buffer */
160 [ # # ]: 0 : if (flags & RTE_DPAA2_QDMA_JOB_DEST_PHY) {
161 : : #ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
162 : 0 : DPAA2_SET_FLE_BMT(fle);
163 : : #endif
164 : 0 : DPAA2_SET_FLE_ADDR(fle, dest);
165 : : } else {
166 : 0 : DPAA2_SET_FLE_ADDR(fle, DPAA2_VADDR_TO_IOVA(dest));
167 : : }
168 : 0 : fle->word4.fmt = fmt;
169 : 0 : DPAA2_SET_FLE_LEN(fle, len);
170 : :
171 : : /* Final bit: 1, for last frame list */
172 : 0 : DPAA2_SET_FLE_FIN(fle);
173 : 0 : }
174 : :
175 : : static inline int
176 : 0 : dpdmai_dev_set_fd_us(struct qdma_virt_queue *qdma_vq,
177 : : struct qbman_fd *fd,
178 : : struct rte_dpaa2_qdma_job **job,
179 : : uint16_t nb_jobs)
180 : : {
181 : : struct rte_dpaa2_qdma_rbp *rbp = &qdma_vq->rbp;
182 : : struct rte_dpaa2_qdma_job **ppjob;
183 : : size_t iova;
184 : : int ret = 0, loop;
185 : 0 : int ser = (qdma_vq->flags & DPAA2_QDMA_VQ_NO_RESPONSE) ?
186 : 0 : 0 : 1;
187 : :
188 [ # # ]: 0 : for (loop = 0; loop < nb_jobs; loop++) {
189 [ # # ]: 0 : if (job[loop]->src & QDMA_RBP_UPPER_ADDRESS_MASK)
190 : 0 : iova = (size_t)job[loop]->dest;
191 : : else
192 : : iova = (size_t)job[loop]->src;
193 : :
194 : : /* Set the metadata */
195 : 0 : job[loop]->vq_id = qdma_vq->vq_id;
196 : 0 : ppjob = (struct rte_dpaa2_qdma_job **)DPAA2_IOVA_TO_VADDR(iova) - 1;
197 : 0 : *ppjob = job[loop];
198 : :
199 [ # # ]: 0 : if ((rbp->drbp == 1) || (rbp->srbp == 1))
200 : 0 : ret = qdma_populate_fd_pci((phys_addr_t)job[loop]->src,
201 : 0 : (phys_addr_t)job[loop]->dest,
202 [ # # ]: 0 : job[loop]->len, &fd[loop], rbp, ser);
203 : : else
204 : 0 : ret = qdma_populate_fd_ddr((phys_addr_t)job[loop]->src,
205 : 0 : (phys_addr_t)job[loop]->dest,
206 : 0 : job[loop]->len, &fd[loop], ser);
207 : : }
208 : :
209 : 0 : return ret;
210 : : }
211 : :
212 : : static uint32_t
213 : 0 : qdma_populate_sg_entry(struct rte_dpaa2_qdma_job **jobs,
214 : : struct qdma_sg_entry *src_sge,
215 : : struct qdma_sg_entry *dst_sge,
216 : : uint16_t nb_jobs)
217 : : {
218 : : uint16_t i;
219 : : uint32_t total_len = 0;
220 : : uint64_t iova;
221 : :
222 [ # # ]: 0 : for (i = 0; i < nb_jobs; i++) {
223 : : /* source SG */
224 [ # # ]: 0 : if (likely(jobs[i]->flags & RTE_DPAA2_QDMA_JOB_SRC_PHY)) {
225 : 0 : src_sge->addr_lo = (uint32_t)jobs[i]->src;
226 : 0 : src_sge->addr_hi = (jobs[i]->src >> 32);
227 : : } else {
228 : 0 : iova = DPAA2_VADDR_TO_IOVA(jobs[i]->src);
229 : 0 : src_sge->addr_lo = (uint32_t)iova;
230 : 0 : src_sge->addr_hi = iova >> 32;
231 : : }
232 : 0 : src_sge->data_len.data_len_sl0 = jobs[i]->len;
233 : 0 : src_sge->ctrl.sl = QDMA_SG_SL_LONG;
234 : 0 : src_sge->ctrl.fmt = QDMA_SG_FMT_SDB;
235 : : #ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
236 : 0 : src_sge->ctrl.bmt = QDMA_SG_BMT_ENABLE;
237 : : #else
238 : : src_sge->ctrl.bmt = QDMA_SG_BMT_DISABLE;
239 : : #endif
240 : : /* destination SG */
241 [ # # ]: 0 : if (likely(jobs[i]->flags & RTE_DPAA2_QDMA_JOB_DEST_PHY)) {
242 : 0 : dst_sge->addr_lo = (uint32_t)jobs[i]->dest;
243 : 0 : dst_sge->addr_hi = (jobs[i]->dest >> 32);
244 : : } else {
245 : 0 : iova = DPAA2_VADDR_TO_IOVA(jobs[i]->dest);
246 : 0 : dst_sge->addr_lo = (uint32_t)iova;
247 : 0 : dst_sge->addr_hi = iova >> 32;
248 : : }
249 : 0 : dst_sge->data_len.data_len_sl0 = jobs[i]->len;
250 : 0 : dst_sge->ctrl.sl = QDMA_SG_SL_LONG;
251 : 0 : dst_sge->ctrl.fmt = QDMA_SG_FMT_SDB;
252 : : #ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
253 : 0 : dst_sge->ctrl.bmt = QDMA_SG_BMT_ENABLE;
254 : : #else
255 : : dst_sge->ctrl.bmt = QDMA_SG_BMT_DISABLE;
256 : : #endif
257 : 0 : total_len += jobs[i]->len;
258 : :
259 [ # # ]: 0 : if (i == (nb_jobs - 1)) {
260 : 0 : src_sge->ctrl.f = QDMA_SG_F;
261 : 0 : dst_sge->ctrl.f = QDMA_SG_F;
262 : : } else {
263 : 0 : src_sge->ctrl.f = 0;
264 : 0 : dst_sge->ctrl.f = 0;
265 : : }
266 : 0 : src_sge++;
267 : 0 : dst_sge++;
268 : : }
269 : :
270 : 0 : return total_len;
271 : : }
272 : :
273 : : static inline int
274 : 0 : dpdmai_dev_set_multi_fd_lf_no_rsp(struct qdma_virt_queue *qdma_vq,
275 : : struct qbman_fd *fd,
276 : : struct rte_dpaa2_qdma_job **job,
277 : : uint16_t nb_jobs)
278 : : {
279 : 0 : struct rte_dpaa2_qdma_rbp *rbp = &qdma_vq->rbp;
280 : : struct rte_dpaa2_qdma_job **ppjob;
281 : : uint16_t i;
282 : : void *elem;
283 : : struct qbman_fle *fle;
284 : : uint64_t elem_iova, fle_iova;
285 : :
286 [ # # ]: 0 : for (i = 0; i < nb_jobs; i++) {
287 : 0 : elem = job[i]->usr_elem;
288 : : #ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
289 : : elem_iova = rte_mempool_virt2iova(elem);
290 : : #else
291 : : elem_iova = DPAA2_VADDR_TO_IOVA(elem);
292 : : #endif
293 : :
294 : : ppjob = (struct rte_dpaa2_qdma_job **)
295 : : ((uintptr_t)(uint64_t)elem +
296 : : QDMA_FLE_SINGLE_JOB_OFFSET);
297 : 0 : *ppjob = job[i];
298 : :
299 : 0 : job[i]->vq_id = qdma_vq->vq_id;
300 : :
301 : 0 : fle = (struct qbman_fle *)
302 : 0 : ((uintptr_t)(uint64_t)elem + QDMA_FLE_FLE_OFFSET);
303 : 0 : fle_iova = elem_iova + QDMA_FLE_FLE_OFFSET;
304 : :
305 : 0 : DPAA2_SET_FD_ADDR(&fd[i], fle_iova);
306 : 0 : DPAA2_SET_FD_COMPOUND_FMT(&fd[i]);
307 : :
308 : : memset(fle, 0, DPAA2_QDMA_MAX_FLE * sizeof(struct qbman_fle) +
309 : : DPAA2_QDMA_MAX_SDD * sizeof(struct qdma_sdd));
310 : :
311 : 0 : dpaa2_qdma_populate_fle(fle, fle_iova, rbp,
312 : 0 : job[i]->src, job[i]->dest, job[i]->len,
313 : 0 : job[i]->flags, QBMAN_FLE_WORD4_FMT_SBF);
314 : : }
315 : :
316 : 0 : return 0;
317 : : }
318 : :
319 : : static inline int
320 : 0 : dpdmai_dev_set_multi_fd_lf(struct qdma_virt_queue *qdma_vq,
321 : : struct qbman_fd *fd,
322 : : struct rte_dpaa2_qdma_job **job,
323 : : uint16_t nb_jobs)
324 : : {
325 : 0 : struct rte_dpaa2_qdma_rbp *rbp = &qdma_vq->rbp;
326 : : struct rte_dpaa2_qdma_job **ppjob;
327 : : uint16_t i;
328 : : int ret;
329 : : void *elem[DPAA2_QDMA_MAX_DESC];
330 : : struct qbman_fle *fle;
331 : : uint64_t elem_iova, fle_iova;
332 : :
333 [ # # ]: 0 : ret = rte_mempool_get_bulk(qdma_vq->fle_pool, elem, nb_jobs);
334 [ # # ]: 0 : if (ret) {
335 : : DPAA2_QDMA_DP_DEBUG("Memory alloc failed for FLE");
336 : : return ret;
337 : : }
338 : :
339 [ # # ]: 0 : for (i = 0; i < nb_jobs; i++) {
340 : : #ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
341 : 0 : elem_iova = rte_mempool_virt2iova(elem[i]);
342 : : #else
343 : : elem_iova = DPAA2_VADDR_TO_IOVA(elem[i]);
344 : : #endif
345 : :
346 : : ppjob = (struct rte_dpaa2_qdma_job **)
347 : : ((uintptr_t)(uint64_t)elem[i] +
348 : : QDMA_FLE_SINGLE_JOB_OFFSET);
349 : 0 : *ppjob = job[i];
350 : :
351 : 0 : job[i]->vq_id = qdma_vq->vq_id;
352 : :
353 : 0 : fle = (struct qbman_fle *)
354 : 0 : ((uintptr_t)(uint64_t)elem[i] + QDMA_FLE_FLE_OFFSET);
355 : 0 : fle_iova = elem_iova + QDMA_FLE_FLE_OFFSET;
356 : :
357 : 0 : DPAA2_SET_FD_ADDR(&fd[i], fle_iova);
358 : 0 : DPAA2_SET_FD_COMPOUND_FMT(&fd[i]);
359 : 0 : DPAA2_SET_FD_FRC(&fd[i], QDMA_SER_CTX);
360 : :
361 : : memset(fle, 0, DPAA2_QDMA_MAX_FLE * sizeof(struct qbman_fle) +
362 : : DPAA2_QDMA_MAX_SDD * sizeof(struct qdma_sdd));
363 : :
364 : 0 : dpaa2_qdma_populate_fle(fle, fle_iova, rbp,
365 : 0 : job[i]->src, job[i]->dest, job[i]->len,
366 : 0 : job[i]->flags, QBMAN_FLE_WORD4_FMT_SBF);
367 : : }
368 : :
369 : : return 0;
370 : : }
371 : :
372 : : static inline int
373 : 0 : dpdmai_dev_set_sg_fd_lf(struct qdma_virt_queue *qdma_vq,
374 : : struct qbman_fd *fd,
375 : : struct rte_dpaa2_qdma_job **job,
376 : : uint16_t nb_jobs)
377 : : {
378 : 0 : struct rte_dpaa2_qdma_rbp *rbp = &qdma_vq->rbp;
379 : : struct rte_dpaa2_qdma_job **ppjob;
380 : : void *elem;
381 : : struct qbman_fle *fle;
382 : : uint64_t elem_iova, fle_iova, src, dst;
383 : : int ret = 0, i;
384 : : struct qdma_sg_entry *src_sge, *dst_sge;
385 : : uint32_t len, fmt, flags;
386 : :
387 : : /*
388 : : * Get an FLE/SDD from FLE pool.
389 : : * Note: IO metadata is before the FLE and SDD memory.
390 : : */
391 [ # # ]: 0 : if (qdma_vq->flags & DPAA2_QDMA_VQ_NO_RESPONSE) {
392 : 0 : elem = job[0]->usr_elem;
393 : : } else {
394 [ # # ]: 0 : ret = rte_mempool_get(qdma_vq->fle_pool, &elem);
395 [ # # ]: 0 : if (ret) {
396 : : DPAA2_QDMA_DP_DEBUG("Memory alloc failed for FLE");
397 : : return ret;
398 : : }
399 : : }
400 : :
401 : : #ifdef RTE_LIBRTE_DPAA2_USE_PHYS_IOVA
402 : 0 : elem_iova = rte_mempool_virt2iova(elem);
403 : : #else
404 : : elem_iova = DPAA2_VADDR_TO_IOVA(elem);
405 : : #endif
406 : :
407 : : /* Set the metadata */
408 : : /* Save job context. */
409 : : *((uint16_t *)
410 : 0 : ((uintptr_t)(uint64_t)elem + QDMA_FLE_JOB_NB_OFFSET)) = nb_jobs;
411 : 0 : ppjob = (struct rte_dpaa2_qdma_job **)
412 : 0 : ((uintptr_t)(uint64_t)elem + QDMA_FLE_SG_JOBS_OFFSET);
413 [ # # ]: 0 : for (i = 0; i < nb_jobs; i++)
414 : 0 : ppjob[i] = job[i];
415 : :
416 : 0 : ppjob[0]->vq_id = qdma_vq->vq_id;
417 : :
418 : 0 : fle = (struct qbman_fle *)
419 : 0 : ((uintptr_t)(uint64_t)elem + QDMA_FLE_FLE_OFFSET);
420 : 0 : fle_iova = elem_iova + QDMA_FLE_FLE_OFFSET;
421 : :
422 : 0 : DPAA2_SET_FD_ADDR(fd, fle_iova);
423 : 0 : DPAA2_SET_FD_COMPOUND_FMT(fd);
424 [ # # ]: 0 : if (!(qdma_vq->flags & DPAA2_QDMA_VQ_NO_RESPONSE))
425 : 0 : DPAA2_SET_FD_FRC(fd, QDMA_SER_CTX);
426 : :
427 : : /* Populate FLE */
428 [ # # ]: 0 : if (likely(nb_jobs > 1)) {
429 : 0 : src_sge = (struct qdma_sg_entry *)
430 : 0 : ((uintptr_t)(uint64_t)elem + QDMA_FLE_SG_ENTRY_OFFSET);
431 : 0 : dst_sge = src_sge + DPAA2_QDMA_MAX_SG_NB;
432 : 0 : src = elem_iova + QDMA_FLE_SG_ENTRY_OFFSET;
433 : 0 : dst = src +
434 : : DPAA2_QDMA_MAX_SG_NB * sizeof(struct qdma_sg_entry);
435 : 0 : len = qdma_populate_sg_entry(job, src_sge, dst_sge, nb_jobs);
436 : : fmt = QBMAN_FLE_WORD4_FMT_SGE;
437 : : flags = RTE_DPAA2_QDMA_JOB_SRC_PHY | RTE_DPAA2_QDMA_JOB_DEST_PHY;
438 : : } else {
439 : 0 : src = job[0]->src;
440 : 0 : dst = job[0]->dest;
441 : 0 : len = job[0]->len;
442 : : fmt = QBMAN_FLE_WORD4_FMT_SBF;
443 : 0 : flags = job[0]->flags;
444 : : }
445 : :
446 : : memset(fle, 0, DPAA2_QDMA_MAX_FLE * sizeof(struct qbman_fle) +
447 : : DPAA2_QDMA_MAX_SDD * sizeof(struct qdma_sdd));
448 : :
449 : 0 : dpaa2_qdma_populate_fle(fle, fle_iova, rbp,
450 : : src, dst, len, flags, fmt);
451 : :
452 : 0 : return 0;
453 : : }
454 : :
455 : : static inline uint16_t
456 : 0 : dpdmai_dev_get_job_us(struct qdma_virt_queue *qdma_vq __rte_unused,
457 : : const struct qbman_fd *fd,
458 : : struct rte_dpaa2_qdma_job **job, uint16_t *nb_jobs)
459 : : {
460 : : uint16_t vqid;
461 : : size_t iova;
462 : : struct rte_dpaa2_qdma_job **ppjob;
463 : :
464 [ # # ]: 0 : if (fd->simple_pci.saddr_hi & (QDMA_RBP_UPPER_ADDRESS_MASK >> 32))
465 : 0 : iova = (size_t)(((uint64_t)fd->simple_pci.daddr_hi) << 32
466 : 0 : | (uint64_t)fd->simple_pci.daddr_lo);
467 : : else
468 : 0 : iova = (size_t)(((uint64_t)fd->simple_pci.saddr_hi) << 32
469 : 0 : | (uint64_t)fd->simple_pci.saddr_lo);
470 : :
471 : 0 : ppjob = (struct rte_dpaa2_qdma_job **)DPAA2_IOVA_TO_VADDR(iova) - 1;
472 : 0 : *job = (struct rte_dpaa2_qdma_job *)*ppjob;
473 : 0 : (*job)->status = (fd->simple_pci.acc_err << 8) |
474 : 0 : (fd->simple_pci.error);
475 : 0 : vqid = (*job)->vq_id;
476 : 0 : *nb_jobs = 1;
477 : :
478 : 0 : return vqid;
479 : : }
480 : :
481 : : static inline uint16_t
482 : 0 : dpdmai_dev_get_single_job_lf(struct qdma_virt_queue *qdma_vq,
483 : : const struct qbman_fd *fd,
484 : : struct rte_dpaa2_qdma_job **job,
485 : : uint16_t *nb_jobs)
486 : : {
487 : : struct qbman_fle *fle;
488 : : struct rte_dpaa2_qdma_job **ppjob = NULL;
489 : : uint16_t status;
490 : :
491 : : /*
492 : : * Fetch metadata from FLE. job and vq_id were set
493 : : * in metadata in the enqueue operation.
494 : : */
495 : : fle = (struct qbman_fle *)
496 : 0 : DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd));
497 : :
498 : 0 : *nb_jobs = 1;
499 : 0 : ppjob = (struct rte_dpaa2_qdma_job **)((uintptr_t)(uint64_t)fle -
500 : 0 : QDMA_FLE_FLE_OFFSET + QDMA_FLE_SINGLE_JOB_OFFSET);
501 : :
502 : 0 : status = (DPAA2_GET_FD_ERR(fd) << 8) | (DPAA2_GET_FD_FRC(fd) & 0xFF);
503 : :
504 : 0 : *job = *ppjob;
505 : 0 : (*job)->status = status;
506 : :
507 : : /* Free FLE to the pool */
508 [ # # ]: 0 : rte_mempool_put(qdma_vq->fle_pool,
509 : : (void *)
510 : : ((uintptr_t)(uint64_t)fle - QDMA_FLE_FLE_OFFSET));
511 : :
512 : 0 : return (*job)->vq_id;
513 : : }
514 : :
515 : : static inline uint16_t
516 : 0 : dpdmai_dev_get_sg_job_lf(struct qdma_virt_queue *qdma_vq,
517 : : const struct qbman_fd *fd,
518 : : struct rte_dpaa2_qdma_job **job,
519 : : uint16_t *nb_jobs)
520 : : {
521 : : struct qbman_fle *fle;
522 : : struct rte_dpaa2_qdma_job **ppjob = NULL;
523 : : uint16_t i, status;
524 : :
525 : : /*
526 : : * Fetch metadata from FLE. job and vq_id were set
527 : : * in metadata in the enqueue operation.
528 : : */
529 : : fle = (struct qbman_fle *)
530 : 0 : DPAA2_IOVA_TO_VADDR(DPAA2_GET_FD_ADDR(fd));
531 : 0 : *nb_jobs = *((uint16_t *)((uintptr_t)(uint64_t)fle -
532 : 0 : QDMA_FLE_FLE_OFFSET + QDMA_FLE_JOB_NB_OFFSET));
533 : 0 : ppjob = (struct rte_dpaa2_qdma_job **)((uintptr_t)(uint64_t)fle -
534 : 0 : QDMA_FLE_FLE_OFFSET + QDMA_FLE_SG_JOBS_OFFSET);
535 : 0 : status = (DPAA2_GET_FD_ERR(fd) << 8) | (DPAA2_GET_FD_FRC(fd) & 0xFF);
536 : :
537 [ # # ]: 0 : for (i = 0; i < (*nb_jobs); i++) {
538 : 0 : job[i] = ppjob[i];
539 : 0 : job[i]->status = status;
540 : : }
541 : :
542 : : /* Free FLE to the pool */
543 [ # # ]: 0 : rte_mempool_put(qdma_vq->fle_pool,
544 : : (void *)
545 : : ((uintptr_t)(uint64_t)fle - QDMA_FLE_FLE_OFFSET));
546 : :
547 : 0 : return job[0]->vq_id;
548 : : }
549 : :
550 : : /* Function to receive a QDMA job for a given device and queue*/
551 : : static int
552 : 0 : dpdmai_dev_dequeue_multijob_prefetch(struct qdma_virt_queue *qdma_vq,
553 : : uint16_t *vq_id,
554 : : struct rte_dpaa2_qdma_job **job,
555 : : uint16_t nb_jobs)
556 : : {
557 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = qdma_vq->dpdmai_dev;
558 : : struct dpaa2_queue *rxq = &(dpdmai_dev->rx_queue[0]);
559 : : struct qbman_result *dq_storage, *dq_storage1 = NULL;
560 : : struct qbman_pull_desc pulldesc;
561 : : struct qbman_swp *swp;
562 : : struct queue_storage_info_t *q_storage;
563 : : uint8_t status, pending;
564 : : uint8_t num_rx = 0;
565 : : const struct qbman_fd *fd;
566 : : uint16_t vqid, num_rx_ret;
567 : 0 : uint16_t rx_fqid = rxq->fqid;
568 : : int ret, pull_size;
569 : :
570 [ # # ]: 0 : if (qdma_vq->flags & DPAA2_QDMA_VQ_FD_SG_FORMAT) {
571 : : /** Make sure there are enough space to get jobs.*/
572 [ # # ]: 0 : if (unlikely(nb_jobs < DPAA2_QDMA_MAX_SG_NB))
573 : : return -EINVAL;
574 : : nb_jobs = 1;
575 : : }
576 : :
577 [ # # ]: 0 : if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
578 : 0 : ret = dpaa2_affine_qbman_swp();
579 [ # # ]: 0 : if (ret) {
580 : 0 : DPAA2_QDMA_ERR(
581 : : "Failed to allocate IO portal, tid: %d\n",
582 : : rte_gettid());
583 : 0 : return 0;
584 : : }
585 : : }
586 : 0 : swp = DPAA2_PER_LCORE_PORTAL;
587 : :
588 [ # # ]: 0 : pull_size = (nb_jobs > dpaa2_dqrr_size) ? dpaa2_dqrr_size : nb_jobs;
589 : 0 : q_storage = rxq->q_storage;
590 : :
591 [ # # ]: 0 : if (unlikely(!q_storage->active_dqs)) {
592 : 0 : q_storage->toggle = 0;
593 : 0 : dq_storage = q_storage->dq_storage[q_storage->toggle];
594 : 0 : q_storage->last_num_pkts = pull_size;
595 : 0 : qbman_pull_desc_clear(&pulldesc);
596 : 0 : qbman_pull_desc_set_numframes(&pulldesc,
597 : 0 : q_storage->last_num_pkts);
598 : 0 : qbman_pull_desc_set_fq(&pulldesc, rx_fqid);
599 : 0 : qbman_pull_desc_set_storage(&pulldesc, dq_storage,
600 : 0 : (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1);
601 [ # # ]: 0 : if (check_swp_active_dqs(DPAA2_PER_LCORE_DPIO->index)) {
602 [ # # ]: 0 : while (!qbman_check_command_complete(
603 : : get_swp_active_dqs(
604 : 0 : DPAA2_PER_LCORE_DPIO->index)))
605 : : ;
606 : 0 : clear_swp_active_dqs(DPAA2_PER_LCORE_DPIO->index);
607 : : }
608 : : while (1) {
609 [ # # ]: 0 : if (qbman_swp_pull(swp, &pulldesc)) {
610 : 0 : DPAA2_QDMA_DP_WARN(
611 : : "VDQ command not issued.QBMAN busy\n");
612 : : /* Portal was busy, try again */
613 : : continue;
614 : : }
615 : : break;
616 : : }
617 : 0 : q_storage->active_dqs = dq_storage;
618 : 0 : q_storage->active_dpio_id = DPAA2_PER_LCORE_DPIO->index;
619 : 0 : set_swp_active_dqs(DPAA2_PER_LCORE_DPIO->index,
620 : : dq_storage);
621 : : }
622 : :
623 : 0 : dq_storage = q_storage->active_dqs;
624 : : rte_prefetch0((void *)(size_t)(dq_storage));
625 : 0 : rte_prefetch0((void *)(size_t)(dq_storage + 1));
626 : :
627 : : /* Prepare next pull descriptor. This will give space for the
628 : : * prefething done on DQRR entries
629 : : */
630 : 0 : q_storage->toggle ^= 1;
631 : 0 : dq_storage1 = q_storage->dq_storage[q_storage->toggle];
632 : 0 : qbman_pull_desc_clear(&pulldesc);
633 : 0 : qbman_pull_desc_set_numframes(&pulldesc, pull_size);
634 : 0 : qbman_pull_desc_set_fq(&pulldesc, rx_fqid);
635 : 0 : qbman_pull_desc_set_storage(&pulldesc, dq_storage1,
636 : 0 : (size_t)(DPAA2_VADDR_TO_IOVA(dq_storage1)), 1);
637 : :
638 : : /* Check if the previous issued command is completed.
639 : : * Also seems like the SWP is shared between the Ethernet Driver
640 : : * and the SEC driver.
641 : : */
642 [ # # ]: 0 : while (!qbman_check_command_complete(dq_storage))
643 : : ;
644 [ # # ]: 0 : if (dq_storage == get_swp_active_dqs(q_storage->active_dpio_id))
645 : : clear_swp_active_dqs(q_storage->active_dpio_id);
646 : :
647 : : pending = 1;
648 : :
649 : : do {
650 : : /* Loop until the dq_storage is updated with
651 : : * new token by QBMAN
652 : : */
653 [ # # ]: 0 : while (!qbman_check_new_result(dq_storage))
654 : : ;
655 : 0 : rte_prefetch0((void *)((size_t)(dq_storage + 2)));
656 : : /* Check whether Last Pull command is Expired and
657 : : * setting Condition for Loop termination
658 : : */
659 [ # # ]: 0 : if (qbman_result_DQ_is_pull_complete(dq_storage)) {
660 : : pending = 0;
661 : : /* Check for valid frame. */
662 : 0 : status = qbman_result_DQ_flags(dq_storage);
663 [ # # ]: 0 : if (unlikely((status & QBMAN_DQ_STAT_VALIDFRAME) == 0))
664 : 0 : continue;
665 : : }
666 : 0 : fd = qbman_result_DQ_fd(dq_storage);
667 : :
668 : 0 : vqid = qdma_vq->get_job(qdma_vq, fd, &job[num_rx],
669 : : &num_rx_ret);
670 [ # # ]: 0 : if (vq_id)
671 : 0 : vq_id[num_rx] = vqid;
672 : :
673 : 0 : dq_storage++;
674 : 0 : num_rx += num_rx_ret;
675 [ # # ]: 0 : } while (pending);
676 : :
677 [ # # ]: 0 : if (check_swp_active_dqs(DPAA2_PER_LCORE_DPIO->index)) {
678 [ # # ]: 0 : while (!qbman_check_command_complete(
679 : 0 : get_swp_active_dqs(DPAA2_PER_LCORE_DPIO->index)))
680 : : ;
681 : 0 : clear_swp_active_dqs(DPAA2_PER_LCORE_DPIO->index);
682 : : }
683 : : /* issue a volatile dequeue command for next pull */
684 : : while (1) {
685 [ # # ]: 0 : if (qbman_swp_pull(swp, &pulldesc)) {
686 : 0 : DPAA2_QDMA_DP_WARN(
687 : : "VDQ command is not issued. QBMAN is busy (2)\n");
688 : : continue;
689 : : }
690 : : break;
691 : : }
692 : :
693 : 0 : q_storage->active_dqs = dq_storage1;
694 : 0 : q_storage->active_dpio_id = DPAA2_PER_LCORE_DPIO->index;
695 : 0 : set_swp_active_dqs(DPAA2_PER_LCORE_DPIO->index, dq_storage1);
696 : :
697 : 0 : return num_rx;
698 : : }
699 : :
700 : : static int
701 : 0 : dpdmai_dev_dequeue_multijob_no_prefetch(struct qdma_virt_queue *qdma_vq,
702 : : uint16_t *vq_id,
703 : : struct rte_dpaa2_qdma_job **job,
704 : : uint16_t nb_jobs)
705 : : {
706 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = qdma_vq->dpdmai_dev;
707 : : struct dpaa2_queue *rxq = &(dpdmai_dev->rx_queue[0]);
708 : : struct qbman_result *dq_storage;
709 : : struct qbman_pull_desc pulldesc;
710 : : struct qbman_swp *swp;
711 : : uint8_t status, pending;
712 : : uint8_t num_rx = 0;
713 : : const struct qbman_fd *fd;
714 : : uint16_t vqid, num_rx_ret;
715 : 0 : uint16_t rx_fqid = rxq->fqid;
716 : : int ret, next_pull, num_pulled = 0;
717 : :
718 [ # # ]: 0 : if (qdma_vq->flags & DPAA2_QDMA_VQ_FD_SG_FORMAT) {
719 : : /** Make sure there are enough space to get jobs.*/
720 [ # # ]: 0 : if (unlikely(nb_jobs < DPAA2_QDMA_MAX_SG_NB))
721 : : return -EINVAL;
722 : : nb_jobs = 1;
723 : : }
724 : :
725 : 0 : next_pull = nb_jobs;
726 : :
727 [ # # ]: 0 : if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
728 : 0 : ret = dpaa2_affine_qbman_swp();
729 [ # # ]: 0 : if (ret) {
730 : 0 : DPAA2_QDMA_ERR(
731 : : "Failed to allocate IO portal, tid: %d\n",
732 : : rte_gettid());
733 : 0 : return 0;
734 : : }
735 : : }
736 : 0 : swp = DPAA2_PER_LCORE_PORTAL;
737 : :
738 : : rxq = &(dpdmai_dev->rx_queue[0]);
739 : :
740 : : do {
741 : 0 : dq_storage = rxq->q_storage->dq_storage[0];
742 : : /* Prepare dequeue descriptor */
743 : 0 : qbman_pull_desc_clear(&pulldesc);
744 : 0 : qbman_pull_desc_set_fq(&pulldesc, rx_fqid);
745 : 0 : qbman_pull_desc_set_storage(&pulldesc, dq_storage,
746 : 0 : (uint64_t)(DPAA2_VADDR_TO_IOVA(dq_storage)), 1);
747 : :
748 [ # # ]: 0 : if (next_pull > dpaa2_dqrr_size) {
749 : 0 : qbman_pull_desc_set_numframes(&pulldesc,
750 : : dpaa2_dqrr_size);
751 : 0 : next_pull -= dpaa2_dqrr_size;
752 : : } else {
753 : 0 : qbman_pull_desc_set_numframes(&pulldesc, next_pull);
754 : : next_pull = 0;
755 : : }
756 : :
757 : : while (1) {
758 [ # # ]: 0 : if (qbman_swp_pull(swp, &pulldesc)) {
759 : 0 : DPAA2_QDMA_DP_WARN(
760 : : "VDQ command not issued. QBMAN busy");
761 : : /* Portal was busy, try again */
762 : : continue;
763 : : }
764 : : break;
765 : : }
766 : :
767 : 0 : rte_prefetch0((void *)((size_t)(dq_storage + 1)));
768 : : /* Check if the previous issued command is completed. */
769 [ # # ]: 0 : while (!qbman_check_command_complete(dq_storage))
770 : : ;
771 : :
772 : : num_pulled = 0;
773 : : pending = 1;
774 : :
775 : : do {
776 : : /* Loop until dq_storage is updated
777 : : * with new token by QBMAN
778 : : */
779 [ # # ]: 0 : while (!qbman_check_new_result(dq_storage))
780 : : ;
781 : 0 : rte_prefetch0((void *)((size_t)(dq_storage + 2)));
782 : :
783 [ # # ]: 0 : if (qbman_result_DQ_is_pull_complete(dq_storage)) {
784 : : pending = 0;
785 : : /* Check for valid frame. */
786 : 0 : status = qbman_result_DQ_flags(dq_storage);
787 [ # # ]: 0 : if (unlikely((status &
788 : : QBMAN_DQ_STAT_VALIDFRAME) == 0))
789 : 0 : continue;
790 : : }
791 : 0 : fd = qbman_result_DQ_fd(dq_storage);
792 : :
793 : 0 : vqid = qdma_vq->get_job(qdma_vq, fd,
794 : 0 : &job[num_rx], &num_rx_ret);
795 [ # # ]: 0 : if (vq_id)
796 : 0 : vq_id[num_rx] = vqid;
797 : :
798 : 0 : dq_storage++;
799 : 0 : num_rx += num_rx_ret;
800 : 0 : num_pulled++;
801 : :
802 [ # # ]: 0 : } while (pending);
803 : : /* Last VDQ provided all packets and more packets are requested */
804 [ # # # # ]: 0 : } while (next_pull && num_pulled == dpaa2_dqrr_size);
805 : :
806 : 0 : return num_rx;
807 : : }
808 : :
809 : : static int
810 : 0 : dpdmai_dev_submit_multi(struct qdma_virt_queue *qdma_vq,
811 : : struct rte_dpaa2_qdma_job **job,
812 : : uint16_t nb_jobs)
813 : : {
814 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = qdma_vq->dpdmai_dev;
815 : 0 : uint16_t txq_id = dpdmai_dev->tx_queue[0].fqid;
816 : : struct qbman_fd fd[DPAA2_QDMA_MAX_DESC];
817 : : struct qbman_eq_desc eqdesc;
818 : : struct qbman_swp *swp;
819 : : uint32_t num_to_send = 0;
820 : : uint16_t num_tx = 0;
821 : : uint32_t enqueue_loop, loop;
822 : : int ret;
823 : :
824 [ # # ]: 0 : if (unlikely(!DPAA2_PER_LCORE_DPIO)) {
825 : 0 : ret = dpaa2_affine_qbman_swp();
826 [ # # ]: 0 : if (ret) {
827 : 0 : DPAA2_QDMA_ERR(
828 : : "Failed to allocate IO portal, tid: %d\n",
829 : : rte_gettid());
830 : 0 : return 0;
831 : : }
832 : : }
833 : 0 : swp = DPAA2_PER_LCORE_PORTAL;
834 : :
835 : : /* Prepare enqueue descriptor */
836 : 0 : qbman_eq_desc_clear(&eqdesc);
837 : 0 : qbman_eq_desc_set_fq(&eqdesc, txq_id);
838 : 0 : qbman_eq_desc_set_no_orp(&eqdesc, 0);
839 : 0 : qbman_eq_desc_set_response(&eqdesc, 0, 0);
840 : :
841 [ # # ]: 0 : if (qdma_vq->flags & DPAA2_QDMA_VQ_FD_SG_FORMAT) {
842 : : uint16_t fd_nb;
843 : 0 : uint16_t sg_entry_nb = nb_jobs > DPAA2_QDMA_MAX_SG_NB ?
844 : : DPAA2_QDMA_MAX_SG_NB : nb_jobs;
845 : : uint16_t job_idx = 0;
846 : : uint16_t fd_sg_nb[8];
847 : : uint16_t nb_jobs_ret = 0;
848 : :
849 [ # # ]: 0 : if (nb_jobs % DPAA2_QDMA_MAX_SG_NB)
850 : 0 : fd_nb = nb_jobs / DPAA2_QDMA_MAX_SG_NB + 1;
851 : : else
852 : 0 : fd_nb = nb_jobs / DPAA2_QDMA_MAX_SG_NB;
853 : :
854 : 0 : memset(&fd[0], 0, sizeof(struct qbman_fd) * fd_nb);
855 : :
856 [ # # ]: 0 : for (loop = 0; loop < fd_nb; loop++) {
857 : 0 : ret = qdma_vq->set_fd(qdma_vq, &fd[loop], &job[job_idx],
858 : : sg_entry_nb);
859 [ # # ]: 0 : if (unlikely(ret < 0))
860 : : return 0;
861 : 0 : fd_sg_nb[loop] = sg_entry_nb;
862 : 0 : nb_jobs -= sg_entry_nb;
863 : 0 : job_idx += sg_entry_nb;
864 : 0 : sg_entry_nb = nb_jobs > DPAA2_QDMA_MAX_SG_NB ?
865 : : DPAA2_QDMA_MAX_SG_NB : nb_jobs;
866 : : }
867 : :
868 : : /* Enqueue the packet to the QBMAN */
869 : : enqueue_loop = 0;
870 : :
871 [ # # ]: 0 : while (enqueue_loop < fd_nb) {
872 : 0 : ret = qbman_swp_enqueue_multiple(swp,
873 : 0 : &eqdesc, &fd[enqueue_loop],
874 : 0 : NULL, fd_nb - enqueue_loop);
875 [ # # ]: 0 : if (likely(ret >= 0)) {
876 [ # # ]: 0 : for (loop = 0; loop < (uint32_t)ret; loop++)
877 : 0 : nb_jobs_ret +=
878 : 0 : fd_sg_nb[enqueue_loop + loop];
879 : 0 : enqueue_loop += ret;
880 : : }
881 : : }
882 : :
883 : 0 : return nb_jobs_ret;
884 : : }
885 : :
886 : 0 : memset(fd, 0, nb_jobs * sizeof(struct qbman_fd));
887 : :
888 [ # # ]: 0 : while (nb_jobs > 0) {
889 : 0 : num_to_send = (nb_jobs > dpaa2_eqcr_size) ?
890 [ # # ]: 0 : dpaa2_eqcr_size : nb_jobs;
891 : :
892 : 0 : ret = qdma_vq->set_fd(qdma_vq, &fd[num_tx],
893 : 0 : &job[num_tx], num_to_send);
894 [ # # ]: 0 : if (unlikely(ret < 0))
895 : : break;
896 : :
897 : : /* Enqueue the packet to the QBMAN */
898 : : enqueue_loop = 0;
899 : : loop = num_to_send;
900 : :
901 [ # # ]: 0 : while (enqueue_loop < loop) {
902 : 0 : ret = qbman_swp_enqueue_multiple(swp,
903 : : &eqdesc,
904 : 0 : &fd[num_tx + enqueue_loop],
905 : : NULL,
906 : 0 : loop - enqueue_loop);
907 [ # # ]: 0 : if (likely(ret >= 0))
908 : 0 : enqueue_loop += ret;
909 : : }
910 : 0 : num_tx += num_to_send;
911 : 0 : nb_jobs -= loop;
912 : : }
913 : :
914 : 0 : qdma_vq->num_enqueues += num_tx;
915 : :
916 : 0 : return num_tx;
917 : : }
918 : :
919 : : static inline int
920 : 0 : dpaa2_qdma_submit(void *dev_private, uint16_t vchan)
921 : : {
922 : : struct dpaa2_dpdmai_dev *dpdmai_dev = dev_private;
923 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
924 : 0 : struct qdma_virt_queue *qdma_vq = &qdma_dev->vqs[vchan];
925 : :
926 : 0 : dpdmai_dev_submit_multi(qdma_vq, qdma_vq->job_list,
927 : 0 : qdma_vq->num_valid_jobs);
928 : :
929 : 0 : qdma_vq->num_valid_jobs = 0;
930 : :
931 : 0 : return 0;
932 : : }
933 : :
934 : : static int
935 : 0 : dpaa2_qdma_enqueue(void *dev_private, uint16_t vchan,
936 : : rte_iova_t src, rte_iova_t dst,
937 : : uint32_t length, uint64_t flags)
938 : : {
939 : : struct dpaa2_dpdmai_dev *dpdmai_dev = dev_private;
940 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
941 : 0 : struct qdma_virt_queue *qdma_vq = &qdma_dev->vqs[vchan];
942 : : struct rte_dpaa2_qdma_job *job;
943 : : int idx, ret;
944 : :
945 : 0 : idx = (uint16_t)(qdma_vq->num_enqueues + qdma_vq->num_valid_jobs);
946 : :
947 [ # # ]: 0 : ret = rte_mempool_get(qdma_vq->job_pool, (void **)&job);
948 [ # # ]: 0 : if (ret) {
949 : : DPAA2_QDMA_DP_DEBUG("Memory alloc failed for FLE");
950 : : return -ENOSPC;
951 : : }
952 : :
953 : 0 : job->src = src;
954 : 0 : job->dest = dst;
955 : 0 : job->len = length;
956 : 0 : job->flags = flags;
957 : 0 : job->status = 0;
958 : 0 : job->vq_id = vchan;
959 : :
960 : 0 : qdma_vq->job_list[qdma_vq->num_valid_jobs] = job;
961 : 0 : qdma_vq->num_valid_jobs++;
962 : :
963 [ # # ]: 0 : if (flags & RTE_DMA_OP_FLAG_SUBMIT)
964 : 0 : dpaa2_qdma_submit(dev_private, vchan);
965 : :
966 : : return idx;
967 : : }
968 : :
969 : : int
970 : 0 : rte_dpaa2_qdma_copy_multi(int16_t dev_id, uint16_t vchan,
971 : : struct rte_dpaa2_qdma_job **jobs,
972 : : uint16_t nb_cpls)
973 : : {
974 : 0 : struct rte_dma_fp_object *obj = &rte_dma_fp_objs[dev_id];
975 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = obj->dev_private;
976 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
977 : 0 : struct qdma_virt_queue *qdma_vq = &qdma_dev->vqs[vchan];
978 : :
979 : 0 : return dpdmai_dev_submit_multi(qdma_vq, jobs, nb_cpls);
980 : : }
981 : :
982 : : static uint16_t
983 : 0 : dpaa2_qdma_dequeue_multi(struct qdma_device *qdma_dev,
984 : : struct qdma_virt_queue *qdma_vq,
985 : : struct rte_dpaa2_qdma_job **jobs,
986 : : uint16_t nb_jobs)
987 : : {
988 : : struct qdma_virt_queue *temp_qdma_vq;
989 : : int ring_count;
990 : : int ret = 0, i;
991 : :
992 [ # # ]: 0 : if (qdma_vq->flags & DPAA2_QDMA_VQ_FD_SG_FORMAT) {
993 : : /** Make sure there are enough space to get jobs.*/
994 [ # # ]: 0 : if (unlikely(nb_jobs < DPAA2_QDMA_MAX_SG_NB))
995 : : return -EINVAL;
996 : : }
997 : :
998 : : /* Only dequeue when there are pending jobs on VQ */
999 [ # # ]: 0 : if (qdma_vq->num_enqueues == qdma_vq->num_dequeues)
1000 : : return 0;
1001 : :
1002 [ # # ]: 0 : if (!(qdma_vq->flags & DPAA2_QDMA_VQ_FD_SG_FORMAT) &&
1003 [ # # ]: 0 : qdma_vq->num_enqueues < (qdma_vq->num_dequeues + nb_jobs))
1004 : 0 : nb_jobs = RTE_MIN((qdma_vq->num_enqueues -
1005 : : qdma_vq->num_dequeues), nb_jobs);
1006 : :
1007 [ # # ]: 0 : if (qdma_vq->exclusive_hw_queue) {
1008 : : /* In case of exclusive queue directly fetch from HW queue */
1009 : 0 : ret = qdma_vq->dequeue_job(qdma_vq, NULL, jobs, nb_jobs);
1010 [ # # ]: 0 : if (ret < 0) {
1011 : 0 : DPAA2_QDMA_ERR(
1012 : : "Dequeue from DPDMAI device failed: %d", ret);
1013 : 0 : return ret;
1014 : : }
1015 : : } else {
1016 : : uint16_t temp_vq_id[DPAA2_QDMA_MAX_DESC];
1017 : :
1018 : : /* Get the QDMA completed jobs from the software ring.
1019 : : * In case they are not available on the ring poke the HW
1020 : : * to fetch completed jobs from corresponding HW queues
1021 : : */
1022 [ # # ]: 0 : ring_count = rte_ring_count(qdma_vq->status_ring);
1023 [ # # ]: 0 : if (ring_count < nb_jobs) {
1024 : 0 : ret = qdma_vq->dequeue_job(qdma_vq,
1025 : : temp_vq_id, jobs, nb_jobs);
1026 [ # # ]: 0 : for (i = 0; i < ret; i++) {
1027 : 0 : temp_qdma_vq = &qdma_dev->vqs[temp_vq_id[i]];
1028 : 0 : rte_ring_enqueue(temp_qdma_vq->status_ring,
1029 [ # # # # : 0 : (void *)(jobs[i]));
# ]
1030 : : }
1031 : 0 : ring_count = rte_ring_count(
1032 : 0 : qdma_vq->status_ring);
1033 : : }
1034 : :
1035 [ # # ]: 0 : if (ring_count) {
1036 : : /* Dequeue job from the software ring
1037 : : * to provide to the user
1038 : : */
1039 [ # # # # : 0 : ret = rte_ring_dequeue_bulk(qdma_vq->status_ring,
# ]
1040 : : (void **)jobs,
1041 : : ring_count, NULL);
1042 : : }
1043 : : }
1044 : :
1045 : 0 : qdma_vq->num_dequeues += ret;
1046 : 0 : return ret;
1047 : : }
1048 : :
1049 : : static uint16_t
1050 : 0 : dpaa2_qdma_dequeue_status(void *dev_private, uint16_t vchan,
1051 : : const uint16_t nb_cpls,
1052 : : uint16_t *last_idx,
1053 : : enum rte_dma_status_code *st)
1054 : : {
1055 : : struct dpaa2_dpdmai_dev *dpdmai_dev = dev_private;
1056 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1057 : 0 : struct qdma_virt_queue *qdma_vq = &qdma_dev->vqs[vchan];
1058 : : struct rte_dpaa2_qdma_job *jobs[DPAA2_QDMA_MAX_DESC];
1059 : : int ret, i;
1060 : :
1061 : 0 : ret = dpaa2_qdma_dequeue_multi(qdma_dev, qdma_vq, jobs, nb_cpls);
1062 : :
1063 [ # # ]: 0 : for (i = 0; i < ret; i++)
1064 : 0 : st[i] = jobs[i]->status;
1065 : :
1066 [ # # ]: 0 : rte_mempool_put_bulk(qdma_vq->job_pool, (void **)jobs, ret);
1067 : :
1068 [ # # ]: 0 : if (last_idx != NULL)
1069 : 0 : *last_idx = (uint16_t)(qdma_vq->num_dequeues - 1);
1070 : :
1071 : 0 : return ret;
1072 : : }
1073 : :
1074 : : static uint16_t
1075 : 0 : dpaa2_qdma_dequeue(void *dev_private,
1076 : : uint16_t vchan, const uint16_t nb_cpls,
1077 : : uint16_t *last_idx, bool *has_error)
1078 : : {
1079 : : struct dpaa2_dpdmai_dev *dpdmai_dev = dev_private;
1080 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1081 : 0 : struct qdma_virt_queue *qdma_vq = &qdma_dev->vqs[vchan];
1082 : : struct rte_dpaa2_qdma_job *jobs[DPAA2_QDMA_MAX_DESC];
1083 : : int ret;
1084 : :
1085 : : RTE_SET_USED(has_error);
1086 : :
1087 : 0 : ret = dpaa2_qdma_dequeue_multi(qdma_dev, qdma_vq,
1088 : : jobs, nb_cpls);
1089 : :
1090 [ # # ]: 0 : rte_mempool_put_bulk(qdma_vq->job_pool, (void **)jobs, ret);
1091 : :
1092 [ # # ]: 0 : if (last_idx != NULL)
1093 : 0 : *last_idx = (uint16_t)(qdma_vq->num_dequeues - 1);
1094 : :
1095 : 0 : return ret;
1096 : : }
1097 : :
1098 : : uint16_t
1099 : 0 : rte_dpaa2_qdma_completed_multi(int16_t dev_id, uint16_t vchan,
1100 : : struct rte_dpaa2_qdma_job **jobs,
1101 : : uint16_t nb_cpls)
1102 : : {
1103 : 0 : struct rte_dma_fp_object *obj = &rte_dma_fp_objs[dev_id];
1104 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = obj->dev_private;
1105 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1106 : 0 : struct qdma_virt_queue *qdma_vq = &qdma_dev->vqs[vchan];
1107 : :
1108 : 0 : return dpaa2_qdma_dequeue_multi(qdma_dev, qdma_vq, jobs, nb_cpls);
1109 : : }
1110 : :
1111 : : static int
1112 : 0 : dpaa2_qdma_info_get(const struct rte_dma_dev *dev,
1113 : : struct rte_dma_info *dev_info,
1114 : : uint32_t info_sz)
1115 : : {
1116 : : RTE_SET_USED(dev);
1117 : : RTE_SET_USED(info_sz);
1118 : :
1119 : 0 : dev_info->dev_capa = RTE_DMA_CAPA_MEM_TO_MEM |
1120 : : RTE_DMA_CAPA_MEM_TO_DEV |
1121 : : RTE_DMA_CAPA_DEV_TO_DEV |
1122 : : RTE_DMA_CAPA_DEV_TO_MEM |
1123 : : RTE_DMA_CAPA_SILENT |
1124 : : RTE_DMA_CAPA_OPS_COPY;
1125 : 0 : dev_info->max_vchans = DPAA2_QDMA_MAX_VHANS;
1126 : 0 : dev_info->max_desc = DPAA2_QDMA_MAX_DESC;
1127 : 0 : dev_info->min_desc = DPAA2_QDMA_MIN_DESC;
1128 : :
1129 : 0 : return 0;
1130 : : }
1131 : :
1132 : : static int
1133 : 0 : dpaa2_qdma_configure(struct rte_dma_dev *dev,
1134 : : const struct rte_dma_conf *dev_conf,
1135 : : uint32_t conf_sz)
1136 : : {
1137 : : char name[32]; /* RTE_MEMZONE_NAMESIZE = 32 */
1138 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = dev->data->dev_private;
1139 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1140 : :
1141 : 0 : DPAA2_QDMA_FUNC_TRACE();
1142 : :
1143 : : RTE_SET_USED(conf_sz);
1144 : :
1145 : : /* In case QDMA device is not in stopped state, return -EBUSY */
1146 [ # # ]: 0 : if (qdma_dev->state == 1) {
1147 : 0 : DPAA2_QDMA_ERR(
1148 : : "Device is in running state. Stop before config.");
1149 : 0 : return -1;
1150 : : }
1151 : :
1152 : : /* Allocate Virtual Queues */
1153 : 0 : sprintf(name, "qdma_%d_vq", dev->data->dev_id);
1154 : 0 : qdma_dev->vqs = rte_malloc(name,
1155 : 0 : (sizeof(struct qdma_virt_queue) * dev_conf->nb_vchans),
1156 : : RTE_CACHE_LINE_SIZE);
1157 [ # # ]: 0 : if (!qdma_dev->vqs) {
1158 : 0 : DPAA2_QDMA_ERR("qdma_virtual_queues allocation failed");
1159 : 0 : return -ENOMEM;
1160 : : }
1161 : 0 : qdma_dev->num_vqs = dev_conf->nb_vchans;
1162 : :
1163 : 0 : return 0;
1164 : : }
1165 : :
1166 : : static int
1167 : 0 : check_devargs_handler(__rte_unused const char *key,
1168 : : const char *value,
1169 : : __rte_unused void *opaque)
1170 : : {
1171 [ # # ]: 0 : if (strcmp(value, "1"))
1172 : 0 : return -1;
1173 : :
1174 : : return 0;
1175 : : }
1176 : :
1177 : : static int
1178 : 0 : dpaa2_qdma_get_devargs(struct rte_devargs *devargs, const char *key)
1179 : : {
1180 : : struct rte_kvargs *kvlist;
1181 : :
1182 [ # # ]: 0 : if (!devargs)
1183 : : return 0;
1184 : :
1185 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
1186 [ # # ]: 0 : if (!kvlist)
1187 : : return 0;
1188 : :
1189 [ # # ]: 0 : if (!rte_kvargs_count(kvlist, key)) {
1190 : 0 : rte_kvargs_free(kvlist);
1191 : 0 : return 0;
1192 : : }
1193 : :
1194 [ # # ]: 0 : if (rte_kvargs_process(kvlist, key,
1195 : : check_devargs_handler, NULL) < 0) {
1196 : 0 : rte_kvargs_free(kvlist);
1197 : 0 : return 0;
1198 : : }
1199 : 0 : rte_kvargs_free(kvlist);
1200 : :
1201 : 0 : return 1;
1202 : : }
1203 : :
1204 : : /* Enable FD in Ultra Short format */
1205 : : void
1206 : 0 : rte_dpaa2_qdma_vchan_fd_us_enable(int16_t dev_id, uint16_t vchan)
1207 : : {
1208 : 0 : struct rte_dma_fp_object *obj = &rte_dma_fp_objs[dev_id];
1209 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = obj->dev_private;
1210 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1211 : :
1212 : 0 : qdma_dev->vqs[vchan].flags |= DPAA2_QDMA_VQ_FD_SHORT_FORMAT;
1213 : 0 : }
1214 : :
1215 : : /* Enable internal SG processing */
1216 : : void
1217 : 0 : rte_dpaa2_qdma_vchan_internal_sg_enable(int16_t dev_id, uint16_t vchan)
1218 : : {
1219 : 0 : struct rte_dma_fp_object *obj = &rte_dma_fp_objs[dev_id];
1220 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = obj->dev_private;
1221 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1222 : :
1223 : 0 : qdma_dev->vqs[vchan].flags |= DPAA2_QDMA_VQ_FD_SG_FORMAT;
1224 : 0 : }
1225 : :
1226 : : /* Enable RBP */
1227 : : void
1228 : 0 : rte_dpaa2_qdma_vchan_rbp_enable(int16_t dev_id, uint16_t vchan,
1229 : : struct rte_dpaa2_qdma_rbp *rbp_config)
1230 : : {
1231 : 0 : struct rte_dma_fp_object *obj = &rte_dma_fp_objs[dev_id];
1232 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = obj->dev_private;
1233 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1234 : :
1235 : 0 : memcpy(&qdma_dev->vqs[vchan].rbp, rbp_config,
1236 : : sizeof(struct rte_dpaa2_qdma_rbp));
1237 : 0 : }
1238 : :
1239 : : static int
1240 : 0 : dpaa2_qdma_vchan_setup(struct rte_dma_dev *dev, uint16_t vchan,
1241 : : const struct rte_dma_vchan_conf *conf,
1242 : : uint32_t conf_sz)
1243 : : {
1244 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = dev->data->dev_private;
1245 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1246 : : uint32_t pool_size;
1247 : : char ring_name[32];
1248 : : char pool_name[64];
1249 : : int fd_long_format = 1;
1250 : : int sg_enable = 0;
1251 : :
1252 : 0 : DPAA2_QDMA_FUNC_TRACE();
1253 : :
1254 : : RTE_SET_USED(conf_sz);
1255 : :
1256 [ # # ]: 0 : if (qdma_dev->vqs[vchan].flags & DPAA2_QDMA_VQ_FD_SG_FORMAT)
1257 : : sg_enable = 1;
1258 : :
1259 [ # # ]: 0 : if (qdma_dev->vqs[vchan].flags & DPAA2_QDMA_VQ_FD_SHORT_FORMAT)
1260 : : fd_long_format = 0;
1261 : :
1262 [ # # ]: 0 : if (dev->data->dev_conf.enable_silent)
1263 : 0 : qdma_dev->vqs[vchan].flags |= DPAA2_QDMA_VQ_NO_RESPONSE;
1264 : :
1265 [ # # ]: 0 : if (sg_enable) {
1266 [ # # ]: 0 : if (qdma_dev->num_vqs != 1) {
1267 : 0 : DPAA2_QDMA_ERR(
1268 : : "qDMA SG format only supports physical queue!");
1269 : 0 : return -ENODEV;
1270 : : }
1271 [ # # ]: 0 : if (!fd_long_format) {
1272 : 0 : DPAA2_QDMA_ERR(
1273 : : "qDMA SG format only supports long FD format!");
1274 : 0 : return -ENODEV;
1275 : : }
1276 : : pool_size = QDMA_FLE_SG_POOL_SIZE;
1277 : : } else {
1278 : : pool_size = QDMA_FLE_SINGLE_POOL_SIZE;
1279 : : }
1280 : :
1281 [ # # ]: 0 : if (qdma_dev->num_vqs == 1)
1282 : 0 : qdma_dev->vqs[vchan].exclusive_hw_queue = 1;
1283 : : else {
1284 : : /* Allocate a Ring for Virtual Queue in VQ mode */
1285 : 0 : snprintf(ring_name, sizeof(ring_name), "status ring %d %d",
1286 : 0 : dev->data->dev_id, vchan);
1287 : 0 : qdma_dev->vqs[vchan].status_ring = rte_ring_create(ring_name,
1288 : 0 : conf->nb_desc, rte_socket_id(), 0);
1289 [ # # ]: 0 : if (!qdma_dev->vqs[vchan].status_ring) {
1290 : 0 : DPAA2_QDMA_ERR("Status ring creation failed for vq");
1291 : 0 : return rte_errno;
1292 : : }
1293 : : }
1294 : :
1295 : 0 : snprintf(pool_name, sizeof(pool_name),
1296 : : "qdma_fle_pool_dev%d_qid%d", dpdmai_dev->dpdmai_id, vchan);
1297 : 0 : qdma_dev->vqs[vchan].fle_pool = rte_mempool_create(pool_name,
1298 : : conf->nb_desc, pool_size,
1299 : 0 : QDMA_FLE_CACHE_SIZE(conf->nb_desc), 0,
1300 : : NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0);
1301 [ # # ]: 0 : if (!qdma_dev->vqs[vchan].fle_pool) {
1302 : 0 : DPAA2_QDMA_ERR("qdma_fle_pool create failed");
1303 : 0 : return -ENOMEM;
1304 : : }
1305 : :
1306 : 0 : snprintf(pool_name, sizeof(pool_name),
1307 : : "qdma_job_pool_dev%d_qid%d", dpdmai_dev->dpdmai_id, vchan);
1308 : 0 : qdma_dev->vqs[vchan].job_pool = rte_mempool_create(pool_name,
1309 : : conf->nb_desc, pool_size,
1310 : 0 : QDMA_FLE_CACHE_SIZE(conf->nb_desc), 0,
1311 : : NULL, NULL, NULL, NULL, SOCKET_ID_ANY, 0);
1312 [ # # ]: 0 : if (!qdma_dev->vqs[vchan].job_pool) {
1313 : 0 : DPAA2_QDMA_ERR("qdma_job_pool create failed");
1314 : 0 : return -ENOMEM;
1315 : : }
1316 : :
1317 [ # # ]: 0 : if (fd_long_format) {
1318 [ # # ]: 0 : if (sg_enable) {
1319 : 0 : qdma_dev->vqs[vchan].set_fd = dpdmai_dev_set_sg_fd_lf;
1320 : 0 : qdma_dev->vqs[vchan].get_job = dpdmai_dev_get_sg_job_lf;
1321 : : } else {
1322 [ # # ]: 0 : if (dev->data->dev_conf.enable_silent)
1323 : 0 : qdma_dev->vqs[vchan].set_fd =
1324 : : dpdmai_dev_set_multi_fd_lf_no_rsp;
1325 : : else
1326 : 0 : qdma_dev->vqs[vchan].set_fd =
1327 : : dpdmai_dev_set_multi_fd_lf;
1328 : 0 : qdma_dev->vqs[vchan].get_job = dpdmai_dev_get_single_job_lf;
1329 : : }
1330 : : } else {
1331 : 0 : qdma_dev->vqs[vchan].set_fd = dpdmai_dev_set_fd_us;
1332 : 0 : qdma_dev->vqs[vchan].get_job = dpdmai_dev_get_job_us;
1333 : : }
1334 : :
1335 [ # # ]: 0 : if (dpaa2_qdma_get_devargs(dev->device->devargs,
1336 : : DPAA2_QDMA_PREFETCH)) {
1337 : : /* If no prefetch is configured. */
1338 : 0 : qdma_dev->vqs[vchan].dequeue_job =
1339 : : dpdmai_dev_dequeue_multijob_prefetch;
1340 : 0 : DPAA2_QDMA_INFO("Prefetch RX Mode enabled");
1341 : : } else {
1342 : 0 : qdma_dev->vqs[vchan].dequeue_job =
1343 : : dpdmai_dev_dequeue_multijob_no_prefetch;
1344 : : }
1345 : :
1346 : 0 : qdma_dev->vqs[vchan].dpdmai_dev = dpdmai_dev;
1347 : 0 : qdma_dev->vqs[vchan].nb_desc = conf->nb_desc;
1348 : 0 : qdma_dev->vqs[vchan].enqueue_job = dpdmai_dev_submit_multi;
1349 : :
1350 : 0 : return 0;
1351 : : }
1352 : :
1353 : : static int
1354 : 0 : dpaa2_qdma_start(struct rte_dma_dev *dev)
1355 : : {
1356 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = dev->data->dev_private;
1357 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1358 : :
1359 : 0 : DPAA2_QDMA_FUNC_TRACE();
1360 : :
1361 : 0 : qdma_dev->state = 1;
1362 : :
1363 : 0 : return 0;
1364 : : }
1365 : :
1366 : : static int
1367 : 0 : dpaa2_qdma_stop(struct rte_dma_dev *dev)
1368 : : {
1369 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = dev->data->dev_private;
1370 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1371 : :
1372 : 0 : DPAA2_QDMA_FUNC_TRACE();
1373 : :
1374 : 0 : qdma_dev->state = 0;
1375 : :
1376 : 0 : return 0;
1377 : : }
1378 : :
1379 : : static int
1380 : 0 : dpaa2_qdma_reset(struct rte_dma_dev *dev)
1381 : : {
1382 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = dev->data->dev_private;
1383 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1384 : : int i;
1385 : :
1386 : 0 : DPAA2_QDMA_FUNC_TRACE();
1387 : :
1388 : : /* In case QDMA device is not in stopped state, return -EBUSY */
1389 [ # # ]: 0 : if (qdma_dev->state == 1) {
1390 : 0 : DPAA2_QDMA_ERR(
1391 : : "Device is in running state. Stop before reset.");
1392 : 0 : return -EBUSY;
1393 : : }
1394 : :
1395 : : /* In case there are pending jobs on any VQ, return -EBUSY */
1396 [ # # ]: 0 : for (i = 0; i < qdma_dev->num_vqs; i++) {
1397 [ # # ]: 0 : if (qdma_dev->vqs[i].in_use && (qdma_dev->vqs[i].num_enqueues !=
1398 [ # # ]: 0 : qdma_dev->vqs[i].num_dequeues)) {
1399 : 0 : DPAA2_QDMA_ERR("Jobs are still pending on VQ: %d", i);
1400 : 0 : return -EBUSY;
1401 : : }
1402 : : }
1403 : :
1404 : : /* Reset and free virtual queues */
1405 [ # # ]: 0 : for (i = 0; i < qdma_dev->num_vqs; i++) {
1406 : 0 : rte_ring_free(qdma_dev->vqs[i].status_ring);
1407 : : }
1408 : 0 : rte_free(qdma_dev->vqs);
1409 : 0 : qdma_dev->vqs = NULL;
1410 : :
1411 : : /* Reset QDMA device structure */
1412 : 0 : qdma_dev->num_vqs = 0;
1413 : :
1414 : 0 : return 0;
1415 : : }
1416 : :
1417 : : static int
1418 : 0 : dpaa2_qdma_close(__rte_unused struct rte_dma_dev *dev)
1419 : : {
1420 : 0 : DPAA2_QDMA_FUNC_TRACE();
1421 : :
1422 : 0 : dpaa2_qdma_reset(dev);
1423 : :
1424 : 0 : return 0;
1425 : : }
1426 : :
1427 : : static int
1428 : 0 : dpaa2_qdma_stats_get(const struct rte_dma_dev *dmadev, uint16_t vchan,
1429 : : struct rte_dma_stats *rte_stats, uint32_t size)
1430 : : {
1431 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = dmadev->data->dev_private;
1432 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1433 : 0 : struct qdma_virt_queue *qdma_vq = &qdma_dev->vqs[vchan];
1434 : : struct rte_dma_stats *stats = &qdma_vq->stats;
1435 : :
1436 : : RTE_SET_USED(size);
1437 : :
1438 : : /* TODO - directly use stats */
1439 : 0 : stats->submitted = qdma_vq->num_enqueues;
1440 : 0 : stats->completed = qdma_vq->num_dequeues;
1441 : 0 : *rte_stats = *stats;
1442 : :
1443 : 0 : return 0;
1444 : : }
1445 : :
1446 : : static int
1447 : 0 : dpaa2_qdma_stats_reset(struct rte_dma_dev *dmadev, uint16_t vchan)
1448 : : {
1449 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = dmadev->data->dev_private;
1450 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1451 : 0 : struct qdma_virt_queue *qdma_vq = &qdma_dev->vqs[vchan];
1452 : :
1453 : 0 : qdma_vq->num_enqueues = 0;
1454 : 0 : qdma_vq->num_dequeues = 0;
1455 : :
1456 : 0 : return 0;
1457 : : }
1458 : :
1459 : : static uint16_t
1460 : 0 : dpaa2_qdma_burst_capacity(const void *dev_private, uint16_t vchan)
1461 : : {
1462 : : const struct dpaa2_dpdmai_dev *dpdmai_dev = dev_private;
1463 : 0 : struct qdma_device *qdma_dev = dpdmai_dev->qdma_dev;
1464 : 0 : struct qdma_virt_queue *qdma_vq = &qdma_dev->vqs[vchan];
1465 : :
1466 : 0 : return qdma_vq->nb_desc - qdma_vq->num_valid_jobs;
1467 : : }
1468 : :
1469 : : static struct rte_dma_dev_ops dpaa2_qdma_ops = {
1470 : : .dev_info_get = dpaa2_qdma_info_get,
1471 : : .dev_configure = dpaa2_qdma_configure,
1472 : : .dev_start = dpaa2_qdma_start,
1473 : : .dev_stop = dpaa2_qdma_stop,
1474 : : .dev_close = dpaa2_qdma_close,
1475 : : .vchan_setup = dpaa2_qdma_vchan_setup,
1476 : : .stats_get = dpaa2_qdma_stats_get,
1477 : : .stats_reset = dpaa2_qdma_stats_reset,
1478 : : };
1479 : :
1480 : : static int
1481 : 0 : dpaa2_dpdmai_dev_uninit(struct rte_dma_dev *dev)
1482 : : {
1483 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = dev->data->dev_private;
1484 : : int ret;
1485 : :
1486 : 0 : DPAA2_QDMA_FUNC_TRACE();
1487 : :
1488 : 0 : ret = dpdmai_disable(&dpdmai_dev->dpdmai, CMD_PRI_LOW,
1489 : 0 : dpdmai_dev->token);
1490 [ # # ]: 0 : if (ret)
1491 : 0 : DPAA2_QDMA_ERR("dmdmai disable failed");
1492 : :
1493 : : /* Set up the DQRR storage for Rx */
1494 : : struct dpaa2_queue *rxq = &(dpdmai_dev->rx_queue[0]);
1495 : :
1496 [ # # ]: 0 : if (rxq->q_storage) {
1497 : 0 : dpaa2_free_dq_storage(rxq->q_storage);
1498 : 0 : rte_free(rxq->q_storage);
1499 : : }
1500 : :
1501 : : /* Close the device at underlying layer*/
1502 : 0 : ret = dpdmai_close(&dpdmai_dev->dpdmai, CMD_PRI_LOW, dpdmai_dev->token);
1503 [ # # ]: 0 : if (ret)
1504 : 0 : DPAA2_QDMA_ERR("Failure closing dpdmai device");
1505 : :
1506 : 0 : return 0;
1507 : : }
1508 : :
1509 : : static int
1510 : 0 : dpaa2_dpdmai_dev_init(struct rte_dma_dev *dev, int dpdmai_id)
1511 : : {
1512 : 0 : struct dpaa2_dpdmai_dev *dpdmai_dev = dev->data->dev_private;
1513 : : struct dpdmai_rx_queue_cfg rx_queue_cfg;
1514 : : struct dpdmai_attr attr;
1515 : : struct dpdmai_rx_queue_attr rx_attr;
1516 : : struct dpdmai_tx_queue_attr tx_attr;
1517 : : struct dpaa2_queue *rxq;
1518 : : int ret;
1519 : :
1520 : 0 : DPAA2_QDMA_FUNC_TRACE();
1521 : :
1522 : : /* Open DPDMAI device */
1523 : 0 : dpdmai_dev->dpdmai_id = dpdmai_id;
1524 : 0 : dpdmai_dev->dpdmai.regs = dpaa2_get_mcp_ptr(MC_PORTAL_INDEX);
1525 : 0 : dpdmai_dev->qdma_dev = rte_malloc(NULL, sizeof(struct qdma_device),
1526 : : RTE_CACHE_LINE_SIZE);
1527 : 0 : ret = dpdmai_open(&dpdmai_dev->dpdmai, CMD_PRI_LOW,
1528 : 0 : dpdmai_dev->dpdmai_id, &dpdmai_dev->token);
1529 [ # # ]: 0 : if (ret) {
1530 : 0 : DPAA2_QDMA_ERR("dpdmai_open() failed with err: %d", ret);
1531 : 0 : return ret;
1532 : : }
1533 : :
1534 : : /* Get DPDMAI attributes */
1535 : 0 : ret = dpdmai_get_attributes(&dpdmai_dev->dpdmai, CMD_PRI_LOW,
1536 : 0 : dpdmai_dev->token, &attr);
1537 [ # # ]: 0 : if (ret) {
1538 : 0 : DPAA2_QDMA_ERR("dpdmai get attributes failed with err: %d",
1539 : : ret);
1540 : 0 : goto init_err;
1541 : : }
1542 : 0 : dpdmai_dev->num_queues = attr.num_of_queues;
1543 : :
1544 : : /* Set up Rx Queue */
1545 : : memset(&rx_queue_cfg, 0, sizeof(struct dpdmai_rx_queue_cfg));
1546 : 0 : ret = dpdmai_set_rx_queue(&dpdmai_dev->dpdmai,
1547 : : CMD_PRI_LOW,
1548 : 0 : dpdmai_dev->token,
1549 : : 0, 0, &rx_queue_cfg);
1550 [ # # ]: 0 : if (ret) {
1551 : 0 : DPAA2_QDMA_ERR("Setting Rx queue failed with err: %d",
1552 : : ret);
1553 : 0 : goto init_err;
1554 : : }
1555 : :
1556 : : /* Allocate DQ storage for the DPDMAI Rx queues */
1557 : : rxq = &(dpdmai_dev->rx_queue[0]);
1558 : 0 : rxq->q_storage = rte_malloc("dq_storage",
1559 : : sizeof(struct queue_storage_info_t),
1560 : : RTE_CACHE_LINE_SIZE);
1561 [ # # ]: 0 : if (!rxq->q_storage) {
1562 : 0 : DPAA2_QDMA_ERR("q_storage allocation failed");
1563 : : ret = -ENOMEM;
1564 : 0 : goto init_err;
1565 : : }
1566 : :
1567 : : memset(rxq->q_storage, 0, sizeof(struct queue_storage_info_t));
1568 : 0 : ret = dpaa2_alloc_dq_storage(rxq->q_storage);
1569 [ # # ]: 0 : if (ret) {
1570 : 0 : DPAA2_QDMA_ERR("dpaa2_alloc_dq_storage failed");
1571 : 0 : goto init_err;
1572 : : }
1573 : :
1574 : : /* Get Rx and Tx queues FQID */
1575 : 0 : ret = dpdmai_get_rx_queue(&dpdmai_dev->dpdmai, CMD_PRI_LOW,
1576 : 0 : dpdmai_dev->token, 0, 0, &rx_attr);
1577 [ # # ]: 0 : if (ret) {
1578 : 0 : DPAA2_QDMA_ERR("Reading device failed with err: %d",
1579 : : ret);
1580 : 0 : goto init_err;
1581 : : }
1582 : 0 : dpdmai_dev->rx_queue[0].fqid = rx_attr.fqid;
1583 : :
1584 : 0 : ret = dpdmai_get_tx_queue(&dpdmai_dev->dpdmai, CMD_PRI_LOW,
1585 : 0 : dpdmai_dev->token, 0, 0, &tx_attr);
1586 [ # # ]: 0 : if (ret) {
1587 : 0 : DPAA2_QDMA_ERR("Reading device failed with err: %d",
1588 : : ret);
1589 : 0 : goto init_err;
1590 : : }
1591 : 0 : dpdmai_dev->tx_queue[0].fqid = tx_attr.fqid;
1592 : :
1593 : : /* Enable the device */
1594 : 0 : ret = dpdmai_enable(&dpdmai_dev->dpdmai, CMD_PRI_LOW,
1595 : 0 : dpdmai_dev->token);
1596 [ # # ]: 0 : if (ret) {
1597 : 0 : DPAA2_QDMA_ERR("Enabling device failed with err: %d", ret);
1598 : 0 : goto init_err;
1599 : : }
1600 : :
1601 [ # # ]: 0 : if (!dpaa2_coherent_no_alloc_cache) {
1602 [ # # ]: 0 : if (dpaa2_svr_family == SVR_LX2160A) {
1603 : 0 : dpaa2_coherent_no_alloc_cache =
1604 : : DPAA2_LX2_COHERENT_NO_ALLOCATE_CACHE;
1605 : 0 : dpaa2_coherent_alloc_cache =
1606 : : DPAA2_LX2_COHERENT_ALLOCATE_CACHE;
1607 : : } else {
1608 : 0 : dpaa2_coherent_no_alloc_cache =
1609 : : DPAA2_COHERENT_NO_ALLOCATE_CACHE;
1610 : 0 : dpaa2_coherent_alloc_cache =
1611 : : DPAA2_COHERENT_ALLOCATE_CACHE;
1612 : : }
1613 : : }
1614 : :
1615 : 0 : DPAA2_QDMA_DEBUG("Initialized dpdmai object successfully");
1616 : :
1617 : : /* Reset the QDMA device */
1618 : 0 : ret = dpaa2_qdma_reset(dev);
1619 [ # # ]: 0 : if (ret) {
1620 : 0 : DPAA2_QDMA_ERR("Resetting QDMA failed");
1621 : 0 : goto init_err;
1622 : : }
1623 : :
1624 : : return 0;
1625 : 0 : init_err:
1626 : 0 : dpaa2_dpdmai_dev_uninit(dev);
1627 : 0 : return ret;
1628 : : }
1629 : :
1630 : : static int
1631 : 0 : dpaa2_qdma_probe(struct rte_dpaa2_driver *dpaa2_drv,
1632 : : struct rte_dpaa2_device *dpaa2_dev)
1633 : : {
1634 : : struct rte_dma_dev *dmadev;
1635 : : int ret;
1636 : :
1637 : 0 : DPAA2_QDMA_FUNC_TRACE();
1638 : :
1639 : : RTE_SET_USED(dpaa2_drv);
1640 : :
1641 : 0 : dmadev = rte_dma_pmd_allocate(dpaa2_dev->device.name,
1642 : 0 : rte_socket_id(),
1643 : : sizeof(struct dpaa2_dpdmai_dev));
1644 [ # # ]: 0 : if (!dmadev) {
1645 : 0 : DPAA2_QDMA_ERR("Unable to allocate dmadevice");
1646 : 0 : return -EINVAL;
1647 : : }
1648 : :
1649 : 0 : dpaa2_dev->dmadev = dmadev;
1650 : 0 : dmadev->dev_ops = &dpaa2_qdma_ops;
1651 : 0 : dmadev->device = &dpaa2_dev->device;
1652 : 0 : dmadev->fp_obj->dev_private = dmadev->data->dev_private;
1653 : 0 : dmadev->fp_obj->copy = dpaa2_qdma_enqueue;
1654 : 0 : dmadev->fp_obj->submit = dpaa2_qdma_submit;
1655 : 0 : dmadev->fp_obj->completed = dpaa2_qdma_dequeue;
1656 : 0 : dmadev->fp_obj->completed_status = dpaa2_qdma_dequeue_status;
1657 : 0 : dmadev->fp_obj->burst_capacity = dpaa2_qdma_burst_capacity;
1658 : :
1659 : : /* Invoke PMD device initialization function */
1660 : 0 : ret = dpaa2_dpdmai_dev_init(dmadev, dpaa2_dev->object_id);
1661 [ # # ]: 0 : if (ret) {
1662 : 0 : rte_dma_pmd_release(dpaa2_dev->device.name);
1663 : 0 : return ret;
1664 : : }
1665 : :
1666 : 0 : dmadev->state = RTE_DMA_DEV_READY;
1667 : 0 : return 0;
1668 : : }
1669 : :
1670 : : static int
1671 : 0 : dpaa2_qdma_remove(struct rte_dpaa2_device *dpaa2_dev)
1672 : : {
1673 : 0 : struct rte_dma_dev *dmadev = dpaa2_dev->dmadev;
1674 : : int ret;
1675 : :
1676 : 0 : DPAA2_QDMA_FUNC_TRACE();
1677 : :
1678 : 0 : dpaa2_dpdmai_dev_uninit(dmadev);
1679 : :
1680 : 0 : ret = rte_dma_pmd_release(dpaa2_dev->device.name);
1681 [ # # ]: 0 : if (ret)
1682 : 0 : DPAA2_QDMA_ERR("Device cleanup failed");
1683 : :
1684 : 0 : return 0;
1685 : : }
1686 : :
1687 : : static struct rte_dpaa2_driver rte_dpaa2_qdma_pmd;
1688 : :
1689 : : static struct rte_dpaa2_driver rte_dpaa2_qdma_pmd = {
1690 : : .drv_flags = RTE_DPAA2_DRV_IOVA_AS_VA,
1691 : : .drv_type = DPAA2_QDMA,
1692 : : .probe = dpaa2_qdma_probe,
1693 : : .remove = dpaa2_qdma_remove,
1694 : : };
1695 : :
1696 : 235 : RTE_PMD_REGISTER_DPAA2(dpaa2_qdma, rte_dpaa2_qdma_pmd);
1697 : : RTE_PMD_REGISTER_PARAM_STRING(dpaa2_qdma,
1698 : : "no_prefetch=<int> ");
1699 [ - + ]: 235 : RTE_LOG_REGISTER_DEFAULT(dpaa2_qdma_logtype, INFO);
|