Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2021-2024 NXP
3 : : */
4 : :
5 : : #include <bus_dpaa_driver.h>
6 : : #include <rte_dmadev_pmd.h>
7 : : #include <rte_kvargs.h>
8 : :
9 : : #include "dpaa_qdma.h"
10 : : #include "dpaa_qdma_logs.h"
11 : :
12 : : static uint32_t s_sg_max_entry_sz = 2000;
13 : : static bool s_hw_err_check;
14 : :
15 : : #define DPAA_DMA_ERROR_CHECK "dpaa_dma_err_check"
16 : :
17 : : static inline void
18 : : qdma_desc_addr_set64(struct fsl_qdma_comp_cmd_desc *ccdf, u64 addr)
19 : : {
20 : 0 : ccdf->addr_hi = upper_32_bits(addr);
21 : 0 : ccdf->addr_lo = rte_cpu_to_le_32(lower_32_bits(addr));
22 : : }
23 : :
24 : : static inline void
25 : : qdma_desc_sge_addr_set64(struct fsl_qdma_comp_sg_desc *sge, u64 addr)
26 : : {
27 : 0 : sge->addr_hi = upper_32_bits(addr);
28 : 0 : sge->addr_lo = rte_cpu_to_le_32(lower_32_bits(addr));
29 : : }
30 : :
31 : : static inline int
32 : : qdma_ccdf_get_queue(struct fsl_qdma_comp_cmd_desc *ccdf,
33 : : uint8_t *queue_idx)
34 : : {
35 : 0 : uint64_t addr = ((uint64_t)ccdf->addr_hi) << 32 | ccdf->addr_lo;
36 : :
37 : 0 : if (addr && queue_idx)
38 : 0 : *queue_idx = ccdf->queue;
39 [ # # ]: 0 : if (addr) {
40 : 0 : ccdf->addr_hi = 0;
41 : 0 : ccdf->addr_lo = 0;
42 : : return true;
43 : : }
44 : :
45 : : return false;
46 : : }
47 : :
48 : : static inline int
49 : : ilog2(int x)
50 : : {
51 : : int log = 0;
52 : :
53 : 0 : x >>= 1;
54 : :
55 [ # # # # : 0 : while (x) {
# # # # #
# # # ]
56 : 0 : log++;
57 : 0 : x >>= 1;
58 : : }
59 : : return log;
60 : : }
61 : :
62 : : static inline int
63 : : ilog2_qsize(uint32_t q_size)
64 : : {
65 : 0 : return (ilog2(q_size) - ilog2(64));
66 : : }
67 : :
68 : : static inline int
69 : : ilog2_qthld(uint32_t q_thld)
70 : : {
71 : 0 : return (ilog2(q_thld) - ilog2(16));
72 : : }
73 : :
74 : : static inline int
75 : : fsl_qdma_queue_bd_in_hw(struct fsl_qdma_queue *fsl_queue)
76 : : {
77 : : struct rte_dma_stats *stats = &fsl_queue->stats;
78 : :
79 : 0 : return (stats->submitted - stats->completed);
80 : : }
81 : :
82 : : static u32
83 : : qdma_readl(void *addr)
84 : : {
85 : : return QDMA_IN(addr);
86 : : }
87 : :
88 : : static void
89 : : qdma_writel(u32 val, void *addr)
90 : : {
91 : 0 : QDMA_OUT(addr, val);
92 : : }
93 : :
94 : : static u32
95 : : qdma_readl_be(void *addr)
96 : : {
97 : : return QDMA_IN_BE(addr);
98 : : }
99 : :
100 : : static void
101 : : qdma_writel_be(u32 val, void *addr)
102 : : {
103 : : QDMA_OUT_BE(addr, val);
104 : : }
105 : :
106 : : static void *
107 : 0 : dma_pool_alloc(char *nm, int size, int aligned, dma_addr_t *phy_addr)
108 : : {
109 : : void *virt_addr;
110 : :
111 : 0 : virt_addr = rte_zmalloc(nm, size, aligned);
112 [ # # ]: 0 : if (!virt_addr)
113 : : return NULL;
114 : :
115 : 0 : *phy_addr = rte_mem_virt2iova(virt_addr);
116 : :
117 : 0 : return virt_addr;
118 : : }
119 : :
120 : : /*
121 : : * Pre-request command descriptor and compound S/G for enqueue.
122 : : */
123 : : static int
124 : 0 : fsl_qdma_pre_comp_sd_desc(struct fsl_qdma_queue *queue)
125 : : {
126 : 0 : struct fsl_qdma_engine *fsl_qdma = queue->engine;
127 : : struct fsl_qdma_sdf *sdf;
128 : : struct fsl_qdma_ddf *ddf;
129 : : struct fsl_qdma_comp_cmd_desc *ccdf;
130 : : uint16_t i, j;
131 : : struct fsl_qdma_cmpd_ft *ft;
132 : :
133 [ # # ]: 0 : for (i = 0; i < queue->n_cq; i++) {
134 : 0 : dma_addr_t phy_ft = 0;
135 : :
136 : 0 : queue->ft[i] = dma_pool_alloc(NULL,
137 : : sizeof(struct fsl_qdma_cmpd_ft),
138 : : RTE_CACHE_LINE_SIZE, &phy_ft);
139 [ # # ]: 0 : if (!queue->ft[i])
140 : 0 : goto fail;
141 [ # # ]: 0 : if (((uint64_t)queue->ft[i]) &
142 : : (RTE_CACHE_LINE_SIZE - 1)) {
143 : 0 : DPAA_QDMA_ERR("FD[%d] addr(%p) not cache aligned",
144 : : i, queue->ft[i]);
145 : 0 : rte_free(queue->ft[i]);
146 : 0 : queue->ft[i] = NULL;
147 : 0 : goto fail;
148 : : }
149 [ # # ]: 0 : if (((uint64_t)(&queue->ft[i]->desc_ssge[0])) &
150 : : (RTE_CACHE_LINE_SIZE - 1)) {
151 : 0 : DPAA_QDMA_ERR("FD[%d] SGE addr(%p) not cache aligned",
152 : : i, &queue->ft[i]->desc_ssge[0]);
153 : 0 : rte_free(queue->ft[i]);
154 : 0 : queue->ft[i] = NULL;
155 : 0 : goto fail;
156 : : }
157 : 0 : queue->ft[i]->phy_ssge = phy_ft +
158 : : offsetof(struct fsl_qdma_cmpd_ft, desc_ssge);
159 : 0 : queue->ft[i]->phy_dsge = phy_ft +
160 : : offsetof(struct fsl_qdma_cmpd_ft, desc_dsge);
161 : 0 : queue->ft[i]->phy_df = phy_ft +
162 : : offsetof(struct fsl_qdma_cmpd_ft, df);
163 : :
164 : : ft = queue->ft[i];
165 : : sdf = &ft->df.sdf;
166 : : ddf = &ft->df.ddf;
167 : : /* Compound Command Descriptor(Frame List Table) */
168 : : qdma_desc_sge_addr_set64(&ft->desc_buf, ft->phy_df);
169 : : /* It must be 32 as Compound S/G Descriptor */
170 : 0 : ft->desc_buf.length = sizeof(struct fsl_qdma_df);
171 : :
172 : : /* Descriptor Buffer */
173 : 0 : sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
174 : : #ifdef RTE_DMA_DPAA_ERRATA_ERR050265
175 : : sdf->prefetch = 1;
176 : : #endif
177 : 0 : ddf->dwttype = FSL_QDMA_CMD_RWTTYPE;
178 : 0 : ddf->lwc = FSL_QDMA_CMD_LWC;
179 : :
180 : 0 : ccdf = &queue->cq[i];
181 : : qdma_desc_addr_set64(ccdf, phy_ft);
182 : 0 : ccdf->format = FSL_QDMA_COMP_SG_FORMAT;
183 [ # # ]: 0 : if (!fsl_qdma->is_silent)
184 : 0 : ccdf->ser = 1;
185 : 0 : ccdf->queue = queue->queue_id;
186 : : }
187 : 0 : queue->ci = 0;
188 : :
189 : 0 : return 0;
190 : :
191 : : fail:
192 [ # # ]: 0 : for (j = 0; j < i; j++)
193 : 0 : rte_free(queue->ft[j]);
194 : :
195 : : return -ENOMEM;
196 : : }
197 : :
198 : : static int
199 : 0 : fsl_qdma_alloc_queue_resources(struct fsl_qdma_engine *fsl_qdma,
200 : : int queue_id, int block_id)
201 : : {
202 : : struct fsl_qdma_queue *cmd_queue;
203 : : uint32_t queue_size;
204 : : char nm[RTE_MEMZONE_NAMESIZE];
205 : :
206 : : cmd_queue = &fsl_qdma->cmd_queues[block_id][queue_id];
207 : 0 : cmd_queue->engine = fsl_qdma;
208 : :
209 : : queue_size = sizeof(struct fsl_qdma_comp_cmd_desc) *
210 : : QDMA_QUEUE_SIZE;
211 : :
212 : : sprintf(nm, "Command queue_%d_%d",
213 : : block_id, queue_id);
214 : 0 : cmd_queue->cq = dma_pool_alloc(nm, queue_size,
215 : : queue_size, &cmd_queue->bus_addr);
216 [ # # ]: 0 : if (!cmd_queue->cq) {
217 : 0 : DPAA_QDMA_ERR("%s alloc failed!", nm);
218 : 0 : return -ENOMEM;
219 : : }
220 : :
221 : 0 : cmd_queue->block_vir = fsl_qdma->block_base +
222 : 0 : FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, block_id);
223 : 0 : cmd_queue->n_cq = QDMA_QUEUE_SIZE;
224 : 0 : cmd_queue->queue_id = queue_id;
225 : 0 : cmd_queue->block_id = block_id;
226 : 0 : cmd_queue->pending_start = 0;
227 : 0 : cmd_queue->pending_num = 0;
228 : 0 : cmd_queue->complete_start = 0;
229 : :
230 : : sprintf(nm, "Compound Table_%d_%d",
231 : : block_id, queue_id);
232 : 0 : cmd_queue->ft = rte_zmalloc(nm,
233 : : sizeof(void *) * QDMA_QUEUE_SIZE, 0);
234 [ # # ]: 0 : if (!cmd_queue->ft) {
235 : 0 : DPAA_QDMA_ERR("%s zmalloc failed!", nm);
236 : 0 : rte_free(cmd_queue->cq);
237 : 0 : return -ENOMEM;
238 : : }
239 : : sprintf(nm, "Pending_desc_%d_%d",
240 : : block_id, queue_id);
241 : 0 : cmd_queue->pending_desc = rte_zmalloc(nm,
242 : : sizeof(struct fsl_qdma_desc) * FSL_QDMA_MAX_DESC_NUM, 0);
243 [ # # ]: 0 : if (!cmd_queue->pending_desc) {
244 : 0 : DPAA_QDMA_ERR("%s zmalloc failed!", nm);
245 : 0 : rte_free(cmd_queue->ft);
246 : 0 : rte_free(cmd_queue->cq);
247 : 0 : return -ENOMEM;
248 : : }
249 : : sprintf(nm, "complete-burst_ring_%d_%d",
250 : : block_id, queue_id);
251 : 0 : cmd_queue->complete_burst = rte_ring_create(nm,
252 : : QDMA_QUEUE_SIZE * 2, 0,
253 : : RING_F_SP_ENQ | RING_F_SC_DEQ);
254 [ # # ]: 0 : if (!cmd_queue->complete_burst) {
255 : 0 : DPAA_QDMA_ERR("%s create failed!", nm);
256 : 0 : rte_free(cmd_queue->pending_desc);
257 : 0 : rte_free(cmd_queue->ft);
258 : 0 : rte_free(cmd_queue->cq);
259 : 0 : return -ENOMEM;
260 : : }
261 : : sprintf(nm, "complete-desc_ring_%d_%d",
262 : : block_id, queue_id);
263 : 0 : cmd_queue->complete_desc = rte_ring_create(nm,
264 : : FSL_QDMA_MAX_DESC_NUM * 2, 0,
265 : : RING_F_SP_ENQ | RING_F_SC_DEQ);
266 [ # # ]: 0 : if (!cmd_queue->complete_desc) {
267 : 0 : DPAA_QDMA_ERR("%s create failed!", nm);
268 : 0 : rte_ring_free(cmd_queue->complete_burst);
269 : 0 : rte_free(cmd_queue->pending_desc);
270 : 0 : rte_free(cmd_queue->ft);
271 : 0 : rte_free(cmd_queue->cq);
272 : 0 : return -ENOMEM;
273 : : }
274 : : sprintf(nm, "complete-pool-desc_ring_%d_%d",
275 : : block_id, queue_id);
276 : 0 : cmd_queue->complete_pool = rte_ring_create(nm,
277 : : FSL_QDMA_MAX_DESC_NUM * 2, 0,
278 : : RING_F_SP_ENQ | RING_F_SC_DEQ);
279 [ # # ]: 0 : if (!cmd_queue->complete_pool) {
280 : 0 : DPAA_QDMA_ERR("%s create failed!", nm);
281 : 0 : rte_ring_free(cmd_queue->complete_desc);
282 : 0 : rte_ring_free(cmd_queue->complete_burst);
283 : 0 : rte_free(cmd_queue->pending_desc);
284 : 0 : rte_free(cmd_queue->ft);
285 : 0 : rte_free(cmd_queue->cq);
286 : 0 : return -ENOMEM;
287 : : }
288 : :
289 : 0 : memset(&cmd_queue->stats, 0, sizeof(struct rte_dma_stats));
290 : 0 : cmd_queue->pending_max = FSL_QDMA_MAX_DESC_NUM;
291 : :
292 : 0 : return 0;
293 : : }
294 : :
295 : : static void
296 : 0 : fsl_qdma_free_cmdq_res(struct fsl_qdma_queue *queue)
297 : : {
298 : 0 : rte_free(queue->ft);
299 : 0 : rte_free(queue->cq);
300 : 0 : rte_free(queue->pending_desc);
301 : 0 : rte_ring_free(queue->complete_burst);
302 : 0 : rte_ring_free(queue->complete_desc);
303 : 0 : rte_ring_free(queue->complete_pool);
304 : 0 : }
305 : :
306 : : static void
307 : : fsl_qdma_free_stq_res(struct fsl_qdma_status_queue *queue)
308 : : {
309 : 0 : rte_free(queue->cq);
310 : : }
311 : :
312 : : static int
313 : 0 : fsl_qdma_prep_status_queue(struct fsl_qdma_engine *fsl_qdma,
314 : : uint32_t block_id)
315 : : {
316 : : struct fsl_qdma_status_queue *status;
317 : : uint32_t status_size;
318 : :
319 : : status = &fsl_qdma->stat_queues[block_id];
320 : 0 : status->engine = fsl_qdma;
321 : :
322 : : status_size = QDMA_STATUS_SIZE *
323 : : sizeof(struct fsl_qdma_comp_cmd_desc);
324 : :
325 : 0 : status->cq = dma_pool_alloc(NULL, status_size,
326 : : status_size, &status->bus_addr);
327 : :
328 [ # # ]: 0 : if (!status->cq)
329 : : return -ENOMEM;
330 : :
331 : : memset(status->cq, 0x0, status_size);
332 : 0 : status->n_cq = QDMA_STATUS_SIZE;
333 : 0 : status->complete = 0;
334 : 0 : status->block_id = block_id;
335 : 0 : status->block_vir = fsl_qdma->block_base +
336 : 0 : FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, block_id);
337 : :
338 : 0 : return 0;
339 : : }
340 : :
341 : : static int
342 : 0 : fsl_qdma_halt(struct fsl_qdma_engine *fsl_qdma)
343 : : {
344 : 0 : void *ctrl = fsl_qdma->ctrl_base;
345 : : void *block;
346 : : int i, count = RETRIES;
347 : : unsigned int j;
348 : : u32 reg;
349 : :
350 : : /* Disable the command queue and wait for idle state. */
351 : : reg = qdma_readl(ctrl + FSL_QDMA_DMR);
352 [ # # ]: 0 : reg |= FSL_QDMA_DMR_DQD;
353 : : qdma_writel(reg, ctrl + FSL_QDMA_DMR);
354 [ # # ]: 0 : for (j = 0; j < fsl_qdma->num_blocks; j++) {
355 : 0 : block = fsl_qdma->block_base +
356 : 0 : FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, j);
357 [ # # ]: 0 : for (i = 0; i < FSL_QDMA_QUEUE_NUM_MAX; i++)
358 : 0 : qdma_writel(0, block + FSL_QDMA_BCQMR(i));
359 : : }
360 : : while (true) {
361 : 0 : reg = qdma_readl(ctrl + FSL_QDMA_DSR);
362 [ # # ]: 0 : if (!(reg & FSL_QDMA_DSR_DB))
363 : : break;
364 [ # # ]: 0 : if (count-- < 0)
365 : : return -EBUSY;
366 : 0 : rte_delay_us(100);
367 : : }
368 : :
369 [ # # ]: 0 : for (j = 0; j < fsl_qdma->num_blocks; j++) {
370 : 0 : block = fsl_qdma->block_base +
371 : 0 : FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, j);
372 : :
373 : : /* Disable status queue. */
374 : : qdma_writel(0, block + FSL_QDMA_BSQMR);
375 : :
376 : : /*
377 : : * clear the command queue interrupt detect register for
378 : : * all queues.
379 : : */
380 : : qdma_writel(0xffffffff, block + FSL_QDMA_BCQIDR(0));
381 : : }
382 : :
383 : : return 0;
384 : : }
385 : :
386 : : static void
387 : 0 : fsl_qdma_data_validation(struct fsl_qdma_desc *desc[],
388 : : uint8_t num, struct fsl_qdma_queue *fsl_queue)
389 : : {
390 : : uint32_t i, j;
391 : : uint8_t *v_src, *v_dst;
392 : : char err_msg[512];
393 : : int offset;
394 : :
395 : :
396 : 0 : offset = sprintf(err_msg, "Fatal TC%d/queue%d: ",
397 : 0 : fsl_queue->block_id,
398 : 0 : fsl_queue->queue_id);
399 [ # # ]: 0 : for (i = 0; i < num; i++) {
400 : 0 : v_src = rte_mem_iova2virt(desc[i]->src);
401 : 0 : v_dst = rte_mem_iova2virt(desc[i]->dst);
402 [ # # ]: 0 : for (j = 0; j < desc[i]->len; j++) {
403 [ # # ]: 0 : if (v_src[j] != v_dst[j]) {
404 : 0 : sprintf(&err_msg[offset],
405 : : "job[%"PRIu64"]:src(%p)[%d](%d)!=dst(%p)[%d](%d)",
406 : : desc[i]->flag, v_src, j, v_src[j],
407 : : v_dst, j, v_dst[j]);
408 : 0 : DPAA_QDMA_ERR("%s, stop validating!",
409 : : err_msg);
410 : 0 : return;
411 : : }
412 : : }
413 : : }
414 : : }
415 : :
416 : : static int
417 : 0 : fsl_qdma_reg_init(struct fsl_qdma_engine *fsl_qdma)
418 : : {
419 : : struct fsl_qdma_queue *temp;
420 : : struct fsl_qdma_status_queue *temp_stat;
421 : 0 : void *ctrl = fsl_qdma->ctrl_base;
422 : : void *block;
423 : : u32 i, j;
424 : : u32 reg;
425 : : int ret, val;
426 : :
427 : : /* Try to halt the qDMA engine first. */
428 : 0 : ret = fsl_qdma_halt(fsl_qdma);
429 [ # # ]: 0 : if (ret) {
430 : 0 : DPAA_QDMA_ERR("DMA halt failed!");
431 : 0 : return ret;
432 : : }
433 : :
434 [ # # ]: 0 : for (j = 0; j < fsl_qdma->num_blocks; j++) {
435 : 0 : block = fsl_qdma->block_base +
436 : 0 : FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, j);
437 [ # # ]: 0 : for (i = 0; i < QDMA_QUEUES; i++) {
438 : : temp = &fsl_qdma->cmd_queues[j][i];
439 : : /*
440 : : * Initialize Command Queue registers to
441 : : * point to the first
442 : : * command descriptor in memory.
443 : : * Dequeue Pointer Address Registers
444 : : * Enqueue Pointer Address Registers
445 : : */
446 : :
447 : 0 : qdma_writel(lower_32_bits(temp->bus_addr),
448 [ # # ]: 0 : block + FSL_QDMA_BCQDPA_SADDR(i));
449 : 0 : qdma_writel(upper_32_bits(temp->bus_addr),
450 [ # # ]: 0 : block + FSL_QDMA_BCQEDPA_SADDR(i));
451 : 0 : qdma_writel(lower_32_bits(temp->bus_addr),
452 [ # # ]: 0 : block + FSL_QDMA_BCQEPA_SADDR(i));
453 : 0 : qdma_writel(upper_32_bits(temp->bus_addr),
454 [ # # ]: 0 : block + FSL_QDMA_BCQEEPA_SADDR(i));
455 : :
456 : : /* Initialize the queue mode. */
457 : : reg = FSL_QDMA_BCQMR_EN;
458 : 0 : reg |= FSL_QDMA_BCQMR_CD_THLD(ilog2_qthld(temp->n_cq));
459 : 0 : reg |= FSL_QDMA_BCQMR_CQ_SIZE(ilog2_qsize(temp->n_cq));
460 : 0 : temp->le_cqmr = reg;
461 [ # # ]: 0 : qdma_writel(reg, block + FSL_QDMA_BCQMR(i));
462 : : }
463 : :
464 : : /*
465 : : * Workaround for erratum: ERR010812.
466 : : * We must enable XOFF to avoid the enqueue rejection occurs.
467 : : * Setting SQCCMR ENTER_WM to 0x20.
468 : : */
469 : :
470 : : qdma_writel(FSL_QDMA_SQCCMR_ENTER_WM,
471 : : block + FSL_QDMA_SQCCMR);
472 : :
473 : : /*
474 : : * Initialize status queue registers to point to the first
475 : : * command descriptor in memory.
476 : : * Dequeue Pointer Address Registers
477 : : * Enqueue Pointer Address Registers
478 : : */
479 : :
480 : : temp_stat = &fsl_qdma->stat_queues[j];
481 [ # # ]: 0 : qdma_writel(upper_32_bits(temp_stat->bus_addr),
482 : : block + FSL_QDMA_SQEEPAR);
483 [ # # ]: 0 : qdma_writel(lower_32_bits(temp_stat->bus_addr),
484 : : block + FSL_QDMA_SQEPAR);
485 [ # # ]: 0 : qdma_writel(upper_32_bits(temp_stat->bus_addr),
486 : : block + FSL_QDMA_SQEDPAR);
487 [ # # ]: 0 : qdma_writel(lower_32_bits(temp_stat->bus_addr),
488 : : block + FSL_QDMA_SQDPAR);
489 : : /* Desiable status queue interrupt. */
490 : :
491 : : qdma_writel(0x0, block + FSL_QDMA_BCQIER(0));
492 : : qdma_writel(0x0, block + FSL_QDMA_BSQICR);
493 : : qdma_writel(0x0, block + FSL_QDMA_CQIER);
494 : :
495 : : /* Initialize the status queue mode. */
496 : : reg = FSL_QDMA_BSQMR_EN;
497 : 0 : val = ilog2_qsize(temp_stat->n_cq);
498 [ # # ]: 0 : reg |= FSL_QDMA_BSQMR_CQ_SIZE(val);
499 : : qdma_writel(reg, block + FSL_QDMA_BSQMR);
500 : : }
501 : :
502 : : reg = qdma_readl(ctrl + FSL_QDMA_DMR);
503 [ # # ]: 0 : reg &= ~FSL_QDMA_DMR_DQD;
504 : : qdma_writel(reg, ctrl + FSL_QDMA_DMR);
505 : :
506 : 0 : return 0;
507 : : }
508 : :
509 : : static uint16_t
510 : 0 : dpaa_qdma_block_dequeue(struct fsl_qdma_engine *fsl_qdma,
511 : : uint8_t block_id)
512 : : {
513 : : struct fsl_qdma_status_queue *stat_queue;
514 : : struct fsl_qdma_queue *cmd_queue;
515 : : struct fsl_qdma_comp_cmd_desc *cq;
516 : : uint16_t start, count = 0;
517 : : uint8_t qid = 0;
518 : : uint32_t reg;
519 : : int ret;
520 : : uint8_t *block;
521 : : uint16_t *dq_complete;
522 : : struct fsl_qdma_desc *desc[FSL_QDMA_SG_MAX_ENTRY];
523 : :
524 : 0 : stat_queue = &fsl_qdma->stat_queues[block_id];
525 : 0 : cq = stat_queue->cq;
526 : 0 : start = stat_queue->complete;
527 : :
528 : 0 : block = fsl_qdma->block_base +
529 : 0 : FSL_QDMA_BLOCK_BASE_OFFSET(fsl_qdma, block_id);
530 : :
531 : : do {
532 : 0 : reg = qdma_readl_be(block + FSL_QDMA_BSQSR);
533 [ # # ]: 0 : if (reg & FSL_QDMA_BSQSR_QE_BE)
534 : : break;
535 : :
536 : : qdma_writel_be(FSL_QDMA_BSQMR_DI, block + FSL_QDMA_BSQMR);
537 [ # # ]: 0 : ret = qdma_ccdf_get_queue(&cq[start], &qid);
538 : : if (ret == true) {
539 : 0 : cmd_queue = &fsl_qdma->cmd_queues[block_id][qid];
540 : :
541 [ # # # # : 0 : ret = rte_ring_dequeue(cmd_queue->complete_burst,
# ]
542 : : (void **)&dq_complete);
543 : : if (ret) {
544 : 0 : DPAA_QDMA_ERR("DQ desc number failed!");
545 : 0 : break;
546 : : }
547 : :
548 : 0 : ret = rte_ring_dequeue_bulk(cmd_queue->complete_desc,
549 [ # # # # : 0 : (void **)desc, *dq_complete, NULL);
# ]
550 [ # # ]: 0 : if (ret != (*dq_complete)) {
551 : 0 : DPAA_QDMA_ERR("DQ %d descs failed!(%d)",
552 : : *dq_complete, ret);
553 : 0 : break;
554 : : }
555 : :
556 : 0 : fsl_qdma_data_validation(desc, *dq_complete, cmd_queue);
557 : :
558 : 0 : ret = rte_ring_enqueue_bulk(cmd_queue->complete_pool,
559 [ # # # # : 0 : (void **)desc, (*dq_complete), NULL);
# ]
560 [ # # ]: 0 : if (ret != (*dq_complete)) {
561 : 0 : DPAA_QDMA_ERR("Failed desc eq %d!=%d to %s",
562 : : ret, *dq_complete,
563 : : cmd_queue->complete_pool->name);
564 : 0 : break;
565 : : }
566 : :
567 : 0 : cmd_queue->complete_start =
568 : 0 : (cmd_queue->complete_start + (*dq_complete)) &
569 : 0 : (cmd_queue->pending_max - 1);
570 : 0 : cmd_queue->stats.completed++;
571 : :
572 : 0 : start++;
573 [ # # ]: 0 : if (unlikely(start == stat_queue->n_cq))
574 : : start = 0;
575 : 0 : count++;
576 : : } else {
577 : 0 : DPAA_QDMA_ERR("Block%d not empty but dq-queue failed!",
578 : : block_id);
579 : 0 : break;
580 : : }
581 : : } while (1);
582 : 0 : stat_queue->complete = start;
583 : :
584 : 0 : return count;
585 : : }
586 : :
587 : : static int
588 : 0 : fsl_qdma_enqueue_desc_to_ring(struct fsl_qdma_queue *fsl_queue,
589 : : uint16_t num)
590 : : {
591 : 0 : struct fsl_qdma_engine *fsl_qdma = fsl_queue->engine;
592 : : uint16_t i, idx, start, dq;
593 : : int ret, dq_cnt;
594 : :
595 [ # # ]: 0 : if (fsl_qdma->is_silent)
596 : : return 0;
597 : :
598 : 0 : fsl_queue->desc_in_hw[fsl_queue->ci] = num;
599 : 0 : eq_again:
600 : 0 : ret = rte_ring_enqueue(fsl_queue->complete_burst,
601 [ # # # # : 0 : &fsl_queue->desc_in_hw[fsl_queue->ci]);
# ]
602 : : if (ret) {
603 : : DPAA_QDMA_DP_DEBUG("%s: Queue is full, try dequeue first",
604 : : __func__);
605 : : DPAA_QDMA_DP_DEBUG("%s: submitted:%"PRIu64", completed:%"PRIu64"",
606 : : __func__, fsl_queue->stats.submitted,
607 : : fsl_queue->stats.completed);
608 : : dq_cnt = 0;
609 : : dq_again:
610 : 0 : dq = dpaa_qdma_block_dequeue(fsl_queue->engine,
611 : 0 : fsl_queue->block_id);
612 : 0 : dq_cnt++;
613 [ # # ]: 0 : if (dq > 0) {
614 : 0 : goto eq_again;
615 : : } else {
616 [ # # ]: 0 : if (dq_cnt < 100)
617 : 0 : goto dq_again;
618 : 0 : DPAA_QDMA_ERR("%s: Dq block%d failed!",
619 : : __func__, fsl_queue->block_id);
620 : : }
621 : 0 : return ret;
622 : : }
623 : 0 : start = fsl_queue->pending_start;
624 [ # # ]: 0 : for (i = 0; i < num; i++) {
625 : 0 : idx = (start + i) & (fsl_queue->pending_max - 1);
626 : 0 : ret = rte_ring_enqueue(fsl_queue->complete_desc,
627 [ # # # # : 0 : &fsl_queue->pending_desc[idx]);
# ]
628 : : if (ret) {
629 : 0 : DPAA_QDMA_ERR("Descriptors eq failed!");
630 : 0 : return ret;
631 : : }
632 : : }
633 : :
634 : : return 0;
635 : : }
636 : :
637 : : static int
638 : 0 : fsl_qdma_enqueue_overflow(struct fsl_qdma_queue *fsl_queue)
639 : : {
640 : : int overflow = 0;
641 : : uint32_t reg;
642 : : uint16_t blk_drain, check_num, drain_num;
643 : 0 : uint8_t *block = fsl_queue->block_vir;
644 : : const struct rte_dma_stats *st = &fsl_queue->stats;
645 : 0 : struct fsl_qdma_engine *fsl_qdma = fsl_queue->engine;
646 : :
647 : : check_num = 0;
648 : : overflow_check:
649 [ # # # # ]: 0 : if (fsl_qdma->is_silent || unlikely(s_hw_err_check)) {
650 : 0 : reg = qdma_readl_be(block +
651 : 0 : FSL_QDMA_BCQSR(fsl_queue->queue_id));
652 : 0 : overflow = (reg & FSL_QDMA_BCQSR_QF_XOFF_BE) ?
653 : 0 : 1 : 0;
654 : : } else {
655 : 0 : overflow = (fsl_qdma_queue_bd_in_hw(fsl_queue) >=
656 : 0 : QDMA_QUEUE_CR_WM) ? 1 : 0;
657 : : }
658 : :
659 [ # # ]: 0 : if (likely(!overflow)) {
660 : : return 0;
661 [ # # ]: 0 : } else if (fsl_qdma->is_silent) {
662 : 0 : check_num++;
663 [ # # ]: 0 : if (check_num >= 10000) {
664 : 0 : DPAA_QDMA_WARN("Waiting for HW complete in silent mode");
665 : : check_num = 0;
666 : : }
667 : 0 : goto overflow_check;
668 : : }
669 : :
670 : : DPAA_QDMA_DP_DEBUG("TC%d/Q%d submitted(%"PRIu64")-completed(%"PRIu64") >= %d",
671 : : fsl_queue->block_id, fsl_queue->queue_id,
672 : : st->submitted, st->completed, QDMA_QUEUE_CR_WM);
673 : : drain_num = 0;
674 : :
675 : 0 : drain_again:
676 : 0 : blk_drain = dpaa_qdma_block_dequeue(fsl_qdma,
677 : 0 : fsl_queue->block_id);
678 [ # # ]: 0 : if (!blk_drain) {
679 : 0 : drain_num++;
680 [ # # ]: 0 : if (drain_num >= 10000) {
681 : 0 : DPAA_QDMA_WARN("TC%d failed drain, Q%d's %"PRIu64" bd in HW.",
682 : : fsl_queue->block_id, fsl_queue->queue_id,
683 : : st->submitted - st->completed);
684 : : drain_num = 0;
685 : : }
686 : 0 : goto drain_again;
687 : : }
688 : 0 : check_num++;
689 [ # # ]: 0 : if (check_num >= 1000) {
690 : 0 : DPAA_QDMA_WARN("TC%d failed check, Q%d's %"PRIu64" bd in HW.",
691 : : fsl_queue->block_id, fsl_queue->queue_id,
692 : : st->submitted - st->completed);
693 : : check_num = 0;
694 : : }
695 : 0 : goto overflow_check;
696 : :
697 : : return 0;
698 : : }
699 : :
700 : : static int
701 : 0 : fsl_qdma_enqueue_desc_single(struct fsl_qdma_queue *fsl_queue,
702 : : dma_addr_t dst, dma_addr_t src, size_t len)
703 : : {
704 : 0 : uint8_t *block = fsl_queue->block_vir;
705 : : struct fsl_qdma_comp_sg_desc *csgf_src, *csgf_dest;
706 : : struct fsl_qdma_cmpd_ft *ft;
707 : : int ret;
708 : : #ifdef RTE_DMA_DPAA_ERRATA_ERR050757
709 : : struct fsl_qdma_sdf *sdf;
710 : : #endif
711 : :
712 : 0 : ret = fsl_qdma_enqueue_overflow(fsl_queue);
713 [ # # ]: 0 : if (unlikely(ret))
714 : : return ret;
715 : :
716 : 0 : ft = fsl_queue->ft[fsl_queue->ci];
717 : :
718 : : #ifdef RTE_DMA_DPAA_ERRATA_ERR050757
719 : : sdf = &ft->df.sdf;
720 : : sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
721 : : #ifdef RTE_DMA_DPAA_ERRATA_ERR050265
722 : : sdf->prefetch = 1;
723 : : #endif
724 : : if (len > FSL_QDMA_CMD_SS_ERR050757_LEN) {
725 : : sdf->ssen = 1;
726 : : sdf->sss = FSL_QDMA_CMD_SS_ERR050757_LEN;
727 : : sdf->ssd = FSL_QDMA_CMD_SS_ERR050757_LEN;
728 : : } else {
729 : : sdf->ssen = 0;
730 : : sdf->sss = 0;
731 : : sdf->ssd = 0;
732 : : }
733 : : #endif
734 : : csgf_src = &ft->desc_sbuf;
735 : : csgf_dest = &ft->desc_dbuf;
736 : : qdma_desc_sge_addr_set64(csgf_src, src);
737 : 0 : csgf_src->length = len;
738 : 0 : csgf_src->extion = 0;
739 : : qdma_desc_sge_addr_set64(csgf_dest, dst);
740 : 0 : csgf_dest->length = len;
741 : 0 : csgf_dest->extion = 0;
742 : : /* This entry is the last entry. */
743 : 0 : csgf_dest->final = 1;
744 : :
745 : 0 : ret = fsl_qdma_enqueue_desc_to_ring(fsl_queue, 1);
746 [ # # ]: 0 : if (ret)
747 : : return ret;
748 : 0 : fsl_queue->ci = (fsl_queue->ci + 1) & (fsl_queue->n_cq - 1);
749 : :
750 : 0 : qdma_writel(fsl_queue->le_cqmr | FSL_QDMA_BCQMR_EI,
751 [ # # ]: 0 : block + FSL_QDMA_BCQMR(fsl_queue->queue_id));
752 : 0 : fsl_queue->stats.submitted++;
753 : :
754 : 0 : return 0;
755 : : }
756 : :
757 : : static int
758 : 0 : fsl_qdma_enqueue_desc_sg(struct fsl_qdma_queue *fsl_queue)
759 : : {
760 : 0 : uint8_t *block = fsl_queue->block_vir;
761 : : struct fsl_qdma_comp_sg_desc *csgf_src, *csgf_dest;
762 : : struct fsl_qdma_cmpd_ft *ft;
763 : : uint32_t total_len;
764 : : uint16_t start, idx, num, i, next_idx;
765 : : int ret;
766 : : #ifdef RTE_DMA_DPAA_ERRATA_ERR050757
767 : : struct fsl_qdma_sdf *sdf;
768 : : #endif
769 : :
770 : : eq_sg:
771 : : total_len = 0;
772 : 0 : start = fsl_queue->pending_start;
773 [ # # ]: 0 : if (fsl_queue->pending_desc[start].len > s_sg_max_entry_sz ||
774 [ # # ]: 0 : fsl_queue->pending_num == 1) {
775 : 0 : ret = fsl_qdma_enqueue_desc_single(fsl_queue,
776 : : fsl_queue->pending_desc[start].dst,
777 : : fsl_queue->pending_desc[start].src,
778 : : fsl_queue->pending_desc[start].len);
779 [ # # ]: 0 : if (!ret) {
780 : 0 : fsl_queue->pending_start =
781 : 0 : (start + 1) & (fsl_queue->pending_max - 1);
782 : 0 : fsl_queue->pending_num--;
783 : : }
784 [ # # ]: 0 : if (fsl_queue->pending_num > 0)
785 : 0 : goto eq_sg;
786 : :
787 : 0 : return ret;
788 : : }
789 : :
790 : 0 : ret = fsl_qdma_enqueue_overflow(fsl_queue);
791 [ # # ]: 0 : if (unlikely(ret))
792 : 0 : return ret;
793 : :
794 : 0 : if (fsl_queue->pending_num > FSL_QDMA_SG_MAX_ENTRY)
795 : : num = FSL_QDMA_SG_MAX_ENTRY;
796 : : else
797 : : num = fsl_queue->pending_num;
798 : :
799 : 0 : ft = fsl_queue->ft[fsl_queue->ci];
800 : : csgf_src = &ft->desc_sbuf;
801 : : csgf_dest = &ft->desc_dbuf;
802 : :
803 : 0 : qdma_desc_sge_addr_set64(csgf_src, ft->phy_ssge);
804 : 0 : csgf_src->extion = 1;
805 : 0 : qdma_desc_sge_addr_set64(csgf_dest, ft->phy_dsge);
806 : 0 : csgf_dest->extion = 1;
807 : : /* This entry is the last entry. */
808 : 0 : csgf_dest->final = 1;
809 [ # # ]: 0 : for (i = 0; i < num; i++) {
810 : 0 : idx = (start + i) & (fsl_queue->pending_max - 1);
811 : 0 : qdma_desc_sge_addr_set64(&ft->desc_ssge[i],
812 : 0 : fsl_queue->pending_desc[idx].src);
813 : 0 : ft->desc_ssge[i].length = fsl_queue->pending_desc[idx].len;
814 : 0 : ft->desc_ssge[i].final = 0;
815 : 0 : qdma_desc_sge_addr_set64(&ft->desc_dsge[i],
816 : : fsl_queue->pending_desc[idx].dst);
817 : 0 : ft->desc_dsge[i].length = fsl_queue->pending_desc[idx].len;
818 : 0 : ft->desc_dsge[i].final = 0;
819 : 0 : total_len += fsl_queue->pending_desc[idx].len;
820 [ # # ]: 0 : if ((i + 1) != num) {
821 : 0 : next_idx = (idx + 1) & (fsl_queue->pending_max - 1);
822 [ # # ]: 0 : if (fsl_queue->pending_desc[next_idx].len >
823 : : s_sg_max_entry_sz) {
824 : 0 : num = i + 1;
825 : 0 : break;
826 : : }
827 : : }
828 : : }
829 : :
830 : 0 : ft->desc_ssge[num - 1].final = 1;
831 : 0 : ft->desc_dsge[num - 1].final = 1;
832 : 0 : csgf_src->length = total_len;
833 : 0 : csgf_dest->length = total_len;
834 : : #ifdef RTE_DMA_DPAA_ERRATA_ERR050757
835 : : sdf = &ft->df.sdf;
836 : : sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
837 : : #ifdef RTE_DMA_DPAA_ERRATA_ERR050265
838 : : sdf->prefetch = 1;
839 : : #endif
840 : : if (total_len > FSL_QDMA_CMD_SS_ERR050757_LEN) {
841 : : sdf->ssen = 1;
842 : : sdf->sss = FSL_QDMA_CMD_SS_ERR050757_LEN;
843 : : sdf->ssd = FSL_QDMA_CMD_SS_ERR050757_LEN;
844 : : } else {
845 : : sdf->ssen = 0;
846 : : sdf->sss = 0;
847 : : sdf->ssd = 0;
848 : : }
849 : : #endif
850 : 0 : ret = fsl_qdma_enqueue_desc_to_ring(fsl_queue, num);
851 [ # # ]: 0 : if (ret)
852 : 0 : return ret;
853 : :
854 : 0 : fsl_queue->ci = (fsl_queue->ci + 1) & (fsl_queue->n_cq - 1);
855 : :
856 : 0 : qdma_writel(fsl_queue->le_cqmr | FSL_QDMA_BCQMR_EI,
857 [ # # ]: 0 : block + FSL_QDMA_BCQMR(fsl_queue->queue_id));
858 : 0 : fsl_queue->stats.submitted++;
859 : :
860 : 0 : fsl_queue->pending_start =
861 : 0 : (start + num) & (fsl_queue->pending_max - 1);
862 : 0 : fsl_queue->pending_num -= num;
863 [ # # ]: 0 : if (fsl_queue->pending_num > 0)
864 : 0 : goto eq_sg;
865 : :
866 : : return 0;
867 : : }
868 : :
869 : : static int
870 : 0 : fsl_qdma_enqueue_desc(struct fsl_qdma_queue *fsl_queue)
871 : : {
872 : 0 : uint16_t start = fsl_queue->pending_start;
873 : : int ret;
874 : :
875 [ # # ]: 0 : if (fsl_queue->pending_num == 1) {
876 : 0 : ret = fsl_qdma_enqueue_desc_single(fsl_queue,
877 : : fsl_queue->pending_desc[start].dst,
878 : : fsl_queue->pending_desc[start].src,
879 : 0 : fsl_queue->pending_desc[start].len);
880 [ # # ]: 0 : if (!ret) {
881 : 0 : fsl_queue->pending_start =
882 : 0 : (start + 1) & (fsl_queue->pending_max - 1);
883 : 0 : fsl_queue->pending_num = 0;
884 : : }
885 : 0 : return ret;
886 : : }
887 : :
888 : 0 : return fsl_qdma_enqueue_desc_sg(fsl_queue);
889 : : }
890 : :
891 : : static int
892 : 0 : dpaa_qdma_info_get(const struct rte_dma_dev *dev,
893 : : struct rte_dma_info *dev_info, __rte_unused uint32_t info_sz)
894 : : {
895 : 0 : struct fsl_qdma_engine *fsl_qdma = dev->data->dev_private;
896 : :
897 : : dev_info->dev_capa = RTE_DMA_CAPA_MEM_TO_MEM |
898 : : RTE_DMA_CAPA_SILENT | RTE_DMA_CAPA_OPS_COPY |
899 : : RTE_DMA_CAPA_OPS_COPY_SG;
900 : 0 : dev_info->dev_capa |= DPAA_QDMA_FLAGS_INDEX;
901 : 0 : dev_info->max_vchans = fsl_qdma->n_queues;
902 : 0 : dev_info->max_desc = FSL_QDMA_MAX_DESC_NUM;
903 : 0 : dev_info->min_desc = QDMA_QUEUE_SIZE;
904 : 0 : dev_info->max_sges = FSL_QDMA_SG_MAX_ENTRY;
905 : :
906 : 0 : return 0;
907 : : }
908 : :
909 : : static int
910 : 0 : dpaa_get_channel(struct fsl_qdma_engine *fsl_qdma,
911 : : uint16_t vchan)
912 : : {
913 : : int ret, i, j, found = 0;
914 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
915 : :
916 [ # # ]: 0 : if (fsl_queue) {
917 : : found = 1;
918 : 0 : goto queue_found;
919 : : }
920 : :
921 [ # # ]: 0 : for (i = 0; i < QDMA_BLOCKS; i++) {
922 [ # # ]: 0 : for (j = 0; j < QDMA_QUEUES; j++) {
923 : 0 : fsl_queue = &fsl_qdma->cmd_queues[i][j];
924 : :
925 [ # # ]: 0 : if (fsl_queue->channel_id == vchan) {
926 : : found = 1;
927 : 0 : fsl_qdma->chan[vchan] = fsl_queue;
928 : 0 : goto queue_found;
929 : : }
930 : : }
931 : : }
932 : :
933 : 0 : queue_found:
934 : : if (!found)
935 : : return -ENXIO;
936 : :
937 [ # # ]: 0 : if (fsl_queue->used)
938 : : return 0;
939 : :
940 : 0 : ret = fsl_qdma_pre_comp_sd_desc(fsl_queue);
941 [ # # ]: 0 : if (ret)
942 : : return ret;
943 : :
944 : 0 : fsl_queue->used = 1;
945 : 0 : fsl_qdma->block_queues[fsl_queue->block_id]++;
946 : :
947 : 0 : return 0;
948 : : }
949 : :
950 : : static int
951 : 0 : dpaa_qdma_configure(struct rte_dma_dev *dmadev,
952 : : const struct rte_dma_conf *dev_conf,
953 : : __rte_unused uint32_t conf_sz)
954 : : {
955 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
956 : :
957 : 0 : fsl_qdma->is_silent = dev_conf->enable_silent;
958 : 0 : return 0;
959 : : }
960 : :
961 : : static int
962 : 0 : dpaa_qdma_start(__rte_unused struct rte_dma_dev *dev)
963 : : {
964 : 0 : return 0;
965 : : }
966 : :
967 : : static int
968 : 0 : dpaa_qdma_close(__rte_unused struct rte_dma_dev *dev)
969 : : {
970 : 0 : return 0;
971 : : }
972 : :
973 : : static int
974 : 0 : dpaa_qdma_queue_setup(struct rte_dma_dev *dmadev,
975 : : uint16_t vchan,
976 : : __rte_unused const struct rte_dma_vchan_conf *conf,
977 : : __rte_unused uint32_t conf_sz)
978 : : {
979 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
980 : :
981 : 0 : return dpaa_get_channel(fsl_qdma, vchan);
982 : : }
983 : :
984 : : static int
985 : 0 : dpaa_qdma_submit(void *dev_private, uint16_t vchan)
986 : : {
987 : : struct fsl_qdma_engine *fsl_qdma = dev_private;
988 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
989 : :
990 [ # # ]: 0 : if (!fsl_queue->pending_num)
991 : : return 0;
992 : :
993 : 0 : return fsl_qdma_enqueue_desc(fsl_queue);
994 : : }
995 : :
996 : : static int
997 : 0 : dpaa_qdma_enqueue(void *dev_private, uint16_t vchan,
998 : : rte_iova_t src, rte_iova_t dst,
999 : : uint32_t length, uint64_t flags)
1000 : : {
1001 : : struct fsl_qdma_engine *fsl_qdma = dev_private;
1002 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1003 : 0 : uint16_t start = fsl_queue->pending_start;
1004 : 0 : uint8_t pending = fsl_queue->pending_num;
1005 : : uint16_t idx;
1006 : : int ret;
1007 : :
1008 [ # # ]: 0 : if (pending >= fsl_queue->pending_max) {
1009 : 0 : DPAA_QDMA_ERR("Too many pending jobs(%d) on queue%d",
1010 : : pending, vchan);
1011 : 0 : return -ENOSPC;
1012 : : }
1013 : 0 : idx = (start + pending) & (fsl_queue->pending_max - 1);
1014 : :
1015 : 0 : fsl_queue->pending_desc[idx].src = src;
1016 : 0 : fsl_queue->pending_desc[idx].dst = dst;
1017 : 0 : fsl_queue->pending_desc[idx].flag =
1018 : 0 : DPAA_QDMA_IDX_FROM_FLAG(flags);
1019 : 0 : fsl_queue->pending_desc[idx].len = length;
1020 : 0 : fsl_queue->pending_num++;
1021 : :
1022 [ # # ]: 0 : if (!(flags & RTE_DMA_OP_FLAG_SUBMIT))
1023 : 0 : return idx;
1024 : :
1025 : 0 : ret = fsl_qdma_enqueue_desc(fsl_queue);
1026 [ # # ]: 0 : if (!ret)
1027 : 0 : return fsl_queue->pending_start;
1028 : :
1029 : : return ret;
1030 : : }
1031 : :
1032 : : static int
1033 : 0 : dpaa_qdma_copy_sg(void *dev_private,
1034 : : uint16_t vchan,
1035 : : const struct rte_dma_sge *src,
1036 : : const struct rte_dma_sge *dst,
1037 : : uint16_t nb_src, uint16_t nb_dst,
1038 : : uint64_t flags)
1039 : : {
1040 : : int ret;
1041 : : uint16_t i, start, idx;
1042 : : struct fsl_qdma_engine *fsl_qdma = dev_private;
1043 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1044 : : const uint16_t *idx_addr = NULL;
1045 : :
1046 [ # # ]: 0 : if (unlikely(nb_src != nb_dst)) {
1047 : 0 : DPAA_QDMA_ERR("%s: nb_src(%d) != nb_dst(%d) on queue%d",
1048 : : __func__, nb_src, nb_dst, vchan);
1049 : 0 : return -EINVAL;
1050 : : }
1051 : :
1052 [ # # ]: 0 : if ((fsl_queue->pending_num + nb_src) > FSL_QDMA_SG_MAX_ENTRY) {
1053 : 0 : DPAA_QDMA_ERR("Too many pending jobs on queue%d",
1054 : : vchan);
1055 : 0 : return -ENOSPC;
1056 : : }
1057 : 0 : start = fsl_queue->pending_start + fsl_queue->pending_num;
1058 : 0 : start = start & (fsl_queue->pending_max - 1);
1059 : : idx = start;
1060 : :
1061 : 0 : idx_addr = DPAA_QDMA_IDXADDR_FROM_SG_FLAG(flags);
1062 : :
1063 [ # # ]: 0 : for (i = 0; i < nb_src; i++) {
1064 [ # # ]: 0 : if (unlikely(src[i].length != dst[i].length)) {
1065 : 0 : DPAA_QDMA_ERR("src.len(%d) != dst.len(%d)",
1066 : : src[i].length, dst[i].length);
1067 : 0 : return -EINVAL;
1068 : : }
1069 : 0 : idx = (start + i) & (fsl_queue->pending_max - 1);
1070 : 0 : fsl_queue->pending_desc[idx].src = src[i].addr;
1071 : 0 : fsl_queue->pending_desc[idx].dst = dst[i].addr;
1072 : 0 : fsl_queue->pending_desc[idx].len = dst[i].length;
1073 : 0 : fsl_queue->pending_desc[idx].flag = idx_addr[i];
1074 : : }
1075 : 0 : fsl_queue->pending_num += nb_src;
1076 : :
1077 [ # # ]: 0 : if (!(flags & RTE_DMA_OP_FLAG_SUBMIT))
1078 : 0 : return idx;
1079 : :
1080 : 0 : ret = fsl_qdma_enqueue_desc(fsl_queue);
1081 [ # # ]: 0 : if (!ret)
1082 : 0 : return fsl_queue->pending_start;
1083 : :
1084 : : return ret;
1085 : : }
1086 : :
1087 : : static int
1088 : 0 : dpaa_qdma_err_handle(struct fsl_qdma_err_reg *reg)
1089 : : {
1090 : : struct fsl_qdma_err_reg local;
1091 : : size_t i, offset = 0;
1092 : : char err_msg[512];
1093 : :
1094 : : local.dedr_be = rte_read32(®->dedr_be);
1095 [ # # ]: 0 : if (!local.dedr_be)
1096 : : return 0;
1097 : 0 : offset = sprintf(err_msg, "ERR detected:");
1098 [ # # ]: 0 : if (local.dedr.ere) {
1099 : 0 : offset += sprintf(&err_msg[offset],
1100 : : " ere(Enqueue rejection error)");
1101 : : }
1102 [ # # ]: 0 : if (local.dedr.dde) {
1103 : 0 : offset += sprintf(&err_msg[offset],
1104 : : " dde(Destination descriptor error)");
1105 : : }
1106 [ # # ]: 0 : if (local.dedr.sde) {
1107 : 0 : offset += sprintf(&err_msg[offset],
1108 : : " sde(Source descriptor error)");
1109 : : }
1110 [ # # ]: 0 : if (local.dedr.cde) {
1111 : 0 : offset += sprintf(&err_msg[offset],
1112 : : " cde(Command descriptor error)");
1113 : : }
1114 [ # # ]: 0 : if (local.dedr.wte) {
1115 : 0 : offset += sprintf(&err_msg[offset],
1116 : : " wte(Write transaction error)");
1117 : : }
1118 [ # # ]: 0 : if (local.dedr.rte) {
1119 : 0 : offset += sprintf(&err_msg[offset],
1120 : : " rte(Read transaction error)");
1121 : : }
1122 [ # # ]: 0 : if (local.dedr.me) {
1123 : 0 : offset += sprintf(&err_msg[offset],
1124 : : " me(Multiple errors of the same type)");
1125 : : }
1126 : 0 : DPAA_QDMA_ERR("%s", err_msg);
1127 [ # # ]: 0 : for (i = 0; i < FSL_QDMA_DECCD_ERR_NUM; i++) {
1128 : 0 : local.deccd_le[FSL_QDMA_DECCD_ERR_NUM - 1 - i] =
1129 : : QDMA_IN(®->deccd_le[i]);
1130 : : }
1131 : 0 : local.deccqidr_be = rte_read32(®->deccqidr_be);
1132 : : local.decbr = rte_read32(®->decbr);
1133 : :
1134 : 0 : offset = sprintf(err_msg, "ERR command:");
1135 : 0 : offset += sprintf(&err_msg[offset],
1136 : : " status: %02x, ser: %d, offset:%d, fmt: %02x",
1137 : 0 : local.err_cmd.status, local.err_cmd.ser,
1138 : 0 : local.err_cmd.offset, local.err_cmd.format);
1139 : 0 : offset += sprintf(&err_msg[offset],
1140 : : " address: 0x%"PRIx64", queue: %d, dd: %02x",
1141 : 0 : (uint64_t)local.err_cmd.addr_hi << 32 |
1142 : 0 : local.err_cmd.addr_lo,
1143 : 0 : local.err_cmd.queue, local.err_cmd.dd);
1144 : 0 : DPAA_QDMA_ERR("%s", err_msg);
1145 : 0 : DPAA_QDMA_ERR("ERR command block: %d, queue: %d",
1146 : : local.deccqidr.block, local.deccqidr.queue);
1147 : :
1148 : : rte_write32(local.dedr_be, ®->dedr_be);
1149 : :
1150 : 0 : return -EIO;
1151 : : }
1152 : :
1153 : : static uint16_t
1154 : 0 : dpaa_qdma_dequeue_status(void *dev_private, uint16_t vchan,
1155 : : const uint16_t nb_cpls, uint16_t *last_idx,
1156 : : enum rte_dma_status_code *st)
1157 : 0 : {
1158 : : struct fsl_qdma_engine *fsl_qdma = dev_private;
1159 : : int err;
1160 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1161 : 0 : void *status = fsl_qdma->status_base;
1162 : 0 : struct fsl_qdma_desc *desc_complete[nb_cpls];
1163 : : uint16_t i, dq_num;
1164 : :
1165 [ # # ]: 0 : if (unlikely(fsl_qdma->is_silent)) {
1166 : 0 : DPAA_QDMA_WARN("Can't dq in silent mode");
1167 : :
1168 : 0 : return 0;
1169 : : }
1170 : :
1171 : 0 : dq_num = dpaa_qdma_block_dequeue(fsl_qdma,
1172 : 0 : fsl_queue->block_id);
1173 : : DPAA_QDMA_DP_DEBUG("%s: block dq(%d)",
1174 : : __func__, dq_num);
1175 : :
1176 [ # # # # : 0 : dq_num = rte_ring_dequeue_burst(fsl_queue->complete_pool,
# ]
1177 : : (void **)desc_complete, nb_cpls, NULL);
1178 [ # # ]: 0 : for (i = 0; i < dq_num; i++)
1179 : 0 : last_idx[i] = desc_complete[i]->flag;
1180 : :
1181 [ # # ]: 0 : if (st) {
1182 [ # # ]: 0 : for (i = 0; i < dq_num; i++)
1183 : 0 : st[i] = RTE_DMA_STATUS_SUCCESSFUL;
1184 : : }
1185 : :
1186 [ # # ]: 0 : if (s_hw_err_check) {
1187 : 0 : err = dpaa_qdma_err_handle(status +
1188 : : FSL_QDMA_ERR_REG_STATUS_OFFSET);
1189 [ # # ]: 0 : if (err)
1190 : 0 : fsl_queue->stats.errors++;
1191 : : }
1192 : :
1193 : : return dq_num;
1194 : : }
1195 : :
1196 : : static uint16_t
1197 : 0 : dpaa_qdma_dequeue(void *dev_private,
1198 : : uint16_t vchan, const uint16_t nb_cpls,
1199 : : uint16_t *last_idx, bool *has_error)
1200 : 0 : {
1201 : : struct fsl_qdma_engine *fsl_qdma = dev_private;
1202 : : int err;
1203 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1204 : 0 : void *status = fsl_qdma->status_base;
1205 : 0 : struct fsl_qdma_desc *desc_complete[nb_cpls];
1206 : : uint16_t i, dq_num;
1207 : :
1208 [ # # ]: 0 : if (unlikely(fsl_qdma->is_silent)) {
1209 : 0 : DPAA_QDMA_WARN("Can't dq in silent mode");
1210 : :
1211 : 0 : return 0;
1212 : : }
1213 : :
1214 : 0 : *has_error = false;
1215 : 0 : dq_num = dpaa_qdma_block_dequeue(fsl_qdma,
1216 : 0 : fsl_queue->block_id);
1217 : : DPAA_QDMA_DP_DEBUG("%s: block dq(%d)",
1218 : : __func__, dq_num);
1219 : :
1220 [ # # # # : 0 : dq_num = rte_ring_dequeue_burst(fsl_queue->complete_pool,
# ]
1221 : : (void **)desc_complete, nb_cpls, NULL);
1222 [ # # ]: 0 : for (i = 0; i < dq_num; i++)
1223 : 0 : last_idx[i] = desc_complete[i]->flag;
1224 : :
1225 [ # # ]: 0 : if (s_hw_err_check) {
1226 : 0 : err = dpaa_qdma_err_handle(status +
1227 : : FSL_QDMA_ERR_REG_STATUS_OFFSET);
1228 [ # # ]: 0 : if (err) {
1229 : : if (has_error)
1230 : 0 : *has_error = true;
1231 : 0 : fsl_queue->stats.errors++;
1232 : : }
1233 : : }
1234 : :
1235 : : return dq_num;
1236 : : }
1237 : :
1238 : : static int
1239 : 0 : dpaa_qdma_stats_get(const struct rte_dma_dev *dmadev,
1240 : : uint16_t vchan, struct rte_dma_stats *rte_stats, uint32_t size)
1241 : : {
1242 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
1243 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1244 : : struct rte_dma_stats *stats = &fsl_queue->stats;
1245 : :
1246 [ # # ]: 0 : if (size < sizeof(rte_stats))
1247 : : return -EINVAL;
1248 [ # # ]: 0 : if (rte_stats == NULL)
1249 : : return -EINVAL;
1250 : :
1251 : 0 : *rte_stats = *stats;
1252 : :
1253 : 0 : return 0;
1254 : : }
1255 : :
1256 : : static int
1257 : 0 : dpaa_qdma_stats_reset(struct rte_dma_dev *dmadev, uint16_t vchan)
1258 : : {
1259 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
1260 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1261 : :
1262 : 0 : memset(&fsl_queue->stats, 0, sizeof(struct rte_dma_stats));
1263 : :
1264 : 0 : return 0;
1265 : : }
1266 : :
1267 : : static uint16_t
1268 : 0 : dpaa_qdma_burst_capacity(const void *dev_private, uint16_t vchan)
1269 : : {
1270 : : const struct fsl_qdma_engine *fsl_qdma = dev_private;
1271 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1272 : :
1273 : 0 : return fsl_queue->pending_max - fsl_queue->pending_num;
1274 : : }
1275 : :
1276 : : static struct rte_dma_dev_ops dpaa_qdma_ops = {
1277 : : .dev_info_get = dpaa_qdma_info_get,
1278 : : .dev_configure = dpaa_qdma_configure,
1279 : : .dev_start = dpaa_qdma_start,
1280 : : .dev_close = dpaa_qdma_close,
1281 : : .vchan_setup = dpaa_qdma_queue_setup,
1282 : : .stats_get = dpaa_qdma_stats_get,
1283 : : .stats_reset = dpaa_qdma_stats_reset,
1284 : : };
1285 : :
1286 : : static int
1287 : 0 : check_devargs_handler(__rte_unused const char *key, const char *value,
1288 : : __rte_unused void *opaque)
1289 : : {
1290 [ # # ]: 0 : if (strcmp(value, "1"))
1291 : 0 : return -1;
1292 : :
1293 : : return 0;
1294 : : }
1295 : :
1296 : : static int
1297 : 0 : dpaa_get_devargs(struct rte_devargs *devargs, const char *key)
1298 : : {
1299 : : struct rte_kvargs *kvlist;
1300 : :
1301 [ # # ]: 0 : if (!devargs)
1302 : : return 0;
1303 : :
1304 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
1305 [ # # ]: 0 : if (!kvlist)
1306 : : return 0;
1307 : :
1308 [ # # ]: 0 : if (!rte_kvargs_count(kvlist, key)) {
1309 : 0 : rte_kvargs_free(kvlist);
1310 : 0 : return 0;
1311 : : }
1312 : :
1313 [ # # ]: 0 : if (rte_kvargs_process(kvlist, key,
1314 : : check_devargs_handler, NULL) < 0) {
1315 : 0 : rte_kvargs_free(kvlist);
1316 : 0 : return 0;
1317 : : }
1318 : 0 : rte_kvargs_free(kvlist);
1319 : :
1320 : 0 : return 1;
1321 : : }
1322 : :
1323 : : static int
1324 : 0 : dpaa_qdma_init(struct rte_dma_dev *dmadev)
1325 : : {
1326 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
1327 : : uint64_t phys_addr;
1328 : : int ccsr_qdma_fd;
1329 : : int regs_size;
1330 : : int ret;
1331 : : uint32_t i, j, k;
1332 : :
1333 [ # # ]: 0 : if (dpaa_get_devargs(dmadev->device->devargs, DPAA_DMA_ERROR_CHECK)) {
1334 : 0 : s_hw_err_check = true;
1335 : 0 : DPAA_QDMA_INFO("Enable DMA error checks");
1336 : : }
1337 : :
1338 : 0 : fsl_qdma->n_queues = QDMA_QUEUES * QDMA_BLOCKS;
1339 : 0 : fsl_qdma->num_blocks = QDMA_BLOCKS;
1340 : 0 : fsl_qdma->block_offset = QDMA_BLOCK_OFFSET;
1341 : :
1342 : : ccsr_qdma_fd = open("/dev/mem", O_RDWR);
1343 [ # # ]: 0 : if (unlikely(ccsr_qdma_fd < 0)) {
1344 : 0 : DPAA_QDMA_ERR("Can not open /dev/mem for qdma CCSR map");
1345 : 0 : return ccsr_qdma_fd;
1346 : : }
1347 : :
1348 : 0 : regs_size = fsl_qdma->block_offset * fsl_qdma->num_blocks;
1349 : 0 : regs_size += (QDMA_CTRL_REGION_SIZE + QDMA_STATUS_REGION_SIZE);
1350 : : phys_addr = QDMA_CCSR_BASE;
1351 : 0 : fsl_qdma->reg_base = mmap(NULL, regs_size,
1352 : : PROT_READ | PROT_WRITE, MAP_SHARED,
1353 : : ccsr_qdma_fd, phys_addr);
1354 : :
1355 : 0 : close(ccsr_qdma_fd);
1356 [ # # ]: 0 : if (fsl_qdma->reg_base == MAP_FAILED) {
1357 : 0 : DPAA_QDMA_ERR("Map qdma reg: Phys(0x%"PRIx64"), size(%d)",
1358 : : phys_addr, regs_size);
1359 : 0 : return -ENOMEM;
1360 : : }
1361 : :
1362 : 0 : fsl_qdma->ctrl_base =
1363 : : fsl_qdma->reg_base + QDMA_CTRL_REGION_OFFSET;
1364 : 0 : fsl_qdma->status_base =
1365 : 0 : fsl_qdma->reg_base + QDMA_STATUS_REGION_OFFSET;
1366 : 0 : fsl_qdma->block_base =
1367 : 0 : fsl_qdma->status_base + QDMA_STATUS_REGION_SIZE;
1368 : :
1369 [ # # ]: 0 : for (i = 0; i < QDMA_BLOCKS; i++) {
1370 : 0 : ret = fsl_qdma_prep_status_queue(fsl_qdma, i);
1371 [ # # ]: 0 : if (ret)
1372 : 0 : goto mem_free;
1373 : : }
1374 : :
1375 : : k = 0;
1376 [ # # ]: 0 : for (i = 0; i < QDMA_QUEUES; i++) {
1377 [ # # ]: 0 : for (j = 0; j < QDMA_BLOCKS; j++) {
1378 : 0 : ret = fsl_qdma_alloc_queue_resources(fsl_qdma, i, j);
1379 [ # # ]: 0 : if (ret)
1380 : 0 : goto mem_free;
1381 : 0 : fsl_qdma->cmd_queues[j][i].channel_id = k;
1382 : 0 : k++;
1383 : : }
1384 : : }
1385 : :
1386 : 0 : ret = fsl_qdma_reg_init(fsl_qdma);
1387 [ # # ]: 0 : if (ret) {
1388 : 0 : DPAA_QDMA_ERR("Can't Initialize the qDMA engine.");
1389 : 0 : goto mem_free;
1390 : : }
1391 : :
1392 : : return 0;
1393 : :
1394 : 0 : mem_free:
1395 [ # # ]: 0 : for (i = 0; i < fsl_qdma->num_blocks; i++)
1396 : : fsl_qdma_free_stq_res(&fsl_qdma->stat_queues[i]);
1397 : :
1398 [ # # ]: 0 : for (i = 0; i < fsl_qdma->num_blocks; i++) {
1399 [ # # ]: 0 : for (j = 0; j < QDMA_QUEUES; j++)
1400 : 0 : fsl_qdma_free_cmdq_res(&fsl_qdma->cmd_queues[i][j]);
1401 : : }
1402 : :
1403 : 0 : munmap(fsl_qdma->ctrl_base, regs_size);
1404 : :
1405 : 0 : return ret;
1406 : : }
1407 : :
1408 : : static int
1409 : 0 : dpaa_qdma_probe(__rte_unused struct rte_dpaa_driver *dpaa_drv,
1410 : : struct rte_dpaa_device *dpaa_dev)
1411 : : {
1412 : : struct rte_dma_dev *dmadev;
1413 : : int ret;
1414 : :
1415 : 0 : dmadev = rte_dma_pmd_allocate(dpaa_dev->device.name,
1416 : 0 : rte_socket_id(),
1417 : : sizeof(struct fsl_qdma_engine));
1418 [ # # ]: 0 : if (!dmadev) {
1419 : 0 : DPAA_QDMA_ERR("Unable to allocate dmadevice");
1420 : 0 : return -EINVAL;
1421 : : }
1422 : :
1423 : 0 : dpaa_dev->dmadev = dmadev;
1424 : 0 : dmadev->dev_ops = &dpaa_qdma_ops;
1425 : 0 : dmadev->device = &dpaa_dev->device;
1426 : 0 : dmadev->fp_obj->dev_private = dmadev->data->dev_private;
1427 : 0 : dmadev->fp_obj->copy = dpaa_qdma_enqueue;
1428 : 0 : dmadev->fp_obj->copy_sg = dpaa_qdma_copy_sg;
1429 : 0 : dmadev->fp_obj->submit = dpaa_qdma_submit;
1430 : 0 : dmadev->fp_obj->completed = dpaa_qdma_dequeue;
1431 : 0 : dmadev->fp_obj->completed_status = dpaa_qdma_dequeue_status;
1432 : 0 : dmadev->fp_obj->burst_capacity = dpaa_qdma_burst_capacity;
1433 : :
1434 : : /* Invoke PMD device initialization function */
1435 : 0 : ret = dpaa_qdma_init(dmadev);
1436 [ # # ]: 0 : if (ret) {
1437 : 0 : (void)rte_dma_pmd_release(dpaa_dev->device.name);
1438 : 0 : return ret;
1439 : : }
1440 : :
1441 : 0 : dmadev->state = RTE_DMA_DEV_READY;
1442 : 0 : return 0;
1443 : : }
1444 : :
1445 : : static int
1446 : 0 : dpaa_qdma_remove(struct rte_dpaa_device *dpaa_dev)
1447 : : {
1448 : 0 : struct rte_dma_dev *dmadev = dpaa_dev->dmadev;
1449 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
1450 : : uint32_t i, j, regs_size;
1451 : :
1452 : 0 : regs_size = fsl_qdma->block_offset * fsl_qdma->num_blocks;
1453 : 0 : regs_size += (QDMA_CTRL_REGION_SIZE + QDMA_STATUS_REGION_SIZE);
1454 : :
1455 [ # # ]: 0 : for (i = 0; i < QDMA_BLOCKS; i++)
1456 : : fsl_qdma_free_stq_res(&fsl_qdma->stat_queues[i]);
1457 : :
1458 [ # # ]: 0 : for (i = 0; i < QDMA_BLOCKS; i++) {
1459 [ # # ]: 0 : for (j = 0; j < QDMA_QUEUES; j++)
1460 : 0 : fsl_qdma_free_cmdq_res(&fsl_qdma->cmd_queues[i][j]);
1461 : : }
1462 : :
1463 : 0 : munmap(fsl_qdma->ctrl_base, regs_size);
1464 : :
1465 : 0 : (void)rte_dma_pmd_release(dpaa_dev->device.name);
1466 : :
1467 : 0 : return 0;
1468 : : }
1469 : :
1470 : : static struct rte_dpaa_driver rte_dpaa_qdma_pmd;
1471 : :
1472 : : static struct rte_dpaa_driver rte_dpaa_qdma_pmd = {
1473 : : .drv_type = FSL_DPAA_QDMA,
1474 : : .probe = dpaa_qdma_probe,
1475 : : .remove = dpaa_qdma_remove,
1476 : : };
1477 : :
1478 : 252 : RTE_PMD_REGISTER_DPAA(dpaa_qdma, rte_dpaa_qdma_pmd);
1479 : : RTE_PMD_REGISTER_PARAM_STRING(dpaa_qdma, DPAA_DMA_ERROR_CHECK "=<int>");
1480 [ - + ]: 252 : RTE_LOG_REGISTER_DEFAULT(dpaa_qdma_logtype, INFO);
|