Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2021-2026 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 : if (num == 0 || num > FSL_QDMA_SG_MAX_ENTRY) {
831 : 0 : DPAA_QDMA_ERR("Invalid scatter-gather entry count: num=%u", num);
832 : 0 : return -EINVAL;
833 : : }
834 : :
835 : 0 : ft->desc_ssge[num - 1].final = 1;
836 : 0 : ft->desc_dsge[num - 1].final = 1;
837 : 0 : csgf_src->length = total_len;
838 : 0 : csgf_dest->length = total_len;
839 : : #ifdef RTE_DMA_DPAA_ERRATA_ERR050757
840 : : sdf = &ft->df.sdf;
841 : : sdf->srttype = FSL_QDMA_CMD_RWTTYPE;
842 : : #ifdef RTE_DMA_DPAA_ERRATA_ERR050265
843 : : sdf->prefetch = 1;
844 : : #endif
845 : : if (total_len > FSL_QDMA_CMD_SS_ERR050757_LEN) {
846 : : sdf->ssen = 1;
847 : : sdf->sss = FSL_QDMA_CMD_SS_ERR050757_LEN;
848 : : sdf->ssd = FSL_QDMA_CMD_SS_ERR050757_LEN;
849 : : } else {
850 : : sdf->ssen = 0;
851 : : sdf->sss = 0;
852 : : sdf->ssd = 0;
853 : : }
854 : : #endif
855 : 0 : ret = fsl_qdma_enqueue_desc_to_ring(fsl_queue, num);
856 [ # # ]: 0 : if (ret)
857 : 0 : return ret;
858 : :
859 : 0 : fsl_queue->ci = (fsl_queue->ci + 1) & (fsl_queue->n_cq - 1);
860 : :
861 : 0 : qdma_writel(fsl_queue->le_cqmr | FSL_QDMA_BCQMR_EI,
862 [ # # ]: 0 : block + FSL_QDMA_BCQMR(fsl_queue->queue_id));
863 : 0 : fsl_queue->stats.submitted++;
864 : :
865 : 0 : fsl_queue->pending_start =
866 : 0 : (start + num) & (fsl_queue->pending_max - 1);
867 : 0 : fsl_queue->pending_num -= num;
868 [ # # ]: 0 : if (fsl_queue->pending_num > 0)
869 : 0 : goto eq_sg;
870 : :
871 : : return 0;
872 : : }
873 : :
874 : : static int
875 : 0 : fsl_qdma_enqueue_desc(struct fsl_qdma_queue *fsl_queue)
876 : : {
877 : 0 : uint16_t start = fsl_queue->pending_start;
878 : : int ret;
879 : :
880 [ # # ]: 0 : if (fsl_queue->pending_num == 1) {
881 : 0 : ret = fsl_qdma_enqueue_desc_single(fsl_queue,
882 : : fsl_queue->pending_desc[start].dst,
883 : : fsl_queue->pending_desc[start].src,
884 : 0 : fsl_queue->pending_desc[start].len);
885 [ # # ]: 0 : if (!ret) {
886 : 0 : fsl_queue->pending_start =
887 : 0 : (start + 1) & (fsl_queue->pending_max - 1);
888 : 0 : fsl_queue->pending_num = 0;
889 : : }
890 : 0 : return ret;
891 : : }
892 : :
893 : 0 : return fsl_qdma_enqueue_desc_sg(fsl_queue);
894 : : }
895 : :
896 : : static int
897 : 0 : dpaa_qdma_info_get(const struct rte_dma_dev *dev,
898 : : struct rte_dma_info *dev_info, __rte_unused uint32_t info_sz)
899 : : {
900 : 0 : struct fsl_qdma_engine *fsl_qdma = dev->data->dev_private;
901 : :
902 : : dev_info->dev_capa = RTE_DMA_CAPA_MEM_TO_MEM |
903 : : RTE_DMA_CAPA_SILENT | RTE_DMA_CAPA_OPS_COPY |
904 : : RTE_DMA_CAPA_OPS_COPY_SG;
905 : 0 : dev_info->dev_capa |= DPAA_QDMA_FLAGS_INDEX;
906 : 0 : dev_info->max_vchans = fsl_qdma->n_queues;
907 : 0 : dev_info->max_desc = FSL_QDMA_MAX_DESC_NUM;
908 : 0 : dev_info->min_desc = QDMA_QUEUE_SIZE;
909 : 0 : dev_info->max_sges = FSL_QDMA_SG_MAX_ENTRY;
910 : :
911 : 0 : return 0;
912 : : }
913 : :
914 : : static int
915 : 0 : dpaa_get_channel(struct fsl_qdma_engine *fsl_qdma,
916 : : uint16_t vchan)
917 : : {
918 : : int ret, i, j, found = 0;
919 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
920 : :
921 [ # # ]: 0 : if (fsl_queue) {
922 : : found = 1;
923 : 0 : goto queue_found;
924 : : }
925 : :
926 [ # # ]: 0 : for (i = 0; i < QDMA_BLOCKS; i++) {
927 [ # # ]: 0 : for (j = 0; j < QDMA_QUEUES; j++) {
928 : 0 : fsl_queue = &fsl_qdma->cmd_queues[i][j];
929 : :
930 [ # # ]: 0 : if (fsl_queue->channel_id == vchan) {
931 : : found = 1;
932 : 0 : fsl_qdma->chan[vchan] = fsl_queue;
933 : 0 : goto queue_found;
934 : : }
935 : : }
936 : : }
937 : :
938 : 0 : queue_found:
939 : : if (!found)
940 : : return -ENXIO;
941 : :
942 [ # # ]: 0 : if (fsl_queue->used)
943 : : return 0;
944 : :
945 : 0 : ret = fsl_qdma_pre_comp_sd_desc(fsl_queue);
946 [ # # ]: 0 : if (ret)
947 : : return ret;
948 : :
949 : 0 : fsl_queue->used = 1;
950 : 0 : fsl_qdma->block_queues[fsl_queue->block_id]++;
951 : :
952 : 0 : return 0;
953 : : }
954 : :
955 : : static int
956 : 0 : dpaa_qdma_configure(struct rte_dma_dev *dmadev,
957 : : const struct rte_dma_conf *dev_conf,
958 : : __rte_unused uint32_t conf_sz)
959 : : {
960 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
961 : :
962 : 0 : fsl_qdma->is_silent = dev_conf->flags & RTE_DMA_CFG_FLAG_SILENT;
963 : 0 : return 0;
964 : : }
965 : :
966 : : static int
967 : 0 : dpaa_qdma_start(__rte_unused struct rte_dma_dev *dev)
968 : : {
969 : 0 : return 0;
970 : : }
971 : :
972 : : static int
973 : 0 : dpaa_qdma_close(struct rte_dma_dev *dmadev)
974 : : {
975 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
976 : : uint32_t i, j, regs_size;
977 : :
978 : 0 : regs_size = fsl_qdma->block_offset * fsl_qdma->num_blocks;
979 : 0 : regs_size += (QDMA_CTRL_REGION_SIZE + QDMA_STATUS_REGION_SIZE);
980 : :
981 [ # # ]: 0 : for (i = 0; i < QDMA_BLOCKS; i++)
982 : : fsl_qdma_free_stq_res(&fsl_qdma->stat_queues[i]);
983 : :
984 [ # # ]: 0 : for (i = 0; i < QDMA_BLOCKS; i++) {
985 [ # # ]: 0 : for (j = 0; j < QDMA_QUEUES; j++)
986 : 0 : fsl_qdma_free_cmdq_res(&fsl_qdma->cmd_queues[i][j]);
987 : : }
988 : :
989 : 0 : munmap(fsl_qdma->ctrl_base, regs_size);
990 : :
991 : 0 : return 0;
992 : : }
993 : :
994 : : static int
995 : 0 : dpaa_qdma_queue_setup(struct rte_dma_dev *dmadev,
996 : : uint16_t vchan,
997 : : __rte_unused const struct rte_dma_vchan_conf *conf,
998 : : __rte_unused uint32_t conf_sz)
999 : : {
1000 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
1001 : :
1002 : 0 : return dpaa_get_channel(fsl_qdma, vchan);
1003 : : }
1004 : :
1005 : : static int
1006 : 0 : dpaa_qdma_submit(void *dev_private, uint16_t vchan)
1007 : : {
1008 : : struct fsl_qdma_engine *fsl_qdma = dev_private;
1009 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1010 : :
1011 [ # # ]: 0 : if (!fsl_queue->pending_num)
1012 : : return 0;
1013 : :
1014 : 0 : return fsl_qdma_enqueue_desc(fsl_queue);
1015 : : }
1016 : :
1017 : : static int
1018 : 0 : dpaa_qdma_enqueue(void *dev_private, uint16_t vchan,
1019 : : rte_iova_t src, rte_iova_t dst,
1020 : : uint32_t length, uint64_t flags)
1021 : : {
1022 : : struct fsl_qdma_engine *fsl_qdma = dev_private;
1023 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1024 : 0 : uint16_t start = fsl_queue->pending_start;
1025 : 0 : uint8_t pending = fsl_queue->pending_num;
1026 : : uint16_t idx;
1027 : : int ret;
1028 : :
1029 [ # # ]: 0 : if (pending >= fsl_queue->pending_max) {
1030 : 0 : DPAA_QDMA_ERR("Too many pending jobs(%d) on queue%d",
1031 : : pending, vchan);
1032 : 0 : return -ENOSPC;
1033 : : }
1034 : 0 : idx = (start + pending) & (fsl_queue->pending_max - 1);
1035 : :
1036 : 0 : fsl_queue->pending_desc[idx].src = src;
1037 : 0 : fsl_queue->pending_desc[idx].dst = dst;
1038 : 0 : fsl_queue->pending_desc[idx].flag =
1039 : 0 : DPAA_QDMA_IDX_FROM_FLAG(flags);
1040 : 0 : fsl_queue->pending_desc[idx].len = length;
1041 : 0 : fsl_queue->pending_num++;
1042 : :
1043 [ # # ]: 0 : if (!(flags & RTE_DMA_OP_FLAG_SUBMIT))
1044 : 0 : return idx;
1045 : :
1046 : 0 : ret = fsl_qdma_enqueue_desc(fsl_queue);
1047 [ # # ]: 0 : if (!ret)
1048 : 0 : return fsl_queue->pending_start;
1049 : :
1050 : : return ret;
1051 : : }
1052 : :
1053 : : static int
1054 : 0 : dpaa_qdma_copy_sg(void *dev_private,
1055 : : uint16_t vchan,
1056 : : const struct rte_dma_sge *src,
1057 : : const struct rte_dma_sge *dst,
1058 : : uint16_t nb_src, uint16_t nb_dst,
1059 : : uint64_t flags)
1060 : : {
1061 : : int ret;
1062 : : uint16_t i, start, idx;
1063 : : struct fsl_qdma_engine *fsl_qdma = dev_private;
1064 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1065 : : const uint16_t *idx_addr = NULL;
1066 : :
1067 [ # # ]: 0 : if (unlikely(nb_src != nb_dst)) {
1068 : 0 : DPAA_QDMA_ERR("%s: nb_src(%d) != nb_dst(%d) on queue%d",
1069 : : __func__, nb_src, nb_dst, vchan);
1070 : 0 : return -EINVAL;
1071 : : }
1072 : :
1073 [ # # ]: 0 : if ((fsl_queue->pending_num + nb_src) > FSL_QDMA_SG_MAX_ENTRY) {
1074 : 0 : DPAA_QDMA_ERR("Too many pending jobs on queue%d",
1075 : : vchan);
1076 : 0 : return -ENOSPC;
1077 : : }
1078 : 0 : start = fsl_queue->pending_start + fsl_queue->pending_num;
1079 : 0 : start = start & (fsl_queue->pending_max - 1);
1080 : : idx = start;
1081 : :
1082 : 0 : idx_addr = DPAA_QDMA_IDXADDR_FROM_SG_FLAG(flags);
1083 : :
1084 [ # # ]: 0 : for (i = 0; i < nb_src; i++) {
1085 [ # # ]: 0 : if (unlikely(src[i].length != dst[i].length)) {
1086 : 0 : DPAA_QDMA_ERR("src.len(%d) != dst.len(%d)",
1087 : : src[i].length, dst[i].length);
1088 : 0 : return -EINVAL;
1089 : : }
1090 : 0 : idx = (start + i) & (fsl_queue->pending_max - 1);
1091 : 0 : fsl_queue->pending_desc[idx].src = src[i].addr;
1092 : 0 : fsl_queue->pending_desc[idx].dst = dst[i].addr;
1093 : 0 : fsl_queue->pending_desc[idx].len = dst[i].length;
1094 : 0 : fsl_queue->pending_desc[idx].flag = idx_addr[i];
1095 : : }
1096 : 0 : fsl_queue->pending_num += nb_src;
1097 : :
1098 [ # # ]: 0 : if (!(flags & RTE_DMA_OP_FLAG_SUBMIT))
1099 : 0 : return idx;
1100 : :
1101 : 0 : ret = fsl_qdma_enqueue_desc(fsl_queue);
1102 [ # # ]: 0 : if (!ret)
1103 : 0 : return fsl_queue->pending_start;
1104 : :
1105 : : return ret;
1106 : : }
1107 : :
1108 : : static int
1109 : 0 : dpaa_qdma_err_handle(struct fsl_qdma_err_reg *reg)
1110 : : {
1111 : : struct fsl_qdma_err_reg local;
1112 : : size_t i, offset = 0;
1113 : : char err_msg[512];
1114 : :
1115 : : local.dedr_be = rte_read32(®->dedr_be);
1116 [ # # ]: 0 : if (!local.dedr_be)
1117 : : return 0;
1118 : 0 : offset = sprintf(err_msg, "ERR detected:");
1119 [ # # ]: 0 : if (local.dedr.ere) {
1120 : 0 : offset += sprintf(&err_msg[offset],
1121 : : " ere(Enqueue rejection error)");
1122 : : }
1123 [ # # ]: 0 : if (local.dedr.dde) {
1124 : 0 : offset += sprintf(&err_msg[offset],
1125 : : " dde(Destination descriptor error)");
1126 : : }
1127 [ # # ]: 0 : if (local.dedr.sde) {
1128 : 0 : offset += sprintf(&err_msg[offset],
1129 : : " sde(Source descriptor error)");
1130 : : }
1131 [ # # ]: 0 : if (local.dedr.cde) {
1132 : 0 : offset += sprintf(&err_msg[offset],
1133 : : " cde(Command descriptor error)");
1134 : : }
1135 [ # # ]: 0 : if (local.dedr.wte) {
1136 : 0 : offset += sprintf(&err_msg[offset],
1137 : : " wte(Write transaction error)");
1138 : : }
1139 [ # # ]: 0 : if (local.dedr.rte) {
1140 : 0 : offset += sprintf(&err_msg[offset],
1141 : : " rte(Read transaction error)");
1142 : : }
1143 [ # # ]: 0 : if (local.dedr.me) {
1144 : 0 : offset += sprintf(&err_msg[offset],
1145 : : " me(Multiple errors of the same type)");
1146 : : }
1147 : 0 : DPAA_QDMA_ERR("%s", err_msg);
1148 [ # # ]: 0 : for (i = 0; i < FSL_QDMA_DECCD_ERR_NUM; i++) {
1149 : 0 : local.deccd_le[FSL_QDMA_DECCD_ERR_NUM - 1 - i] =
1150 : : QDMA_IN(®->deccd_le[i]);
1151 : : }
1152 : 0 : local.deccqidr_be = rte_read32(®->deccqidr_be);
1153 : : local.decbr = rte_read32(®->decbr);
1154 : :
1155 : 0 : offset = sprintf(err_msg, "ERR command:");
1156 : 0 : offset += sprintf(&err_msg[offset],
1157 : : " status: %02x, ser: %d, offset:%d, fmt: %02x",
1158 : 0 : local.err_cmd.status, local.err_cmd.ser,
1159 : 0 : local.err_cmd.offset, local.err_cmd.format);
1160 : 0 : offset += sprintf(&err_msg[offset],
1161 : : " address: 0x%"PRIx64", queue: %d, dd: %02x",
1162 : 0 : (uint64_t)local.err_cmd.addr_hi << 32 |
1163 : 0 : local.err_cmd.addr_lo,
1164 : 0 : local.err_cmd.queue, local.err_cmd.dd);
1165 : 0 : DPAA_QDMA_ERR("%s", err_msg);
1166 : 0 : DPAA_QDMA_ERR("ERR command block: %d, queue: %d",
1167 : : local.deccqidr.block, local.deccqidr.queue);
1168 : :
1169 : : rte_write32(local.dedr_be, ®->dedr_be);
1170 : :
1171 : 0 : return -EIO;
1172 : : }
1173 : :
1174 : : static uint16_t
1175 : 0 : dpaa_qdma_dequeue_status(void *dev_private, uint16_t vchan,
1176 : : const uint16_t nb_cpls, uint16_t *last_idx,
1177 : : enum rte_dma_status_code *st)
1178 : 0 : {
1179 : : struct fsl_qdma_engine *fsl_qdma = dev_private;
1180 : : int err;
1181 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1182 : 0 : void *status = fsl_qdma->status_base;
1183 : 0 : struct fsl_qdma_desc *desc_complete[nb_cpls];
1184 : : uint16_t i, dq_num;
1185 : :
1186 [ # # ]: 0 : if (unlikely(fsl_qdma->is_silent)) {
1187 : 0 : DPAA_QDMA_WARN("Can't dq in silent mode");
1188 : :
1189 : 0 : return 0;
1190 : : }
1191 : :
1192 : 0 : dq_num = dpaa_qdma_block_dequeue(fsl_qdma,
1193 : 0 : fsl_queue->block_id);
1194 : : DPAA_QDMA_DP_DEBUG("%s: block dq(%d)",
1195 : : __func__, dq_num);
1196 : :
1197 [ # # # # : 0 : dq_num = rte_ring_dequeue_burst(fsl_queue->complete_pool,
# ]
1198 : : (void **)desc_complete, nb_cpls, NULL);
1199 [ # # ]: 0 : for (i = 0; i < dq_num; i++)
1200 : 0 : last_idx[i] = desc_complete[i]->flag;
1201 : :
1202 [ # # ]: 0 : if (st) {
1203 [ # # ]: 0 : for (i = 0; i < dq_num; i++)
1204 : 0 : st[i] = RTE_DMA_STATUS_SUCCESSFUL;
1205 : : }
1206 : :
1207 [ # # ]: 0 : if (s_hw_err_check) {
1208 : 0 : err = dpaa_qdma_err_handle(status +
1209 : : FSL_QDMA_ERR_REG_STATUS_OFFSET);
1210 [ # # ]: 0 : if (err)
1211 : 0 : fsl_queue->stats.errors++;
1212 : : }
1213 : :
1214 : : return dq_num;
1215 : : }
1216 : :
1217 : : static uint16_t
1218 : 0 : dpaa_qdma_dequeue(void *dev_private,
1219 : : uint16_t vchan, const uint16_t nb_cpls,
1220 : : uint16_t *last_idx, bool *has_error)
1221 : 0 : {
1222 : : struct fsl_qdma_engine *fsl_qdma = dev_private;
1223 : : int err;
1224 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1225 : 0 : void *status = fsl_qdma->status_base;
1226 : 0 : struct fsl_qdma_desc *desc_complete[nb_cpls];
1227 : : uint16_t i, dq_num;
1228 : :
1229 [ # # ]: 0 : if (unlikely(fsl_qdma->is_silent)) {
1230 : 0 : DPAA_QDMA_WARN("Can't dq in silent mode");
1231 : :
1232 : 0 : return 0;
1233 : : }
1234 : :
1235 : 0 : *has_error = false;
1236 : 0 : dq_num = dpaa_qdma_block_dequeue(fsl_qdma,
1237 : 0 : fsl_queue->block_id);
1238 : : DPAA_QDMA_DP_DEBUG("%s: block dq(%d)",
1239 : : __func__, dq_num);
1240 : :
1241 [ # # # # : 0 : dq_num = rte_ring_dequeue_burst(fsl_queue->complete_pool,
# ]
1242 : : (void **)desc_complete, nb_cpls, NULL);
1243 [ # # ]: 0 : for (i = 0; i < dq_num; i++)
1244 : 0 : last_idx[i] = desc_complete[i]->flag;
1245 : :
1246 [ # # ]: 0 : if (s_hw_err_check) {
1247 : 0 : err = dpaa_qdma_err_handle(status +
1248 : : FSL_QDMA_ERR_REG_STATUS_OFFSET);
1249 [ # # ]: 0 : if (err) {
1250 : : if (has_error)
1251 : 0 : *has_error = true;
1252 : 0 : fsl_queue->stats.errors++;
1253 : : }
1254 : : }
1255 : :
1256 : : return dq_num;
1257 : : }
1258 : :
1259 : : static int
1260 : 0 : dpaa_qdma_stats_get(const struct rte_dma_dev *dmadev,
1261 : : uint16_t vchan, struct rte_dma_stats *rte_stats, uint32_t size)
1262 : : {
1263 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
1264 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1265 : : struct rte_dma_stats *stats = &fsl_queue->stats;
1266 : :
1267 [ # # ]: 0 : if (size < sizeof(rte_stats))
1268 : : return -EINVAL;
1269 [ # # ]: 0 : if (rte_stats == NULL)
1270 : : return -EINVAL;
1271 : :
1272 : 0 : *rte_stats = *stats;
1273 : :
1274 : 0 : return 0;
1275 : : }
1276 : :
1277 : : static int
1278 : 0 : dpaa_qdma_stats_reset(struct rte_dma_dev *dmadev, uint16_t vchan)
1279 : : {
1280 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
1281 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1282 : :
1283 : 0 : memset(&fsl_queue->stats, 0, sizeof(struct rte_dma_stats));
1284 : :
1285 : 0 : return 0;
1286 : : }
1287 : :
1288 : : static uint16_t
1289 : 0 : dpaa_qdma_burst_capacity(const void *dev_private, uint16_t vchan)
1290 : : {
1291 : : const struct fsl_qdma_engine *fsl_qdma = dev_private;
1292 : 0 : struct fsl_qdma_queue *fsl_queue = fsl_qdma->chan[vchan];
1293 : :
1294 : 0 : return fsl_queue->pending_max - fsl_queue->pending_num;
1295 : : }
1296 : :
1297 : : static struct rte_dma_dev_ops dpaa_qdma_ops = {
1298 : : .dev_info_get = dpaa_qdma_info_get,
1299 : : .dev_configure = dpaa_qdma_configure,
1300 : : .dev_start = dpaa_qdma_start,
1301 : : .dev_close = dpaa_qdma_close,
1302 : : .vchan_setup = dpaa_qdma_queue_setup,
1303 : : .stats_get = dpaa_qdma_stats_get,
1304 : : .stats_reset = dpaa_qdma_stats_reset,
1305 : : };
1306 : :
1307 : : static int
1308 : 0 : check_devargs_handler(__rte_unused const char *key, const char *value,
1309 : : __rte_unused void *opaque)
1310 : : {
1311 [ # # ]: 0 : if (strcmp(value, "1"))
1312 : 0 : return -1;
1313 : :
1314 : : return 0;
1315 : : }
1316 : :
1317 : : static int
1318 : 0 : dpaa_get_devargs(struct rte_devargs *devargs, const char *key)
1319 : : {
1320 : : struct rte_kvargs *kvlist;
1321 : :
1322 [ # # ]: 0 : if (!devargs)
1323 : : return 0;
1324 : :
1325 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
1326 [ # # ]: 0 : if (!kvlist)
1327 : : return 0;
1328 : :
1329 [ # # ]: 0 : if (!rte_kvargs_count(kvlist, key)) {
1330 : 0 : rte_kvargs_free(kvlist);
1331 : 0 : return 0;
1332 : : }
1333 : :
1334 [ # # ]: 0 : if (rte_kvargs_process(kvlist, key,
1335 : : check_devargs_handler, NULL) < 0) {
1336 : 0 : rte_kvargs_free(kvlist);
1337 : 0 : return 0;
1338 : : }
1339 : 0 : rte_kvargs_free(kvlist);
1340 : :
1341 : 0 : return 1;
1342 : : }
1343 : :
1344 : : static int
1345 : 0 : dpaa_qdma_init(struct rte_dma_dev *dmadev)
1346 : : {
1347 : 0 : struct fsl_qdma_engine *fsl_qdma = dmadev->data->dev_private;
1348 : : uint64_t phys_addr;
1349 : : int ccsr_qdma_fd;
1350 : : int regs_size;
1351 : : int ret;
1352 : : uint32_t i, j, k;
1353 : :
1354 [ # # ]: 0 : if (dpaa_get_devargs(dmadev->device->devargs, DPAA_DMA_ERROR_CHECK)) {
1355 : 0 : s_hw_err_check = true;
1356 : 0 : DPAA_QDMA_INFO("Enable DMA error checks");
1357 : : }
1358 : :
1359 : 0 : fsl_qdma->n_queues = QDMA_QUEUES * QDMA_BLOCKS;
1360 : 0 : fsl_qdma->num_blocks = QDMA_BLOCKS;
1361 : 0 : fsl_qdma->block_offset = QDMA_BLOCK_OFFSET;
1362 : :
1363 : : ccsr_qdma_fd = open("/dev/mem", O_RDWR);
1364 [ # # ]: 0 : if (unlikely(ccsr_qdma_fd < 0)) {
1365 : 0 : DPAA_QDMA_ERR("Can not open /dev/mem for qdma CCSR map");
1366 : 0 : return ccsr_qdma_fd;
1367 : : }
1368 : :
1369 : 0 : regs_size = fsl_qdma->block_offset * fsl_qdma->num_blocks;
1370 : 0 : regs_size += (QDMA_CTRL_REGION_SIZE + QDMA_STATUS_REGION_SIZE);
1371 : : phys_addr = QDMA_CCSR_BASE;
1372 : 0 : fsl_qdma->reg_base = mmap(NULL, regs_size,
1373 : : PROT_READ | PROT_WRITE, MAP_SHARED,
1374 : : ccsr_qdma_fd, phys_addr);
1375 : :
1376 : 0 : close(ccsr_qdma_fd);
1377 [ # # ]: 0 : if (fsl_qdma->reg_base == MAP_FAILED) {
1378 : 0 : DPAA_QDMA_ERR("Map qdma reg: Phys(0x%"PRIx64"), size(%d)",
1379 : : phys_addr, regs_size);
1380 : 0 : return -ENOMEM;
1381 : : }
1382 : :
1383 : 0 : fsl_qdma->ctrl_base =
1384 : : fsl_qdma->reg_base + QDMA_CTRL_REGION_OFFSET;
1385 : 0 : fsl_qdma->status_base =
1386 : 0 : fsl_qdma->reg_base + QDMA_STATUS_REGION_OFFSET;
1387 : 0 : fsl_qdma->block_base =
1388 : 0 : fsl_qdma->status_base + QDMA_STATUS_REGION_SIZE;
1389 : :
1390 [ # # ]: 0 : for (i = 0; i < QDMA_BLOCKS; i++) {
1391 : 0 : ret = fsl_qdma_prep_status_queue(fsl_qdma, i);
1392 [ # # ]: 0 : if (ret)
1393 : 0 : goto mem_free;
1394 : : }
1395 : :
1396 : : k = 0;
1397 [ # # ]: 0 : for (i = 0; i < QDMA_QUEUES; i++) {
1398 [ # # ]: 0 : for (j = 0; j < QDMA_BLOCKS; j++) {
1399 : 0 : ret = fsl_qdma_alloc_queue_resources(fsl_qdma, i, j);
1400 [ # # ]: 0 : if (ret)
1401 : 0 : goto mem_free;
1402 : 0 : fsl_qdma->cmd_queues[j][i].channel_id = k;
1403 : 0 : k++;
1404 : : }
1405 : : }
1406 : :
1407 : 0 : ret = fsl_qdma_reg_init(fsl_qdma);
1408 [ # # ]: 0 : if (ret) {
1409 : 0 : DPAA_QDMA_ERR("Can't Initialize the qDMA engine.");
1410 : 0 : goto mem_free;
1411 : : }
1412 : :
1413 : : return 0;
1414 : :
1415 : 0 : mem_free:
1416 [ # # ]: 0 : for (i = 0; i < fsl_qdma->num_blocks; i++)
1417 : : fsl_qdma_free_stq_res(&fsl_qdma->stat_queues[i]);
1418 : :
1419 [ # # ]: 0 : for (i = 0; i < fsl_qdma->num_blocks; i++) {
1420 [ # # ]: 0 : for (j = 0; j < QDMA_QUEUES; j++)
1421 : 0 : fsl_qdma_free_cmdq_res(&fsl_qdma->cmd_queues[i][j]);
1422 : : }
1423 : :
1424 : 0 : munmap(fsl_qdma->ctrl_base, regs_size);
1425 : :
1426 : 0 : return ret;
1427 : : }
1428 : :
1429 : : static int
1430 : 0 : dpaa_qdma_probe(__rte_unused struct rte_dpaa_driver *dpaa_drv,
1431 : : struct rte_dpaa_device *dpaa_dev)
1432 : : {
1433 : : struct rte_dma_dev *dmadev;
1434 : : int ret;
1435 : :
1436 : 0 : dmadev = rte_dma_pmd_allocate(dpaa_dev->device.name,
1437 : 0 : rte_socket_id(),
1438 : : sizeof(struct fsl_qdma_engine));
1439 [ # # ]: 0 : if (!dmadev) {
1440 : 0 : DPAA_QDMA_ERR("Unable to allocate dmadevice");
1441 : 0 : return -EINVAL;
1442 : : }
1443 : :
1444 : 0 : dmadev->dev_ops = &dpaa_qdma_ops;
1445 : 0 : dmadev->device = &dpaa_dev->device;
1446 : 0 : dmadev->fp_obj->dev_private = dmadev->data->dev_private;
1447 : 0 : dmadev->fp_obj->copy = dpaa_qdma_enqueue;
1448 : 0 : dmadev->fp_obj->copy_sg = dpaa_qdma_copy_sg;
1449 : 0 : dmadev->fp_obj->submit = dpaa_qdma_submit;
1450 : 0 : dmadev->fp_obj->completed = dpaa_qdma_dequeue;
1451 : 0 : dmadev->fp_obj->completed_status = dpaa_qdma_dequeue_status;
1452 : 0 : dmadev->fp_obj->burst_capacity = dpaa_qdma_burst_capacity;
1453 : :
1454 : : /* Invoke PMD device initialization function */
1455 : 0 : ret = dpaa_qdma_init(dmadev);
1456 [ # # ]: 0 : if (ret) {
1457 : 0 : (void)rte_dma_pmd_release(dpaa_dev->device.name);
1458 : 0 : return ret;
1459 : : }
1460 : :
1461 : 0 : dmadev->state = RTE_DMA_DEV_READY;
1462 : 0 : return 0;
1463 : : }
1464 : :
1465 : : static int
1466 : 0 : dpaa_qdma_remove(struct rte_dpaa_device *dpaa_dev)
1467 : : {
1468 [ # # ]: 0 : if (rte_dma_pmd_release(dpaa_dev->device.name))
1469 : 0 : DPAA_QDMA_ERR("Device cleanup failed");
1470 : :
1471 : 0 : return 0;
1472 : : }
1473 : :
1474 : : static struct rte_dpaa_driver rte_dpaa_qdma_pmd;
1475 : :
1476 : : static struct rte_dpaa_driver rte_dpaa_qdma_pmd = {
1477 : : .drv_type = FSL_DPAA_QDMA,
1478 : : .probe = dpaa_qdma_probe,
1479 : : .remove = dpaa_qdma_remove,
1480 : : };
1481 : :
1482 : 303 : RTE_PMD_REGISTER_DPAA(dpaa_qdma, rte_dpaa_qdma_pmd);
1483 : : RTE_PMD_REGISTER_PARAM_STRING(dpaa_qdma, DPAA_DMA_ERROR_CHECK "=<int>");
1484 [ - + ]: 303 : RTE_LOG_REGISTER_DEFAULT(dpaa_qdma_logtype, INFO);
|