Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : *
3 : : * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
4 : : * Copyright 2018-2020 NXP
5 : : *
6 : : */
7 : :
8 : : #include "qbman_sys.h"
9 : : #include "qbman_portal.h"
10 : :
11 : : /* QBMan portal management command codes */
12 : : #define QBMAN_MC_ACQUIRE 0x30
13 : : #define QBMAN_WQCHAN_CONFIGURE 0x46
14 : :
15 : : /* Reverse mapping of QBMAN_CENA_SWP_DQRR() */
16 : : #define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0x1ff) >> 6)
17 : :
18 : : /* QBMan FQ management command codes */
19 : : #define QBMAN_FQ_SCHEDULE 0x48
20 : : #define QBMAN_FQ_FORCE 0x49
21 : : #define QBMAN_FQ_XON 0x4d
22 : : #define QBMAN_FQ_XOFF 0x4e
23 : :
24 : : /*******************************/
25 : : /* Pre-defined attribute codes */
26 : : /*******************************/
27 : :
28 : : #define QBMAN_RESPONSE_VERB_MASK 0x7f
29 : :
30 : : /*************************/
31 : : /* SDQCR attribute codes */
32 : : /*************************/
33 : : #define QB_SDQCR_FC_SHIFT 29
34 : : #define QB_SDQCR_FC_MASK 0x1
35 : : #define QB_SDQCR_DCT_SHIFT 24
36 : : #define QB_SDQCR_DCT_MASK 0x3
37 : : #define QB_SDQCR_TOK_SHIFT 16
38 : : #define QB_SDQCR_TOK_MASK 0xff
39 : : #define QB_SDQCR_SRC_SHIFT 0
40 : : #define QB_SDQCR_SRC_MASK 0xffff
41 : :
42 : : /* opaque token for static dequeues */
43 : : #define QMAN_SDQCR_TOKEN 0xbb
44 : :
45 : : enum qbman_sdqcr_dct {
46 : : qbman_sdqcr_dct_null = 0,
47 : : qbman_sdqcr_dct_prio_ics,
48 : : qbman_sdqcr_dct_active_ics,
49 : : qbman_sdqcr_dct_active
50 : : };
51 : :
52 : : enum qbman_sdqcr_fc {
53 : : qbman_sdqcr_fc_one = 0,
54 : : qbman_sdqcr_fc_up_to_3 = 1
55 : : };
56 : :
57 : : /* We need to keep track of which SWP triggered a pull command
58 : : * so keep an array of portal IDs and use the token field to
59 : : * be able to find the proper portal
60 : : */
61 : : #define MAX_QBMAN_PORTALS 64
62 : : static struct qbman_swp *portal_idx_map[MAX_QBMAN_PORTALS];
63 : :
64 : : uint32_t qman_version;
65 : :
66 : : /* Internal Function declaration */
67 : : static int
68 : : qbman_swp_enqueue_array_mode_direct(struct qbman_swp *s,
69 : : const struct qbman_eq_desc *d,
70 : : const struct qbman_fd *fd);
71 : : static int
72 : : qbman_swp_enqueue_array_mode_mem_back(struct qbman_swp *s,
73 : : const struct qbman_eq_desc *d,
74 : : const struct qbman_fd *fd);
75 : :
76 : : static int
77 : : qbman_swp_enqueue_ring_mode_direct(struct qbman_swp *s,
78 : : const struct qbman_eq_desc *d,
79 : : const struct qbman_fd *fd);
80 : : static int
81 : : qbman_swp_enqueue_ring_mode_cinh_read_direct(struct qbman_swp *s,
82 : : const struct qbman_eq_desc *d,
83 : : const struct qbman_fd *fd);
84 : : static int
85 : : qbman_swp_enqueue_ring_mode_cinh_direct(struct qbman_swp *s,
86 : : const struct qbman_eq_desc *d,
87 : : const struct qbman_fd *fd);
88 : : static int
89 : : qbman_swp_enqueue_ring_mode_mem_back(struct qbman_swp *s,
90 : : const struct qbman_eq_desc *d,
91 : : const struct qbman_fd *fd);
92 : :
93 : : static int
94 : : qbman_swp_enqueue_multiple_direct(struct qbman_swp *s,
95 : : const struct qbman_eq_desc *d,
96 : : const struct qbman_fd *fd,
97 : : uint32_t *flags,
98 : : int num_frames);
99 : : static int
100 : : qbman_swp_enqueue_multiple_cinh_read_direct(struct qbman_swp *s,
101 : : const struct qbman_eq_desc *d,
102 : : const struct qbman_fd *fd,
103 : : uint32_t *flags,
104 : : int num_frames);
105 : : static int
106 : : qbman_swp_enqueue_multiple_cinh_direct(struct qbman_swp *s,
107 : : const struct qbman_eq_desc *d,
108 : : const struct qbman_fd *fd,
109 : : uint32_t *flags,
110 : : int num_frames);
111 : : static int
112 : : qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
113 : : const struct qbman_eq_desc *d,
114 : : const struct qbman_fd *fd,
115 : : uint32_t *flags,
116 : : int num_frames);
117 : :
118 : : static int
119 : : qbman_swp_enqueue_multiple_fd_direct(struct qbman_swp *s,
120 : : const struct qbman_eq_desc *d,
121 : : struct qbman_fd **fd,
122 : : uint32_t *flags,
123 : : int num_frames);
124 : : static int
125 : : qbman_swp_enqueue_multiple_fd_cinh_read_direct(struct qbman_swp *s,
126 : : const struct qbman_eq_desc *d,
127 : : struct qbman_fd **fd,
128 : : uint32_t *flags,
129 : : int num_frames);
130 : : static int
131 : : qbman_swp_enqueue_multiple_fd_cinh_direct(struct qbman_swp *s,
132 : : const struct qbman_eq_desc *d,
133 : : struct qbman_fd **fd,
134 : : uint32_t *flags,
135 : : int num_frames);
136 : : static int
137 : : qbman_swp_enqueue_multiple_fd_mem_back(struct qbman_swp *s,
138 : : const struct qbman_eq_desc *d,
139 : : struct qbman_fd **fd,
140 : : uint32_t *flags,
141 : : int num_frames);
142 : :
143 : : static int
144 : : qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
145 : : const struct qbman_eq_desc *d,
146 : : const struct qbman_fd *fd,
147 : : int num_frames);
148 : : static int
149 : : qbman_swp_enqueue_multiple_desc_cinh_read_direct(struct qbman_swp *s,
150 : : const struct qbman_eq_desc *d,
151 : : const struct qbman_fd *fd,
152 : : int num_frames);
153 : : static int
154 : : qbman_swp_enqueue_multiple_desc_cinh_direct(struct qbman_swp *s,
155 : : const struct qbman_eq_desc *d,
156 : : const struct qbman_fd *fd,
157 : : int num_frames);
158 : : static int
159 : : qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s,
160 : : const struct qbman_eq_desc *d,
161 : : const struct qbman_fd *fd,
162 : : int num_frames);
163 : :
164 : : static int
165 : : qbman_swp_pull_direct(struct qbman_swp *s, struct qbman_pull_desc *d);
166 : : static int
167 : : qbman_swp_pull_cinh_direct(struct qbman_swp *s, struct qbman_pull_desc *d);
168 : : static int
169 : : qbman_swp_pull_mem_back(struct qbman_swp *s, struct qbman_pull_desc *d);
170 : :
171 : : const struct qbman_result *qbman_swp_dqrr_next_direct(struct qbman_swp *s);
172 : : const struct qbman_result *qbman_swp_dqrr_next_cinh_direct(struct qbman_swp *s);
173 : : const struct qbman_result *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s);
174 : :
175 : : static int
176 : : qbman_swp_release_direct(struct qbman_swp *s,
177 : : const struct qbman_release_desc *d,
178 : : const uint64_t *buffers, unsigned int num_buffers);
179 : : static int
180 : : qbman_swp_release_cinh_direct(struct qbman_swp *s,
181 : : const struct qbman_release_desc *d,
182 : : const uint64_t *buffers, unsigned int num_buffers);
183 : : static int
184 : : qbman_swp_release_mem_back(struct qbman_swp *s,
185 : : const struct qbman_release_desc *d,
186 : : const uint64_t *buffers, unsigned int num_buffers);
187 : :
188 : : /* Function pointers */
189 : : static int (*qbman_swp_enqueue_array_mode_ptr)(struct qbman_swp *s,
190 : : const struct qbman_eq_desc *d,
191 : : const struct qbman_fd *fd)
192 : : = qbman_swp_enqueue_array_mode_direct;
193 : :
194 : : static int (*qbman_swp_enqueue_ring_mode_ptr)(struct qbman_swp *s,
195 : : const struct qbman_eq_desc *d,
196 : : const struct qbman_fd *fd)
197 : : = qbman_swp_enqueue_ring_mode_direct;
198 : :
199 : : static int (*qbman_swp_enqueue_multiple_ptr)(struct qbman_swp *s,
200 : : const struct qbman_eq_desc *d,
201 : : const struct qbman_fd *fd,
202 : : uint32_t *flags,
203 : : int num_frames)
204 : : = qbman_swp_enqueue_multiple_direct;
205 : :
206 : : static int (*qbman_swp_enqueue_multiple_fd_ptr)(struct qbman_swp *s,
207 : : const struct qbman_eq_desc *d,
208 : : struct qbman_fd **fd,
209 : : uint32_t *flags,
210 : : int num_frames)
211 : : = qbman_swp_enqueue_multiple_fd_direct;
212 : :
213 : : static int (*qbman_swp_enqueue_multiple_desc_ptr)(struct qbman_swp *s,
214 : : const struct qbman_eq_desc *d,
215 : : const struct qbman_fd *fd,
216 : : int num_frames)
217 : : = qbman_swp_enqueue_multiple_desc_direct;
218 : :
219 : : static int (*qbman_swp_pull_ptr)(struct qbman_swp *s,
220 : : struct qbman_pull_desc *d)
221 : : = qbman_swp_pull_direct;
222 : :
223 : : const struct qbman_result *(*qbman_swp_dqrr_next_ptr)(struct qbman_swp *s)
224 : : = qbman_swp_dqrr_next_direct;
225 : :
226 : : static int (*qbman_swp_release_ptr)(struct qbman_swp *s,
227 : : const struct qbman_release_desc *d,
228 : : const uint64_t *buffers, unsigned int num_buffers)
229 : : = qbman_swp_release_direct;
230 : :
231 : : /*********************************/
232 : : /* Portal constructor/destructor */
233 : : /*********************************/
234 : :
235 : : /* Software portals should always be in the power-on state when we initialise,
236 : : * due to the CCSR-based portal reset functionality that MC has.
237 : : *
238 : : * Erk! Turns out that QMan versions prior to 4.1 do not correctly reset DQRR
239 : : * valid-bits, so we need to support a workaround where we don't trust
240 : : * valid-bits when detecting new entries until any stale ring entries have been
241 : : * overwritten at least once. The idea is that we read PI for the first few
242 : : * entries, then switch to valid-bit after that. The trick is to clear the
243 : : * bug-work-around boolean once the PI wraps around the ring for the first time.
244 : : *
245 : : * Note: this still carries a slight additional cost once the decrementer hits
246 : : * zero.
247 : : */
248 : 0 : struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
249 : : {
250 : : int ret;
251 : : uint32_t eqcr_pi;
252 : : uint32_t mask_size;
253 : 0 : struct qbman_swp *p = malloc(sizeof(*p));
254 : :
255 [ # # ]: 0 : if (!p)
256 : : return NULL;
257 : :
258 : : memset(p, 0, sizeof(struct qbman_swp));
259 : :
260 : 0 : p->desc = *d;
261 : : #ifdef QBMAN_CHECKING
262 : : p->mc.check = swp_mc_can_start;
263 : : #endif
264 : 0 : p->mc.valid_bit = QB_VALID_BIT;
265 : : p->sdq |= qbman_sdqcr_dct_prio_ics << QB_SDQCR_DCT_SHIFT;
266 : : p->sdq |= qbman_sdqcr_fc_up_to_3 << QB_SDQCR_FC_SHIFT;
267 : 0 : p->sdq |= QMAN_SDQCR_TOKEN << QB_SDQCR_TOK_SHIFT;
268 [ # # ]: 0 : if ((d->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000
269 [ # # ]: 0 : && (d->cena_access_mode == qman_cena_fastest_access))
270 : 0 : p->mr.valid_bit = QB_VALID_BIT;
271 : :
272 : : atomic_set(&p->vdq.busy, 1);
273 : 0 : p->vdq.valid_bit = QB_VALID_BIT;
274 : 0 : p->dqrr.valid_bit = QB_VALID_BIT;
275 : 0 : qman_version = p->desc.qman_version;
276 [ # # ]: 0 : if ((qman_version & QMAN_REV_MASK) < QMAN_REV_4100) {
277 : 0 : p->dqrr.dqrr_size = 4;
278 : 0 : p->dqrr.reset_bug = 1;
279 : : } else {
280 : 0 : p->dqrr.dqrr_size = 8;
281 : : p->dqrr.reset_bug = 0;
282 : : }
283 : :
284 : 0 : ret = qbman_swp_sys_init(&p->sys, d, p->dqrr.dqrr_size);
285 [ # # ]: 0 : if (ret) {
286 : 0 : free(p);
287 : 0 : pr_err("qbman_swp_sys_init() failed %d\n", ret);
288 : 0 : return NULL;
289 : : }
290 : :
291 : : /* Verify that the DQRRPI is 0 - if it is not the portal isn't
292 : : * in default state which is an error
293 : : */
294 [ # # ]: 0 : if (qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_DQPI) & 0xF) {
295 : 0 : pr_err("qbman DQRR PI is not zero, portal is not clean\n");
296 : 0 : free(p);
297 : 0 : return NULL;
298 : : }
299 : :
300 : : /* SDQCR needs to be initialized to 0 when no channels are
301 : : * being dequeued from or else the QMan HW will indicate an
302 : : * error. The values that were calculated above will be
303 : : * applied when dequeues from a specific channel are enabled.
304 : : */
305 : : qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_SDQCR, 0);
306 : :
307 : 0 : p->eqcr.pi_ring_size = 8;
308 [ # # ]: 0 : if ((qman_version & QMAN_REV_MASK) >= QMAN_REV_5000
309 [ # # ]: 0 : && (d->cena_access_mode == qman_cena_fastest_access)) {
310 : 0 : p->eqcr.pi_ring_size = 32;
311 : 0 : qbman_swp_enqueue_array_mode_ptr =
312 : : qbman_swp_enqueue_array_mode_mem_back;
313 : 0 : qbman_swp_enqueue_ring_mode_ptr =
314 : : qbman_swp_enqueue_ring_mode_mem_back;
315 : 0 : qbman_swp_enqueue_multiple_ptr =
316 : : qbman_swp_enqueue_multiple_mem_back;
317 : 0 : qbman_swp_enqueue_multiple_fd_ptr =
318 : : qbman_swp_enqueue_multiple_fd_mem_back;
319 : 0 : qbman_swp_enqueue_multiple_desc_ptr =
320 : : qbman_swp_enqueue_multiple_desc_mem_back;
321 : 0 : qbman_swp_pull_ptr = qbman_swp_pull_mem_back;
322 : 0 : qbman_swp_dqrr_next_ptr = qbman_swp_dqrr_next_mem_back;
323 : 0 : qbman_swp_release_ptr = qbman_swp_release_mem_back;
324 : : }
325 : :
326 [ # # ]: 0 : if (dpaa2_svr_family == SVR_LS1080A) {
327 : 0 : qbman_swp_enqueue_ring_mode_ptr =
328 : : qbman_swp_enqueue_ring_mode_cinh_read_direct;
329 : 0 : qbman_swp_enqueue_multiple_ptr =
330 : : qbman_swp_enqueue_multiple_cinh_read_direct;
331 : 0 : qbman_swp_enqueue_multiple_fd_ptr =
332 : : qbman_swp_enqueue_multiple_fd_cinh_read_direct;
333 : 0 : qbman_swp_enqueue_multiple_desc_ptr =
334 : : qbman_swp_enqueue_multiple_desc_cinh_read_direct;
335 : : }
336 : :
337 [ # # ]: 0 : for (mask_size = p->eqcr.pi_ring_size; mask_size > 0; mask_size >>= 1)
338 : 0 : p->eqcr.pi_ci_mask = (p->eqcr.pi_ci_mask<<1) + 1;
339 : : eqcr_pi = qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_EQCR_PI);
340 : 0 : p->eqcr.pi = eqcr_pi & p->eqcr.pi_ci_mask;
341 : 0 : p->eqcr.pi_vb = eqcr_pi & QB_VALID_BIT;
342 : 0 : p->eqcr.ci = qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_EQCR_CI)
343 : 0 : & p->eqcr.pi_ci_mask;
344 : 0 : p->eqcr.available = p->eqcr.pi_ring_size;
345 : :
346 : 0 : portal_idx_map[p->desc.idx] = p;
347 : 0 : return p;
348 : : }
349 : :
350 : 0 : int qbman_swp_update(struct qbman_swp *p, int stash_off)
351 : : {
352 : 0 : const struct qbman_swp_desc *d = &p->desc;
353 : 0 : struct qbman_swp_sys *s = &p->sys;
354 : : int ret;
355 : :
356 : : /* Nothing needs to be done for QBMAN rev > 5000 with fast access */
357 [ # # ]: 0 : if ((qman_version & QMAN_REV_MASK) >= QMAN_REV_5000
358 [ # # ]: 0 : && (d->cena_access_mode == qman_cena_fastest_access))
359 : : return 0;
360 : :
361 : 0 : ret = qbman_swp_sys_update(s, d, p->dqrr.dqrr_size, stash_off);
362 [ # # ]: 0 : if (ret) {
363 : 0 : pr_err("qbman_swp_sys_init() failed %d\n", ret);
364 : 0 : return ret;
365 : : }
366 : :
367 : 0 : p->stash_off = stash_off;
368 : :
369 : 0 : return 0;
370 : : }
371 : :
372 : 0 : void qbman_swp_finish(struct qbman_swp *p)
373 : : {
374 : : #ifdef QBMAN_CHECKING
375 : : QBMAN_BUG_ON(p->mc.check != swp_mc_can_start);
376 : : #endif
377 : : qbman_swp_sys_finish(&p->sys);
378 : 0 : portal_idx_map[p->desc.idx] = NULL;
379 : 0 : free(p);
380 : 0 : }
381 : :
382 : 0 : const struct qbman_swp_desc *qbman_swp_get_desc(struct qbman_swp *p)
383 : : {
384 : 0 : return &p->desc;
385 : : }
386 : :
387 : : /**************/
388 : : /* Interrupts */
389 : : /**************/
390 : :
391 : 0 : uint32_t qbman_swp_interrupt_get_vanish(struct qbman_swp *p)
392 : : {
393 : 0 : return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_ISDR);
394 : : }
395 : :
396 : 0 : void qbman_swp_interrupt_set_vanish(struct qbman_swp *p, uint32_t mask)
397 : : {
398 : : qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_ISDR, mask);
399 : 0 : }
400 : :
401 : 0 : uint32_t qbman_swp_interrupt_read_status(struct qbman_swp *p)
402 : : {
403 : 0 : return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_ISR);
404 : : }
405 : :
406 : 0 : void qbman_swp_interrupt_clear_status(struct qbman_swp *p, uint32_t mask)
407 : : {
408 : : qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_ISR, mask);
409 : 0 : }
410 : :
411 : 0 : uint32_t qbman_swp_dqrr_thrshld_read_status(struct qbman_swp *p)
412 : : {
413 : 0 : return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_DQRR_ITR);
414 : : }
415 : :
416 : 0 : void qbman_swp_dqrr_thrshld_write(struct qbman_swp *p, uint32_t mask)
417 : : {
418 : : qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_DQRR_ITR, mask);
419 : 0 : }
420 : :
421 : 0 : uint32_t qbman_swp_intr_timeout_read_status(struct qbman_swp *p)
422 : : {
423 : 0 : return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_ITPR);
424 : : }
425 : :
426 : 0 : void qbman_swp_intr_timeout_write(struct qbman_swp *p, uint32_t mask)
427 : : {
428 : : qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_ITPR, mask);
429 : 0 : }
430 : :
431 : 0 : uint32_t qbman_swp_interrupt_get_trigger(struct qbman_swp *p)
432 : : {
433 : 0 : return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_IER);
434 : : }
435 : :
436 : 0 : void qbman_swp_interrupt_set_trigger(struct qbman_swp *p, uint32_t mask)
437 : : {
438 : : qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_IER, mask);
439 : 0 : }
440 : :
441 : 0 : int qbman_swp_interrupt_get_inhibit(struct qbman_swp *p)
442 : : {
443 : 0 : return qbman_cinh_read(&p->sys, QBMAN_CINH_SWP_IIR);
444 : : }
445 : :
446 : 0 : void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit)
447 : : {
448 [ # # ]: 0 : qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_IIR,
449 : : inhibit ? 0xffffffff : 0);
450 : 0 : }
451 : :
452 : : /***********************/
453 : : /* Management commands */
454 : : /***********************/
455 : :
456 : : /*
457 : : * Internal code common to all types of management commands.
458 : : */
459 : :
460 : 0 : void *qbman_swp_mc_start(struct qbman_swp *p)
461 : : {
462 : : void *ret;
463 : : #ifdef QBMAN_CHECKING
464 : : QBMAN_BUG_ON(p->mc.check != swp_mc_can_start);
465 : : #endif
466 [ # # ]: 0 : if ((p->desc.qman_version & QMAN_REV_MASK) >= QMAN_REV_5000
467 [ # # ]: 0 : && (p->desc.cena_access_mode == qman_cena_fastest_access))
468 : 0 : ret = qbman_cena_write_start(&p->sys, QBMAN_CENA_SWP_CR_MEM);
469 : : else
470 : : ret = qbman_cena_write_start(&p->sys, QBMAN_CENA_SWP_CR);
471 : : #ifdef QBMAN_CHECKING
472 : : if (!ret)
473 : : p->mc.check = swp_mc_can_submit;
474 : : #endif
475 : 0 : return ret;
476 : : }
477 : :
478 : 0 : void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint8_t cmd_verb)
479 : : {
480 : : uint8_t *v = cmd;
481 : : #ifdef QBMAN_CHECKING
482 : : QBMAN_BUG_ON(!(p->mc.check != swp_mc_can_submit));
483 : : #endif
484 : : /* TBD: "|=" is going to hurt performance. Need to move as many fields
485 : : * out of word zero, and for those that remain, the "OR" needs to occur
486 : : * at the caller side. This debug check helps to catch cases where the
487 : : * caller wants to OR but has forgotten to do so.
488 : : */
489 : : QBMAN_BUG_ON((*v & cmd_verb) != *v);
490 [ # # ]: 0 : if ((p->desc.qman_version & QMAN_REV_MASK) >= QMAN_REV_5000
491 [ # # ]: 0 : && (p->desc.cena_access_mode == qman_cena_fastest_access)) {
492 : 0 : *v = cmd_verb | p->mr.valid_bit;
493 : : qbman_cena_write_complete(&p->sys, QBMAN_CENA_SWP_CR_MEM, cmd);
494 : 0 : dma_wmb();
495 : : qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_CR_RT, QMAN_RT_MODE);
496 : : } else {
497 : 0 : dma_wmb();
498 : 0 : *v = cmd_verb | p->mc.valid_bit;
499 : : qbman_cena_write_complete(&p->sys, QBMAN_CENA_SWP_CR, cmd);
500 : : clean(cmd);
501 : : }
502 : : #ifdef QBMAN_CHECKING
503 : : p->mc.check = swp_mc_can_poll;
504 : : #endif
505 : 0 : }
506 : :
507 : 0 : void qbman_swp_mc_submit_cinh(struct qbman_swp *p, void *cmd, uint8_t cmd_verb)
508 : : {
509 : : uint8_t *v = cmd;
510 : : #ifdef QBMAN_CHECKING
511 : : QBMAN_BUG_ON(!(p->mc.check != swp_mc_can_submit));
512 : : #endif
513 : : /* TBD: "|=" is going to hurt performance. Need to move as many fields
514 : : * out of word zero, and for those that remain, the "OR" needs to occur
515 : : * at the caller side. This debug check helps to catch cases where the
516 : : * caller wants to OR but has forgotten to do so.
517 : : */
518 : : QBMAN_BUG_ON((*v & cmd_verb) != *v);
519 : 0 : dma_wmb();
520 : 0 : *v = cmd_verb | p->mc.valid_bit;
521 : : qbman_cinh_write_complete(&p->sys, QBMAN_CENA_SWP_CR, cmd);
522 : : clean(cmd);
523 : : #ifdef QBMAN_CHECKING
524 : : p->mc.check = swp_mc_can_poll;
525 : : #endif
526 : 0 : }
527 : :
528 : 0 : void *qbman_swp_mc_result(struct qbman_swp *p)
529 : : {
530 : : uint32_t *ret, verb;
531 : : #ifdef QBMAN_CHECKING
532 : : QBMAN_BUG_ON(p->mc.check != swp_mc_can_poll);
533 : : #endif
534 [ # # ]: 0 : if ((p->desc.qman_version & QMAN_REV_MASK) >= QMAN_REV_5000
535 [ # # ]: 0 : && (p->desc.cena_access_mode == qman_cena_fastest_access)) {
536 : : ret = qbman_cena_read(&p->sys, QBMAN_CENA_SWP_RR_MEM);
537 : : /* Command completed if the valid bit is toggled */
538 [ # # ]: 0 : if (p->mr.valid_bit != (ret[0] & QB_VALID_BIT))
539 : : return NULL;
540 : : /* Remove the valid-bit -
541 : : * command completed iff the rest is non-zero
542 : : */
543 : 0 : verb = ret[0] & ~QB_VALID_BIT;
544 [ # # ]: 0 : if (!verb)
545 : : return NULL;
546 : 0 : p->mr.valid_bit ^= QB_VALID_BIT;
547 : : } else {
548 : 0 : qbman_cena_invalidate_prefetch(&p->sys,
549 : 0 : QBMAN_CENA_SWP_RR(p->mc.valid_bit));
550 : : ret = qbman_cena_read(&p->sys,
551 : : QBMAN_CENA_SWP_RR(p->mc.valid_bit));
552 : : /* Remove the valid-bit -
553 : : * command completed iff the rest is non-zero
554 : : */
555 : 0 : verb = ret[0] & ~QB_VALID_BIT;
556 [ # # ]: 0 : if (!verb)
557 : : return NULL;
558 : 0 : p->mc.valid_bit ^= QB_VALID_BIT;
559 : : }
560 : : #ifdef QBMAN_CHECKING
561 : : p->mc.check = swp_mc_can_start;
562 : : #endif
563 : : return ret;
564 : : }
565 : :
566 : 0 : void *qbman_swp_mc_result_cinh(struct qbman_swp *p)
567 : : {
568 : : uint32_t *ret, verb;
569 : : #ifdef QBMAN_CHECKING
570 : : QBMAN_BUG_ON(p->mc.check != swp_mc_can_poll);
571 : : #endif
572 : 0 : ret = qbman_cinh_read_shadow(&p->sys,
573 : 0 : QBMAN_CENA_SWP_RR(p->mc.valid_bit));
574 : : /* Remove the valid-bit -
575 : : * command completed iff the rest is non-zero
576 : : */
577 : 0 : verb = ret[0] & ~QB_VALID_BIT;
578 [ # # ]: 0 : if (!verb)
579 : : return NULL;
580 : 0 : p->mc.valid_bit ^= QB_VALID_BIT;
581 : : #ifdef QBMAN_CHECKING
582 : : p->mc.check = swp_mc_can_start;
583 : : #endif
584 : 0 : return ret;
585 : : }
586 : :
587 : : /***********/
588 : : /* Enqueue */
589 : : /***********/
590 : :
591 : : #define QB_ENQUEUE_CMD_OPTIONS_SHIFT 0
592 : : enum qb_enqueue_commands {
593 : : enqueue_empty = 0,
594 : : enqueue_response_always = 1,
595 : : enqueue_rejects_to_fq = 2
596 : : };
597 : :
598 : : #define QB_ENQUEUE_CMD_EC_OPTION_MASK 0x3
599 : : #define QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT 2
600 : : #define QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT 3
601 : : #define QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT 4
602 : : #define QB_ENQUEUE_CMD_DCA_PK_SHIFT 6
603 : : #define QB_ENQUEUE_CMD_DCA_EN_SHIFT 7
604 : : #define QB_ENQUEUE_CMD_NLIS_SHIFT 14
605 : : #define QB_ENQUEUE_CMD_IS_NESN_SHIFT 15
606 : :
607 : 0 : void qbman_eq_desc_clear(struct qbman_eq_desc *d)
608 : : {
609 : : memset(d, 0, sizeof(*d));
610 : 0 : }
611 : :
612 : 0 : void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success)
613 : : {
614 : 0 : d->eq.verb &= ~(1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT);
615 [ # # ]: 0 : if (respond_success)
616 : 0 : d->eq.verb |= enqueue_response_always;
617 : : else
618 : 0 : d->eq.verb |= enqueue_rejects_to_fq;
619 : 0 : }
620 : :
621 : 0 : void qbman_eq_desc_set_orp(struct qbman_eq_desc *d, int respond_success,
622 : : uint16_t opr_id, uint16_t seqnum, int incomplete)
623 : : {
624 : 0 : d->eq.verb |= 1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT;
625 [ # # ]: 0 : if (respond_success)
626 : 0 : d->eq.verb |= enqueue_response_always;
627 : : else
628 : 0 : d->eq.verb |= enqueue_rejects_to_fq;
629 : :
630 : 0 : d->eq.orpid = opr_id;
631 : : d->eq.seqnum = seqnum;
632 [ # # ]: 0 : if (incomplete)
633 : 0 : d->eq.seqnum |= 1 << QB_ENQUEUE_CMD_NLIS_SHIFT;
634 : : else
635 : 0 : d->eq.seqnum &= ~(1 << QB_ENQUEUE_CMD_NLIS_SHIFT);
636 : 0 : }
637 : :
638 : 0 : void qbman_eq_desc_set_orp_hole(struct qbman_eq_desc *d, uint16_t opr_id,
639 : : uint16_t seqnum)
640 : : {
641 : 0 : d->eq.verb |= 1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT;
642 : 0 : d->eq.verb &= ~QB_ENQUEUE_CMD_EC_OPTION_MASK;
643 : 0 : d->eq.orpid = opr_id;
644 : : d->eq.seqnum = seqnum;
645 : 0 : d->eq.seqnum &= ~(1 << QB_ENQUEUE_CMD_NLIS_SHIFT);
646 : 0 : d->eq.seqnum &= ~(1 << QB_ENQUEUE_CMD_IS_NESN_SHIFT);
647 : 0 : }
648 : :
649 : 0 : void qbman_eq_desc_set_orp_nesn(struct qbman_eq_desc *d, uint16_t opr_id,
650 : : uint16_t seqnum)
651 : : {
652 : 0 : d->eq.verb |= 1 << QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT;
653 : 0 : d->eq.verb &= ~QB_ENQUEUE_CMD_EC_OPTION_MASK;
654 : 0 : d->eq.orpid = opr_id;
655 : : d->eq.seqnum = seqnum;
656 : 0 : d->eq.seqnum &= ~(1 << QB_ENQUEUE_CMD_NLIS_SHIFT);
657 : 0 : d->eq.seqnum |= 1 << QB_ENQUEUE_CMD_IS_NESN_SHIFT;
658 : 0 : }
659 : :
660 : 0 : void qbman_eq_desc_set_response(struct qbman_eq_desc *d,
661 : : dma_addr_t storage_phys,
662 : : int stash)
663 : : {
664 : 0 : d->eq.rsp_addr = storage_phys;
665 : 0 : d->eq.wae = stash;
666 : 0 : }
667 : :
668 : 0 : void qbman_eq_desc_set_token(struct qbman_eq_desc *d, uint8_t token)
669 : : {
670 : 0 : d->eq.rspid = token;
671 : 0 : }
672 : :
673 : 0 : void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, uint32_t fqid)
674 : : {
675 : 0 : d->eq.verb &= ~(1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT);
676 : 0 : d->eq.tgtid = fqid;
677 : 0 : }
678 : :
679 : 0 : void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, uint32_t qdid,
680 : : uint16_t qd_bin, uint8_t qd_prio)
681 : : {
682 : 0 : d->eq.verb |= 1 << QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT;
683 : 0 : d->eq.tgtid = qdid;
684 : 0 : d->eq.qdbin = qd_bin;
685 : 0 : d->eq.qpri = qd_prio;
686 : 0 : }
687 : :
688 : 0 : void qbman_eq_desc_set_eqdi(struct qbman_eq_desc *d, int enable)
689 : : {
690 [ # # ]: 0 : if (enable)
691 : 0 : d->eq.verb |= 1 << QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT;
692 : : else
693 : 0 : d->eq.verb &= ~(1 << QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT);
694 : 0 : }
695 : :
696 : 0 : void qbman_eq_desc_set_dca(struct qbman_eq_desc *d, int enable,
697 : : uint8_t dqrr_idx, int park)
698 : : {
699 [ # # ]: 0 : if (enable) {
700 : : d->eq.dca = dqrr_idx;
701 [ # # ]: 0 : if (park)
702 : 0 : d->eq.dca |= 1 << QB_ENQUEUE_CMD_DCA_PK_SHIFT;
703 : : else
704 : 0 : d->eq.dca &= ~(1 << QB_ENQUEUE_CMD_DCA_PK_SHIFT);
705 : 0 : d->eq.dca |= 1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT;
706 : : } else {
707 : 0 : d->eq.dca &= ~(1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT);
708 : : }
709 : 0 : }
710 : :
711 : : #define EQAR_IDX(eqar) ((eqar) & 0x1f)
712 : : #define EQAR_VB(eqar) ((eqar) & 0x80)
713 : : #define EQAR_SUCCESS(eqar) ((eqar) & 0x100)
714 : :
715 : : static inline void qbman_write_eqcr_am_rt_register(struct qbman_swp *p,
716 : : uint8_t idx)
717 : : {
718 : 0 : if (idx < 16)
719 : 0 : qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_EQCR_AM_RT + idx * 4,
720 : : QMAN_RT_MODE);
721 : : else
722 : 0 : qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_EQCR_AM_RT2 +
723 : : (idx - 16) * 4,
724 : : QMAN_RT_MODE);
725 : : }
726 : :
727 : : static void memcpy_byte_by_byte(void *to, const void *from, size_t n)
728 : : {
729 : : const uint8_t *src = from;
730 : : volatile uint8_t *dest = to;
731 : : size_t i;
732 : :
733 [ # # # # : 0 : for (i = 0; i < n; i++)
# # # # #
# # # # #
# # # # #
# ]
734 : 0 : dest[i] = src[i];
735 : : }
736 : :
737 : :
738 [ # # ]: 0 : static int qbman_swp_enqueue_array_mode_direct(struct qbman_swp *s,
739 : : const struct qbman_eq_desc *d,
740 : : const struct qbman_fd *fd)
741 : : {
742 : : uint32_t *p;
743 : : const uint32_t *cl = qb_cl(d);
744 : : uint32_t eqar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_EQAR);
745 : :
746 : : pr_debug("EQAR=%08x\n", eqar);
747 [ # # ]: 0 : if (!EQAR_SUCCESS(eqar))
748 : : return -EBUSY;
749 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
750 : 0 : QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)));
751 : 0 : memcpy(&p[1], &cl[1], 28);
752 : 0 : memcpy(&p[8], fd, sizeof(*fd));
753 : :
754 : : /* Set the verb byte, have to substitute in the valid-bit */
755 : 0 : dma_wmb();
756 : 0 : p[0] = cl[0] | EQAR_VB(eqar);
757 : : qbman_cena_write_complete_wo_shadow(&s->sys,
758 : : QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)));
759 : 0 : return 0;
760 : : }
761 [ # # ]: 0 : static int qbman_swp_enqueue_array_mode_mem_back(struct qbman_swp *s,
762 : : const struct qbman_eq_desc *d,
763 : : const struct qbman_fd *fd)
764 : : {
765 : : uint32_t *p;
766 : : const uint32_t *cl = qb_cl(d);
767 : : uint32_t eqar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_EQAR);
768 : :
769 : : pr_debug("EQAR=%08x\n", eqar);
770 [ # # ]: 0 : if (!EQAR_SUCCESS(eqar))
771 : : return -EBUSY;
772 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
773 : 0 : QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)));
774 : 0 : memcpy(&p[1], &cl[1], 28);
775 : 0 : memcpy(&p[8], fd, sizeof(*fd));
776 : :
777 : : /* Set the verb byte, have to substitute in the valid-bit */
778 : 0 : p[0] = cl[0] | EQAR_VB(eqar);
779 : 0 : dma_wmb();
780 [ # # ]: 0 : qbman_write_eqcr_am_rt_register(s, EQAR_IDX(eqar));
781 : : return 0;
782 : : }
783 : :
784 : : static inline int qbman_swp_enqueue_array_mode(struct qbman_swp *s,
785 : : const struct qbman_eq_desc *d,
786 : : const struct qbman_fd *fd)
787 : : {
788 : 0 : return qbman_swp_enqueue_array_mode_ptr(s, d, fd);
789 : : }
790 : :
791 : 0 : static int qbman_swp_enqueue_ring_mode_direct(struct qbman_swp *s,
792 : : const struct qbman_eq_desc *d,
793 : : const struct qbman_fd *fd)
794 : : {
795 : : uint32_t *p;
796 : : const uint32_t *cl = qb_cl(d);
797 : : uint32_t eqcr_ci, full_mask, half_mask;
798 : :
799 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
800 : : full_mask = s->eqcr.pi_ci_mask;
801 [ # # ]: 0 : if (!s->eqcr.available) {
802 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
803 : 0 : s->eqcr.ci = qbman_cena_read_reg(&s->sys,
804 : 0 : QBMAN_CENA_SWP_EQCR_CI) & full_mask;
805 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
806 : : eqcr_ci, s->eqcr.ci);
807 [ # # ]: 0 : if (!s->eqcr.available)
808 : : return -EBUSY;
809 : : }
810 : :
811 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
812 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(s->eqcr.pi & half_mask));
813 [ # # ]: 0 : memcpy(&p[1], &cl[1], 28);
814 : 0 : memcpy(&p[8], fd, sizeof(*fd));
815 : : lwsync();
816 : :
817 : : /* Set the verb byte, have to substitute in the valid-bit */
818 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
819 : : qbman_cena_write_complete_wo_shadow(&s->sys,
820 : 0 : QBMAN_CENA_SWP_EQCR(s->eqcr.pi & half_mask));
821 : 0 : s->eqcr.pi++;
822 : 0 : s->eqcr.pi &= full_mask;
823 : 0 : s->eqcr.available--;
824 [ # # ]: 0 : if (!(s->eqcr.pi & half_mask))
825 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
826 : :
827 : : return 0;
828 : : }
829 : :
830 : 0 : static int qbman_swp_enqueue_ring_mode_cinh_read_direct(
831 : : struct qbman_swp *s,
832 : : const struct qbman_eq_desc *d,
833 : : const struct qbman_fd *fd)
834 : : {
835 : : uint32_t *p;
836 : : const uint32_t *cl = qb_cl(d);
837 : : uint32_t eqcr_ci, full_mask, half_mask;
838 : :
839 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
840 : : full_mask = s->eqcr.pi_ci_mask;
841 [ # # ]: 0 : if (!s->eqcr.available) {
842 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
843 : 0 : s->eqcr.ci = qbman_cinh_read(&s->sys,
844 : 0 : QBMAN_CINH_SWP_EQCR_CI) & full_mask;
845 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
846 : : eqcr_ci, s->eqcr.ci);
847 [ # # ]: 0 : if (!s->eqcr.available)
848 : : return -EBUSY;
849 : : }
850 : :
851 : 0 : p = qbman_cinh_write_start_wo_shadow(&s->sys,
852 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(s->eqcr.pi & half_mask));
853 [ # # ]: 0 : memcpy(&p[1], &cl[1], 28);
854 : 0 : memcpy(&p[8], fd, sizeof(*fd));
855 : : lwsync();
856 : :
857 : : /* Set the verb byte, have to substitute in the valid-bit */
858 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
859 : 0 : s->eqcr.pi++;
860 : 0 : s->eqcr.pi &= full_mask;
861 : 0 : s->eqcr.available--;
862 [ # # ]: 0 : if (!(s->eqcr.pi & half_mask))
863 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
864 : :
865 : : return 0;
866 : : }
867 : :
868 : 0 : static int qbman_swp_enqueue_ring_mode_cinh_direct(
869 : : struct qbman_swp *s,
870 : : const struct qbman_eq_desc *d,
871 : : const struct qbman_fd *fd)
872 : : {
873 : : uint32_t *p;
874 : : const uint32_t *cl = qb_cl(d);
875 : : uint32_t eqcr_ci, full_mask, half_mask;
876 : :
877 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
878 : : full_mask = s->eqcr.pi_ci_mask;
879 [ # # ]: 0 : if (!s->eqcr.available) {
880 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
881 : 0 : s->eqcr.ci = qbman_cinh_read(&s->sys,
882 : 0 : QBMAN_CINH_SWP_EQCR_CI) & full_mask;
883 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
884 : : eqcr_ci, s->eqcr.ci);
885 [ # # ]: 0 : if (!s->eqcr.available)
886 : : return -EBUSY;
887 : : }
888 : :
889 : 0 : p = qbman_cinh_write_start_wo_shadow(&s->sys,
890 : 0 : QBMAN_CENA_SWP_EQCR(s->eqcr.pi & half_mask));
891 : 0 : memcpy_byte_by_byte(&p[1], &cl[1], 28);
892 : : memcpy_byte_by_byte(&p[8], fd, sizeof(*fd));
893 : : lwsync();
894 : :
895 : : /* Set the verb byte, have to substitute in the valid-bit */
896 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
897 : 0 : s->eqcr.pi++;
898 : 0 : s->eqcr.pi &= full_mask;
899 : 0 : s->eqcr.available--;
900 [ # # ]: 0 : if (!(s->eqcr.pi & half_mask))
901 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
902 : :
903 : : return 0;
904 : : }
905 : :
906 : 0 : static int qbman_swp_enqueue_ring_mode_mem_back(struct qbman_swp *s,
907 : : const struct qbman_eq_desc *d,
908 : : const struct qbman_fd *fd)
909 : : {
910 : : uint32_t *p;
911 : : const uint32_t *cl = qb_cl(d);
912 : : uint32_t eqcr_ci, full_mask, half_mask;
913 : :
914 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
915 : : full_mask = s->eqcr.pi_ci_mask;
916 [ # # ]: 0 : if (!s->eqcr.available) {
917 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
918 : 0 : s->eqcr.ci = qbman_cena_read_reg(&s->sys,
919 : 0 : QBMAN_CENA_SWP_EQCR_CI_MEMBACK) & full_mask;
920 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
921 : : eqcr_ci, s->eqcr.ci);
922 [ # # ]: 0 : if (!s->eqcr.available)
923 : : return -EBUSY;
924 : : }
925 : :
926 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
927 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(s->eqcr.pi & half_mask));
928 [ # # ]: 0 : memcpy(&p[1], &cl[1], 28);
929 : 0 : memcpy(&p[8], fd, sizeof(*fd));
930 : :
931 : : /* Set the verb byte, have to substitute in the valid-bit */
932 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
933 : 0 : s->eqcr.pi++;
934 : 0 : s->eqcr.pi &= full_mask;
935 : 0 : s->eqcr.available--;
936 [ # # ]: 0 : if (!(s->eqcr.pi & half_mask))
937 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
938 : 0 : dma_wmb();
939 : 0 : qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_EQCR_PI,
940 : 0 : (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb);
941 : 0 : return 0;
942 : : }
943 : :
944 : 0 : static int qbman_swp_enqueue_ring_mode(struct qbman_swp *s,
945 : : const struct qbman_eq_desc *d,
946 : : const struct qbman_fd *fd)
947 : : {
948 [ # # ]: 0 : if (!s->stash_off)
949 : 0 : return qbman_swp_enqueue_ring_mode_ptr(s, d, fd);
950 : : else
951 : 0 : return qbman_swp_enqueue_ring_mode_cinh_direct(s, d, fd);
952 : : }
953 : :
954 : 0 : int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
955 : : const struct qbman_fd *fd)
956 : : {
957 [ # # ]: 0 : if (s->sys.eqcr_mode == qman_eqcr_vb_array)
958 : 0 : return qbman_swp_enqueue_array_mode(s, d, fd);
959 : : else /* Use ring mode by default */
960 : 0 : return qbman_swp_enqueue_ring_mode(s, d, fd);
961 : : }
962 : :
963 : 0 : static int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s,
964 : : const struct qbman_eq_desc *d,
965 : : const struct qbman_fd *fd,
966 : : uint32_t *flags,
967 : : int num_frames)
968 : : {
969 : : uint32_t *p = NULL;
970 : : const uint32_t *cl = qb_cl(d);
971 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
972 : : int i, num_enqueued = 0;
973 : : uint64_t addr_cena;
974 : :
975 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
976 : : full_mask = s->eqcr.pi_ci_mask;
977 [ # # ]: 0 : if (!s->eqcr.available) {
978 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
979 : 0 : s->eqcr.ci = qbman_cena_read_reg(&s->sys,
980 : 0 : QBMAN_CENA_SWP_EQCR_CI) & full_mask;
981 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
982 : : eqcr_ci, s->eqcr.ci);
983 [ # # ]: 0 : if (!s->eqcr.available)
984 : : return 0;
985 : : }
986 : :
987 : 0 : eqcr_pi = s->eqcr.pi;
988 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
989 : : s->eqcr.available : num_frames;
990 : 0 : s->eqcr.available -= num_enqueued;
991 : : /* Fill in the EQCR ring */
992 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
993 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
994 : 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
995 : 0 : memcpy(&p[1], &cl[1], 28);
996 : 0 : memcpy(&p[8], &fd[i], sizeof(*fd));
997 : 0 : eqcr_pi++;
998 : : }
999 : :
1000 : : lwsync();
1001 : :
1002 : : /* Set the verb byte, have to substitute in the valid-bit */
1003 : 0 : eqcr_pi = s->eqcr.pi;
1004 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1005 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1006 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1007 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1008 [ # # # # ]: 0 : if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
1009 : : struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
1010 : :
1011 : 0 : d->eq.dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
1012 : 0 : ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
1013 : : }
1014 : 0 : eqcr_pi++;
1015 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1016 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1017 : : }
1018 : :
1019 : : /* Flush all the cacheline without load/store in between */
1020 : 0 : eqcr_pi = s->eqcr.pi;
1021 : : addr_cena = (size_t)s->sys.addr_cena;
1022 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1023 : : dcbf((uintptr_t)(addr_cena +
1024 : : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)));
1025 : 0 : eqcr_pi++;
1026 : : }
1027 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1028 : :
1029 : 0 : return num_enqueued;
1030 : : }
1031 : :
1032 : 0 : static int qbman_swp_enqueue_multiple_cinh_read_direct(
1033 : : struct qbman_swp *s,
1034 : : const struct qbman_eq_desc *d,
1035 : : const struct qbman_fd *fd,
1036 : : uint32_t *flags,
1037 : : int num_frames)
1038 : : {
1039 : : uint32_t *p = NULL;
1040 : : const uint32_t *cl = qb_cl(d);
1041 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
1042 : : int i, num_enqueued = 0;
1043 : : uint64_t addr_cena;
1044 : :
1045 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
1046 : : full_mask = s->eqcr.pi_ci_mask;
1047 [ # # ]: 0 : if (!s->eqcr.available) {
1048 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
1049 : 0 : s->eqcr.ci = qbman_cinh_read(&s->sys,
1050 : 0 : QBMAN_CINH_SWP_EQCR_CI) & full_mask;
1051 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
1052 : : eqcr_ci, s->eqcr.ci);
1053 [ # # ]: 0 : if (!s->eqcr.available)
1054 : : return 0;
1055 : : }
1056 : :
1057 : 0 : eqcr_pi = s->eqcr.pi;
1058 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
1059 : : s->eqcr.available : num_frames;
1060 : 0 : s->eqcr.available -= num_enqueued;
1061 : : /* Fill in the EQCR ring */
1062 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1063 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1064 : 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1065 : 0 : memcpy(&p[1], &cl[1], 28);
1066 : 0 : memcpy(&p[8], &fd[i], sizeof(*fd));
1067 : 0 : eqcr_pi++;
1068 : : }
1069 : :
1070 : : lwsync();
1071 : :
1072 : : /* Set the verb byte, have to substitute in the valid-bit */
1073 : 0 : eqcr_pi = s->eqcr.pi;
1074 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1075 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1076 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1077 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1078 [ # # # # ]: 0 : if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
1079 : : struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
1080 : :
1081 : 0 : d->eq.dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
1082 : 0 : ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
1083 : : }
1084 : 0 : eqcr_pi++;
1085 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1086 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1087 : : }
1088 : :
1089 : : /* Flush all the cacheline without load/store in between */
1090 : 0 : eqcr_pi = s->eqcr.pi;
1091 : : addr_cena = (size_t)s->sys.addr_cena;
1092 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1093 : : dcbf(addr_cena +
1094 : : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1095 : 0 : eqcr_pi++;
1096 : : }
1097 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1098 : :
1099 : 0 : return num_enqueued;
1100 : : }
1101 : :
1102 : 0 : static int qbman_swp_enqueue_multiple_cinh_direct(
1103 : : struct qbman_swp *s,
1104 : : const struct qbman_eq_desc *d,
1105 : : const struct qbman_fd *fd,
1106 : : uint32_t *flags,
1107 : : int num_frames)
1108 : : {
1109 : : uint32_t *p = NULL;
1110 : : const uint32_t *cl = qb_cl(d);
1111 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
1112 : : int i, num_enqueued = 0;
1113 : :
1114 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
1115 : : full_mask = s->eqcr.pi_ci_mask;
1116 [ # # ]: 0 : if (!s->eqcr.available) {
1117 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
1118 : 0 : s->eqcr.ci = qbman_cinh_read(&s->sys,
1119 : 0 : QBMAN_CINH_SWP_EQCR_CI) & full_mask;
1120 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
1121 : : eqcr_ci, s->eqcr.ci);
1122 [ # # ]: 0 : if (!s->eqcr.available)
1123 : : return 0;
1124 : : }
1125 : :
1126 : 0 : eqcr_pi = s->eqcr.pi;
1127 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
1128 : : s->eqcr.available : num_frames;
1129 : 0 : s->eqcr.available -= num_enqueued;
1130 : : /* Fill in the EQCR ring */
1131 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1132 : 0 : p = qbman_cinh_write_start_wo_shadow(&s->sys,
1133 : 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1134 : 0 : memcpy_byte_by_byte(&p[1], &cl[1], 28);
1135 : 0 : memcpy_byte_by_byte(&p[8], &fd[i], sizeof(*fd));
1136 : 0 : eqcr_pi++;
1137 : : }
1138 : :
1139 : : lwsync();
1140 : :
1141 : : /* Set the verb byte, have to substitute in the valid-bit */
1142 : 0 : eqcr_pi = s->eqcr.pi;
1143 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1144 : 0 : p = qbman_cinh_write_start_wo_shadow(&s->sys,
1145 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1146 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1147 [ # # # # ]: 0 : if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
1148 : : struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
1149 : :
1150 : 0 : d->eq.dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
1151 : 0 : ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
1152 : : }
1153 : 0 : eqcr_pi++;
1154 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1155 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1156 : : }
1157 : :
1158 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1159 : :
1160 : 0 : return num_enqueued;
1161 : : }
1162 : :
1163 : 0 : static int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
1164 : : const struct qbman_eq_desc *d,
1165 : : const struct qbman_fd *fd,
1166 : : uint32_t *flags,
1167 : : int num_frames)
1168 : : {
1169 : : uint32_t *p = NULL;
1170 : : const uint32_t *cl = qb_cl(d);
1171 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
1172 : : int i, num_enqueued = 0;
1173 : :
1174 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
1175 : : full_mask = s->eqcr.pi_ci_mask;
1176 [ # # ]: 0 : if (!s->eqcr.available) {
1177 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
1178 : 0 : s->eqcr.ci = qbman_cena_read_reg(&s->sys,
1179 : 0 : QBMAN_CENA_SWP_EQCR_CI_MEMBACK) & full_mask;
1180 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
1181 : : eqcr_ci, s->eqcr.ci);
1182 [ # # ]: 0 : if (!s->eqcr.available)
1183 : : return 0;
1184 : : }
1185 : :
1186 : 0 : eqcr_pi = s->eqcr.pi;
1187 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
1188 : : s->eqcr.available : num_frames;
1189 : 0 : s->eqcr.available -= num_enqueued;
1190 : : /* Fill in the EQCR ring */
1191 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1192 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1193 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1194 [ # # ]: 0 : memcpy(&p[1], &cl[1], 28);
1195 : 0 : memcpy(&p[8], &fd[i], sizeof(*fd));
1196 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1197 : :
1198 [ # # # # ]: 0 : if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
1199 : : struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
1200 : :
1201 : 0 : d->eq.dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
1202 : 0 : ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
1203 : : }
1204 : 0 : eqcr_pi++;
1205 : :
1206 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1207 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1208 : : }
1209 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1210 : :
1211 : 0 : dma_wmb();
1212 : 0 : qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_EQCR_PI,
1213 : 0 : (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb);
1214 : 0 : return num_enqueued;
1215 : : }
1216 : :
1217 : 0 : int qbman_swp_enqueue_multiple(struct qbman_swp *s,
1218 : : const struct qbman_eq_desc *d,
1219 : : const struct qbman_fd *fd,
1220 : : uint32_t *flags,
1221 : : int num_frames)
1222 : : {
1223 [ # # ]: 0 : if (!s->stash_off)
1224 : 0 : return qbman_swp_enqueue_multiple_ptr(s, d, fd, flags,
1225 : : num_frames);
1226 : : else
1227 : 0 : return qbman_swp_enqueue_multiple_cinh_direct(s, d, fd, flags,
1228 : : num_frames);
1229 : : }
1230 : :
1231 : 0 : static int qbman_swp_enqueue_multiple_fd_direct(struct qbman_swp *s,
1232 : : const struct qbman_eq_desc *d,
1233 : : struct qbman_fd **fd,
1234 : : uint32_t *flags,
1235 : : int num_frames)
1236 : : {
1237 : : uint32_t *p = NULL;
1238 : : const uint32_t *cl = qb_cl(d);
1239 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
1240 : : int i, num_enqueued = 0;
1241 : : uint64_t addr_cena;
1242 : :
1243 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
1244 : : full_mask = s->eqcr.pi_ci_mask;
1245 [ # # ]: 0 : if (!s->eqcr.available) {
1246 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
1247 : 0 : s->eqcr.ci = qbman_cena_read_reg(&s->sys,
1248 : 0 : QBMAN_CENA_SWP_EQCR_CI) & full_mask;
1249 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
1250 : : eqcr_ci, s->eqcr.ci);
1251 [ # # ]: 0 : if (!s->eqcr.available)
1252 : : return 0;
1253 : : }
1254 : :
1255 : 0 : eqcr_pi = s->eqcr.pi;
1256 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
1257 : : s->eqcr.available : num_frames;
1258 : 0 : s->eqcr.available -= num_enqueued;
1259 : : /* Fill in the EQCR ring */
1260 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1261 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1262 : 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1263 : 0 : memcpy(&p[1], &cl[1], 28);
1264 : 0 : memcpy(&p[8], fd[i], sizeof(struct qbman_fd));
1265 : 0 : eqcr_pi++;
1266 : : }
1267 : :
1268 : : lwsync();
1269 : :
1270 : : /* Set the verb byte, have to substitute in the valid-bit */
1271 : 0 : eqcr_pi = s->eqcr.pi;
1272 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1273 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1274 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1275 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1276 [ # # # # ]: 0 : if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
1277 : : struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
1278 : :
1279 : 0 : d->eq.dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
1280 : 0 : ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
1281 : : }
1282 : 0 : eqcr_pi++;
1283 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1284 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1285 : : }
1286 : :
1287 : : /* Flush all the cacheline without load/store in between */
1288 : 0 : eqcr_pi = s->eqcr.pi;
1289 : : addr_cena = (size_t)s->sys.addr_cena;
1290 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1291 : : dcbf(addr_cena +
1292 : : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1293 : 0 : eqcr_pi++;
1294 : : }
1295 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1296 : :
1297 : 0 : return num_enqueued;
1298 : : }
1299 : :
1300 : 0 : static int qbman_swp_enqueue_multiple_fd_cinh_read_direct(
1301 : : struct qbman_swp *s,
1302 : : const struct qbman_eq_desc *d,
1303 : : struct qbman_fd **fd,
1304 : : uint32_t *flags,
1305 : : int num_frames)
1306 : : {
1307 : : uint32_t *p = NULL;
1308 : : const uint32_t *cl = qb_cl(d);
1309 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
1310 : : int i, num_enqueued = 0;
1311 : : uint64_t addr_cena;
1312 : :
1313 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
1314 : : full_mask = s->eqcr.pi_ci_mask;
1315 [ # # ]: 0 : if (!s->eqcr.available) {
1316 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
1317 : 0 : s->eqcr.ci = qbman_cinh_read(&s->sys,
1318 : 0 : QBMAN_CINH_SWP_EQCR_CI) & full_mask;
1319 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
1320 : : eqcr_ci, s->eqcr.ci);
1321 [ # # ]: 0 : if (!s->eqcr.available)
1322 : : return 0;
1323 : : }
1324 : :
1325 : 0 : eqcr_pi = s->eqcr.pi;
1326 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
1327 : : s->eqcr.available : num_frames;
1328 : 0 : s->eqcr.available -= num_enqueued;
1329 : : /* Fill in the EQCR ring */
1330 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1331 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1332 : 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1333 : 0 : memcpy(&p[1], &cl[1], 28);
1334 : 0 : memcpy(&p[8], fd[i], sizeof(struct qbman_fd));
1335 : 0 : eqcr_pi++;
1336 : : }
1337 : :
1338 : : lwsync();
1339 : :
1340 : : /* Set the verb byte, have to substitute in the valid-bit */
1341 : 0 : eqcr_pi = s->eqcr.pi;
1342 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1343 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1344 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1345 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1346 [ # # # # ]: 0 : if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
1347 : : struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
1348 : :
1349 : 0 : d->eq.dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
1350 : 0 : ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
1351 : : }
1352 : 0 : eqcr_pi++;
1353 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1354 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1355 : : }
1356 : :
1357 : : /* Flush all the cacheline without load/store in between */
1358 : 0 : eqcr_pi = s->eqcr.pi;
1359 : : addr_cena = (size_t)s->sys.addr_cena;
1360 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1361 : : dcbf(addr_cena +
1362 : : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1363 : 0 : eqcr_pi++;
1364 : : }
1365 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1366 : :
1367 : 0 : return num_enqueued;
1368 : : }
1369 : :
1370 : 0 : static int qbman_swp_enqueue_multiple_fd_cinh_direct(
1371 : : struct qbman_swp *s,
1372 : : const struct qbman_eq_desc *d,
1373 : : struct qbman_fd **fd,
1374 : : uint32_t *flags,
1375 : : int num_frames)
1376 : : {
1377 : : uint32_t *p = NULL;
1378 : : const uint32_t *cl = qb_cl(d);
1379 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
1380 : : int i, num_enqueued = 0;
1381 : :
1382 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
1383 : : full_mask = s->eqcr.pi_ci_mask;
1384 [ # # ]: 0 : if (!s->eqcr.available) {
1385 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
1386 : 0 : s->eqcr.ci = qbman_cinh_read(&s->sys,
1387 : 0 : QBMAN_CINH_SWP_EQCR_CI) & full_mask;
1388 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
1389 : : eqcr_ci, s->eqcr.ci);
1390 [ # # ]: 0 : if (!s->eqcr.available)
1391 : : return 0;
1392 : : }
1393 : :
1394 : 0 : eqcr_pi = s->eqcr.pi;
1395 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
1396 : : s->eqcr.available : num_frames;
1397 : 0 : s->eqcr.available -= num_enqueued;
1398 : : /* Fill in the EQCR ring */
1399 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1400 : 0 : p = qbman_cinh_write_start_wo_shadow(&s->sys,
1401 : 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1402 : 0 : memcpy_byte_by_byte(&p[1], &cl[1], 28);
1403 : 0 : memcpy_byte_by_byte(&p[8], fd[i], sizeof(struct qbman_fd));
1404 : 0 : eqcr_pi++;
1405 : : }
1406 : :
1407 : : lwsync();
1408 : :
1409 : : /* Set the verb byte, have to substitute in the valid-bit */
1410 : 0 : eqcr_pi = s->eqcr.pi;
1411 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1412 : 0 : p = qbman_cinh_write_start_wo_shadow(&s->sys,
1413 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1414 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1415 [ # # # # ]: 0 : if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
1416 : : struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
1417 : :
1418 : 0 : d->eq.dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
1419 : 0 : ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
1420 : : }
1421 : 0 : eqcr_pi++;
1422 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1423 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1424 : : }
1425 : :
1426 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1427 : :
1428 : 0 : return num_enqueued;
1429 : : }
1430 : :
1431 : 0 : static int qbman_swp_enqueue_multiple_fd_mem_back(struct qbman_swp *s,
1432 : : const struct qbman_eq_desc *d,
1433 : : struct qbman_fd **fd,
1434 : : uint32_t *flags,
1435 : : int num_frames)
1436 : : {
1437 : : uint32_t *p = NULL;
1438 : : const uint32_t *cl = qb_cl(d);
1439 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
1440 : : int i, num_enqueued = 0;
1441 : :
1442 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
1443 : : full_mask = s->eqcr.pi_ci_mask;
1444 [ # # ]: 0 : if (!s->eqcr.available) {
1445 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
1446 : 0 : s->eqcr.ci = qbman_cena_read_reg(&s->sys,
1447 : 0 : QBMAN_CENA_SWP_EQCR_CI_MEMBACK) & full_mask;
1448 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
1449 : : eqcr_ci, s->eqcr.ci);
1450 [ # # ]: 0 : if (!s->eqcr.available)
1451 : : return 0;
1452 : : }
1453 : :
1454 : 0 : eqcr_pi = s->eqcr.pi;
1455 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
1456 : : s->eqcr.available : num_frames;
1457 : 0 : s->eqcr.available -= num_enqueued;
1458 : : /* Fill in the EQCR ring */
1459 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1460 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1461 : 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1462 : 0 : memcpy(&p[1], &cl[1], 28);
1463 : 0 : memcpy(&p[8], fd[i], sizeof(struct qbman_fd));
1464 : 0 : eqcr_pi++;
1465 : : }
1466 : :
1467 : : /* Set the verb byte, have to substitute in the valid-bit */
1468 : 0 : eqcr_pi = s->eqcr.pi;
1469 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1470 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1471 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1472 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1473 [ # # # # ]: 0 : if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
1474 : : struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
1475 : :
1476 : 0 : d->eq.dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
1477 : 0 : ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
1478 : : }
1479 : 0 : eqcr_pi++;
1480 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1481 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1482 : : }
1483 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1484 : :
1485 : 0 : dma_wmb();
1486 : 0 : qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_EQCR_PI,
1487 : 0 : (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb);
1488 : 0 : return num_enqueued;
1489 : : }
1490 : :
1491 : 0 : int qbman_swp_enqueue_multiple_fd(struct qbman_swp *s,
1492 : : const struct qbman_eq_desc *d,
1493 : : struct qbman_fd **fd,
1494 : : uint32_t *flags,
1495 : : int num_frames)
1496 : : {
1497 [ # # ]: 0 : if (!s->stash_off)
1498 : 0 : return qbman_swp_enqueue_multiple_fd_ptr(s, d, fd, flags,
1499 : : num_frames);
1500 : : else
1501 : 0 : return qbman_swp_enqueue_multiple_fd_cinh_direct(s, d, fd,
1502 : : flags, num_frames);
1503 : : }
1504 : :
1505 : 0 : static int qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
1506 : : const struct qbman_eq_desc *d,
1507 : : const struct qbman_fd *fd,
1508 : : int num_frames)
1509 : : {
1510 : : uint32_t *p;
1511 : : const uint32_t *cl;
1512 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
1513 : : int i, num_enqueued = 0;
1514 : : uint64_t addr_cena;
1515 : :
1516 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
1517 : : full_mask = s->eqcr.pi_ci_mask;
1518 [ # # ]: 0 : if (!s->eqcr.available) {
1519 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
1520 : 0 : s->eqcr.ci = qbman_cena_read_reg(&s->sys,
1521 : 0 : QBMAN_CENA_SWP_EQCR_CI) & full_mask;
1522 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
1523 : : eqcr_ci, s->eqcr.ci);
1524 [ # # ]: 0 : if (!s->eqcr.available)
1525 : : return 0;
1526 : : }
1527 : :
1528 : 0 : eqcr_pi = s->eqcr.pi;
1529 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
1530 : : s->eqcr.available : num_frames;
1531 : 0 : s->eqcr.available -= num_enqueued;
1532 : : /* Fill in the EQCR ring */
1533 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1534 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1535 : 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1536 : 0 : cl = qb_cl(&d[i]);
1537 : 0 : memcpy(&p[1], &cl[1], 28);
1538 : 0 : memcpy(&p[8], &fd[i], sizeof(*fd));
1539 : 0 : eqcr_pi++;
1540 : : }
1541 : :
1542 : : lwsync();
1543 : :
1544 : : /* Set the verb byte, have to substitute in the valid-bit */
1545 : 0 : eqcr_pi = s->eqcr.pi;
1546 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1547 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1548 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1549 : 0 : cl = qb_cl(&d[i]);
1550 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1551 : 0 : eqcr_pi++;
1552 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1553 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1554 : : }
1555 : :
1556 : : /* Flush all the cacheline without load/store in between */
1557 : 0 : eqcr_pi = s->eqcr.pi;
1558 : : addr_cena = (size_t)s->sys.addr_cena;
1559 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1560 : : dcbf((uintptr_t)(addr_cena +
1561 : : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask)));
1562 : 0 : eqcr_pi++;
1563 : : }
1564 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1565 : :
1566 : 0 : return num_enqueued;
1567 : : }
1568 : :
1569 : 0 : static int qbman_swp_enqueue_multiple_desc_cinh_read_direct(
1570 : : struct qbman_swp *s,
1571 : : const struct qbman_eq_desc *d,
1572 : : const struct qbman_fd *fd,
1573 : : int num_frames)
1574 : : {
1575 : : uint32_t *p;
1576 : : const uint32_t *cl;
1577 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
1578 : : int i, num_enqueued = 0;
1579 : : uint64_t addr_cena;
1580 : :
1581 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
1582 : : full_mask = s->eqcr.pi_ci_mask;
1583 [ # # ]: 0 : if (!s->eqcr.available) {
1584 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
1585 : 0 : s->eqcr.ci = qbman_cinh_read(&s->sys,
1586 : 0 : QBMAN_CINH_SWP_EQCR_CI) & full_mask;
1587 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
1588 : : eqcr_ci, s->eqcr.ci);
1589 [ # # ]: 0 : if (!s->eqcr.available)
1590 : : return 0;
1591 : : }
1592 : :
1593 : 0 : eqcr_pi = s->eqcr.pi;
1594 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
1595 : : s->eqcr.available : num_frames;
1596 : 0 : s->eqcr.available -= num_enqueued;
1597 : : /* Fill in the EQCR ring */
1598 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1599 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1600 : 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1601 : 0 : cl = qb_cl(&d[i]);
1602 : 0 : memcpy(&p[1], &cl[1], 28);
1603 : 0 : memcpy(&p[8], &fd[i], sizeof(*fd));
1604 : 0 : eqcr_pi++;
1605 : : }
1606 : :
1607 : : lwsync();
1608 : :
1609 : : /* Set the verb byte, have to substitute in the valid-bit */
1610 : 0 : eqcr_pi = s->eqcr.pi;
1611 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1612 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1613 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1614 : 0 : cl = qb_cl(&d[i]);
1615 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1616 : 0 : eqcr_pi++;
1617 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1618 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1619 : : }
1620 : :
1621 : : /* Flush all the cacheline without load/store in between */
1622 : 0 : eqcr_pi = s->eqcr.pi;
1623 : : addr_cena = (size_t)s->sys.addr_cena;
1624 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1625 : : dcbf(addr_cena +
1626 : : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1627 : 0 : eqcr_pi++;
1628 : : }
1629 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1630 : :
1631 : 0 : return num_enqueued;
1632 : : }
1633 : :
1634 : 0 : static int qbman_swp_enqueue_multiple_desc_cinh_direct(
1635 : : struct qbman_swp *s,
1636 : : const struct qbman_eq_desc *d,
1637 : : const struct qbman_fd *fd,
1638 : : int num_frames)
1639 : : {
1640 : : uint32_t *p;
1641 : : const uint32_t *cl;
1642 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
1643 : : int i, num_enqueued = 0;
1644 : :
1645 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
1646 : : full_mask = s->eqcr.pi_ci_mask;
1647 [ # # ]: 0 : if (!s->eqcr.available) {
1648 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
1649 : 0 : s->eqcr.ci = qbman_cinh_read(&s->sys,
1650 : 0 : QBMAN_CINH_SWP_EQCR_CI) & full_mask;
1651 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
1652 : : eqcr_ci, s->eqcr.ci);
1653 [ # # ]: 0 : if (!s->eqcr.available)
1654 : : return 0;
1655 : : }
1656 : :
1657 : 0 : eqcr_pi = s->eqcr.pi;
1658 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
1659 : : s->eqcr.available : num_frames;
1660 : 0 : s->eqcr.available -= num_enqueued;
1661 : : /* Fill in the EQCR ring */
1662 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1663 : 0 : p = qbman_cinh_write_start_wo_shadow(&s->sys,
1664 : 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1665 : 0 : cl = qb_cl(&d[i]);
1666 : 0 : memcpy_byte_by_byte(&p[1], &cl[1], 28);
1667 : : memcpy_byte_by_byte(&p[8], &fd[i], sizeof(*fd));
1668 : 0 : eqcr_pi++;
1669 : : }
1670 : :
1671 : : lwsync();
1672 : :
1673 : : /* Set the verb byte, have to substitute in the valid-bit */
1674 : 0 : eqcr_pi = s->eqcr.pi;
1675 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1676 : 0 : p = qbman_cinh_write_start_wo_shadow(&s->sys,
1677 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1678 : 0 : cl = qb_cl(&d[i]);
1679 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1680 : 0 : eqcr_pi++;
1681 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1682 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1683 : : }
1684 : :
1685 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1686 : :
1687 : 0 : return num_enqueued;
1688 : : }
1689 : :
1690 : 0 : static int qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s,
1691 : : const struct qbman_eq_desc *d,
1692 : : const struct qbman_fd *fd,
1693 : : int num_frames)
1694 : : {
1695 : : uint32_t *p;
1696 : : const uint32_t *cl;
1697 : : uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
1698 : : int i, num_enqueued = 0;
1699 : :
1700 : 0 : half_mask = (s->eqcr.pi_ci_mask>>1);
1701 : : full_mask = s->eqcr.pi_ci_mask;
1702 [ # # ]: 0 : if (!s->eqcr.available) {
1703 [ # # ]: 0 : eqcr_ci = s->eqcr.ci;
1704 : 0 : s->eqcr.ci = qbman_cena_read_reg(&s->sys,
1705 : 0 : QBMAN_CENA_SWP_EQCR_CI_MEMBACK) & full_mask;
1706 [ # # ]: 0 : s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
1707 : : eqcr_ci, s->eqcr.ci);
1708 [ # # ]: 0 : if (!s->eqcr.available)
1709 : : return 0;
1710 : : }
1711 : :
1712 : 0 : eqcr_pi = s->eqcr.pi;
1713 : 0 : num_enqueued = (s->eqcr.available < num_frames) ?
1714 : : s->eqcr.available : num_frames;
1715 : 0 : s->eqcr.available -= num_enqueued;
1716 : : /* Fill in the EQCR ring */
1717 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1718 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1719 : 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1720 : 0 : cl = qb_cl(&d[i]);
1721 : 0 : memcpy(&p[1], &cl[1], 28);
1722 : 0 : memcpy(&p[8], &fd[i], sizeof(*fd));
1723 : 0 : eqcr_pi++;
1724 : : }
1725 : :
1726 : : /* Set the verb byte, have to substitute in the valid-bit */
1727 : 0 : eqcr_pi = s->eqcr.pi;
1728 [ # # ]: 0 : for (i = 0; i < num_enqueued; i++) {
1729 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
1730 [ # # ]: 0 : QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
1731 : 0 : cl = qb_cl(&d[i]);
1732 : 0 : p[0] = cl[0] | s->eqcr.pi_vb;
1733 : 0 : eqcr_pi++;
1734 [ # # ]: 0 : if (!(eqcr_pi & half_mask))
1735 : 0 : s->eqcr.pi_vb ^= QB_VALID_BIT;
1736 : : }
1737 : :
1738 : 0 : s->eqcr.pi = eqcr_pi & full_mask;
1739 : :
1740 : 0 : dma_wmb();
1741 : 0 : qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_EQCR_PI,
1742 : 0 : (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb);
1743 : :
1744 : 0 : return num_enqueued;
1745 : : }
1746 : 0 : int qbman_swp_enqueue_multiple_desc(struct qbman_swp *s,
1747 : : const struct qbman_eq_desc *d,
1748 : : const struct qbman_fd *fd,
1749 : : int num_frames)
1750 : : {
1751 [ # # ]: 0 : if (!s->stash_off)
1752 : 0 : return qbman_swp_enqueue_multiple_desc_ptr(s, d, fd,
1753 : : num_frames);
1754 : : else
1755 : 0 : return qbman_swp_enqueue_multiple_desc_cinh_direct(s, d, fd,
1756 : : num_frames);
1757 : :
1758 : : }
1759 : :
1760 : : /*************************/
1761 : : /* Static (push) dequeue */
1762 : : /*************************/
1763 : :
1764 : 0 : void qbman_swp_push_get(struct qbman_swp *s, uint8_t channel_idx, int *enabled)
1765 : : {
1766 : 0 : uint16_t src = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK;
1767 : :
1768 : : QBMAN_BUG_ON(channel_idx > 15);
1769 : 0 : *enabled = src | (1 << channel_idx);
1770 : 0 : }
1771 : :
1772 : 0 : void qbman_swp_push_set(struct qbman_swp *s, uint8_t channel_idx, int enable)
1773 : : {
1774 : : uint16_t dqsrc;
1775 : :
1776 : : QBMAN_BUG_ON(channel_idx > 15);
1777 [ # # ]: 0 : if (enable)
1778 : 0 : s->sdq |= 1 << channel_idx;
1779 : : else
1780 : 0 : s->sdq &= ~(1 << channel_idx);
1781 : :
1782 : : /* Read make the complete src map. If no channels are enabled
1783 : : * the SDQCR must be 0 or else QMan will assert errors
1784 : : */
1785 : 0 : dqsrc = (s->sdq >> QB_SDQCR_SRC_SHIFT) & QB_SDQCR_SRC_MASK;
1786 [ # # ]: 0 : if (dqsrc != 0)
1787 : : qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_SDQCR, s->sdq);
1788 : : else
1789 : : qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_SDQCR, 0);
1790 : 0 : }
1791 : :
1792 : : /***************************/
1793 : : /* Volatile (pull) dequeue */
1794 : : /***************************/
1795 : :
1796 : : /* These should be const, eventually */
1797 : : #define QB_VDQCR_VERB_DCT_SHIFT 0
1798 : : #define QB_VDQCR_VERB_DT_SHIFT 2
1799 : : #define QB_VDQCR_VERB_RLS_SHIFT 4
1800 : : #define QB_VDQCR_VERB_WAE_SHIFT 5
1801 : : #define QB_VDQCR_VERB_RAD_SHIFT 6
1802 : :
1803 : : enum qb_pull_dt_e {
1804 : : qb_pull_dt_channel,
1805 : : qb_pull_dt_workqueue,
1806 : : qb_pull_dt_framequeue
1807 : : };
1808 : :
1809 : 0 : void qbman_pull_desc_clear(struct qbman_pull_desc *d)
1810 : : {
1811 : : memset(d, 0, sizeof(*d));
1812 : 0 : }
1813 : :
1814 : 0 : void qbman_pull_desc_set_storage(struct qbman_pull_desc *d,
1815 : : struct qbman_result *storage,
1816 : : dma_addr_t storage_phys,
1817 : : int stash)
1818 : : {
1819 : 0 : d->pull.rsp_addr_virt = (size_t)storage;
1820 : :
1821 [ # # ]: 0 : if (!storage) {
1822 : 0 : d->pull.verb &= ~(1 << QB_VDQCR_VERB_RLS_SHIFT);
1823 : 0 : return;
1824 : : }
1825 : 0 : d->pull.verb |= 1 << QB_VDQCR_VERB_RLS_SHIFT;
1826 [ # # ]: 0 : if (stash)
1827 : 0 : d->pull.verb |= 1 << QB_VDQCR_VERB_WAE_SHIFT;
1828 : : else
1829 : 0 : d->pull.verb &= ~(1 << QB_VDQCR_VERB_WAE_SHIFT);
1830 : :
1831 : 0 : d->pull.rsp_addr = storage_phys;
1832 : : }
1833 : :
1834 : 0 : void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d,
1835 : : uint8_t numframes)
1836 : : {
1837 : 0 : d->pull.numf = numframes - 1;
1838 : 0 : }
1839 : :
1840 : 0 : void qbman_pull_desc_set_token(struct qbman_pull_desc *d, uint8_t token)
1841 : : {
1842 : 0 : d->pull.tok = token;
1843 : 0 : }
1844 : :
1845 : 0 : void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, uint32_t fqid)
1846 : : {
1847 : 0 : d->pull.verb |= 1 << QB_VDQCR_VERB_DCT_SHIFT;
1848 : 0 : d->pull.verb |= qb_pull_dt_framequeue << QB_VDQCR_VERB_DT_SHIFT;
1849 : 0 : d->pull.dq_src = fqid;
1850 : 0 : }
1851 : :
1852 : 0 : void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, uint32_t wqid,
1853 : : enum qbman_pull_type_e dct)
1854 : : {
1855 : 0 : d->pull.verb |= dct << QB_VDQCR_VERB_DCT_SHIFT;
1856 : 0 : d->pull.verb |= qb_pull_dt_workqueue << QB_VDQCR_VERB_DT_SHIFT;
1857 : 0 : d->pull.dq_src = wqid;
1858 : 0 : }
1859 : :
1860 : 0 : void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, uint32_t chid,
1861 : : enum qbman_pull_type_e dct)
1862 : : {
1863 : 0 : d->pull.verb |= dct << QB_VDQCR_VERB_DCT_SHIFT;
1864 : : d->pull.verb |= qb_pull_dt_channel << QB_VDQCR_VERB_DT_SHIFT;
1865 : 0 : d->pull.dq_src = chid;
1866 : 0 : }
1867 : :
1868 : : /**
1869 : : * qbman_pull_desc_set_rad() - Decide whether reschedule the fq after dequeue
1870 : : *
1871 : : * @rad: 1 = Reschedule the FQ after dequeue.
1872 : : * 0 = Allow the FQ to remain active after dequeue.
1873 : : */
1874 : 0 : void qbman_pull_desc_set_rad(struct qbman_pull_desc *d, int rad)
1875 : : {
1876 [ # # ]: 0 : if (d->pull.verb & (1 << QB_VDQCR_VERB_RLS_SHIFT)) {
1877 [ # # ]: 0 : if (rad)
1878 : 0 : d->pull.verb |= 1 << QB_VDQCR_VERB_RAD_SHIFT;
1879 : : else
1880 : 0 : d->pull.verb &= ~(1 << QB_VDQCR_VERB_RAD_SHIFT);
1881 : : } else {
1882 : : printf("The RAD feature is not valid when RLS = 0\n");
1883 : : }
1884 : 0 : }
1885 : :
1886 : 0 : static int qbman_swp_pull_direct(struct qbman_swp *s,
1887 : : struct qbman_pull_desc *d)
1888 : : {
1889 : : uint32_t *p;
1890 : : uint32_t *cl = qb_cl(d);
1891 : :
1892 [ # # ]: 0 : if (!atomic_dec_and_test(&s->vdq.busy)) {
1893 : : atomic_inc(&s->vdq.busy);
1894 : 0 : return -EBUSY;
1895 : : }
1896 : :
1897 : 0 : d->pull.tok = s->sys.idx + 1;
1898 : 0 : s->vdq.storage = (void *)(size_t)d->pull.rsp_addr_virt;
1899 : : p = qbman_cena_write_start_wo_shadow(&s->sys, QBMAN_CENA_SWP_VDQCR);
1900 : 0 : memcpy(&p[1], &cl[1], 12);
1901 : :
1902 : : /* Set the verb byte, have to substitute in the valid-bit */
1903 : : lwsync();
1904 : 0 : p[0] = cl[0] | s->vdq.valid_bit;
1905 : 0 : s->vdq.valid_bit ^= QB_VALID_BIT;
1906 : : qbman_cena_write_complete_wo_shadow(&s->sys, QBMAN_CENA_SWP_VDQCR);
1907 : :
1908 : 0 : return 0;
1909 : : }
1910 : :
1911 : 0 : static int qbman_swp_pull_cinh_direct(struct qbman_swp *s,
1912 : : struct qbman_pull_desc *d)
1913 : : {
1914 : : uint32_t *p;
1915 : : uint32_t *cl = qb_cl(d);
1916 : :
1917 [ # # ]: 0 : if (!atomic_dec_and_test(&s->vdq.busy)) {
1918 : : atomic_inc(&s->vdq.busy);
1919 : 0 : return -EBUSY;
1920 : : }
1921 : :
1922 : 0 : d->pull.tok = s->sys.idx + 1;
1923 : 0 : s->vdq.storage = (void *)(size_t)d->pull.rsp_addr_virt;
1924 : : p = qbman_cinh_write_start_wo_shadow(&s->sys, QBMAN_CENA_SWP_VDQCR);
1925 : 0 : memcpy_byte_by_byte(&p[1], &cl[1], 12);
1926 : :
1927 : : /* Set the verb byte, have to substitute in the valid-bit */
1928 : : lwsync();
1929 : 0 : p[0] = cl[0] | s->vdq.valid_bit;
1930 : 0 : s->vdq.valid_bit ^= QB_VALID_BIT;
1931 : :
1932 : 0 : return 0;
1933 : : }
1934 : :
1935 : 0 : static int qbman_swp_pull_mem_back(struct qbman_swp *s,
1936 : : struct qbman_pull_desc *d)
1937 : : {
1938 : : uint32_t *p;
1939 : : uint32_t *cl = qb_cl(d);
1940 : :
1941 [ # # ]: 0 : if (!atomic_dec_and_test(&s->vdq.busy)) {
1942 : : atomic_inc(&s->vdq.busy);
1943 : 0 : return -EBUSY;
1944 : : }
1945 : :
1946 : 0 : d->pull.tok = s->sys.idx + 1;
1947 : 0 : s->vdq.storage = (void *)(size_t)d->pull.rsp_addr_virt;
1948 : : p = qbman_cena_write_start_wo_shadow(&s->sys, QBMAN_CENA_SWP_VDQCR_MEM);
1949 : 0 : memcpy(&p[1], &cl[1], 12);
1950 : :
1951 : : /* Set the verb byte, have to substitute in the valid-bit */
1952 : 0 : p[0] = cl[0] | s->vdq.valid_bit;
1953 : 0 : s->vdq.valid_bit ^= QB_VALID_BIT;
1954 : 0 : dma_wmb();
1955 : : qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_VDQCR_RT, QMAN_RT_MODE);
1956 : :
1957 : 0 : return 0;
1958 : : }
1959 : :
1960 : 0 : int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d)
1961 : : {
1962 [ # # ]: 0 : if (!s->stash_off)
1963 : 0 : return qbman_swp_pull_ptr(s, d);
1964 : : else
1965 : 0 : return qbman_swp_pull_cinh_direct(s, d);
1966 : : }
1967 : :
1968 : : /****************/
1969 : : /* Polling DQRR */
1970 : : /****************/
1971 : :
1972 : : #define QMAN_DQRR_PI_MASK 0xf
1973 : :
1974 : : #define QBMAN_RESULT_DQ 0x60
1975 : : #define QBMAN_RESULT_FQRN 0x21
1976 : : #define QBMAN_RESULT_FQRNI 0x22
1977 : : #define QBMAN_RESULT_FQPN 0x24
1978 : : #define QBMAN_RESULT_FQDAN 0x25
1979 : : #define QBMAN_RESULT_CDAN 0x26
1980 : : #define QBMAN_RESULT_CSCN_MEM 0x27
1981 : : #define QBMAN_RESULT_CGCU 0x28
1982 : : #define QBMAN_RESULT_BPSCN 0x29
1983 : : #define QBMAN_RESULT_CSCN_WQ 0x2a
1984 : :
1985 : : #include <rte_prefetch.h>
1986 : :
1987 : 0 : void qbman_swp_prefetch_dqrr_next(struct qbman_swp *s)
1988 : : {
1989 : : const struct qbman_result *p;
1990 : :
1991 : 0 : p = qbman_cena_read_wo_shadow(&s->sys,
1992 : 0 : QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
1993 : : rte_prefetch0(p);
1994 : 0 : }
1995 : :
1996 : : /* NULL return if there are no unconsumed DQRR entries. Returns a DQRR entry
1997 : : * only once, so repeated calls can return a sequence of DQRR entries, without
1998 : : * requiring they be consumed immediately or in any particular order.
1999 : : */
2000 : 0 : const struct qbman_result *qbman_swp_dqrr_next(struct qbman_swp *s)
2001 : : {
2002 [ # # ]: 0 : if (!s->stash_off)
2003 : 0 : return qbman_swp_dqrr_next_ptr(s);
2004 : : else
2005 : 0 : return qbman_swp_dqrr_next_cinh_direct(s);
2006 : : }
2007 : :
2008 : 0 : const struct qbman_result *qbman_swp_dqrr_next_direct(struct qbman_swp *s)
2009 : : {
2010 : : uint32_t verb;
2011 : : uint32_t response_verb;
2012 : : uint32_t flags;
2013 : : const struct qbman_result *p;
2014 : :
2015 : : /* Before using valid-bit to detect if something is there, we have to
2016 : : * handle the case of the DQRR reset bug...
2017 : : */
2018 [ # # ]: 0 : if (s->dqrr.reset_bug) {
2019 : : /* We pick up new entries by cache-inhibited producer index,
2020 : : * which means that a non-coherent mapping would require us to
2021 : : * invalidate and read *only* once that PI has indicated that
2022 : : * there's an entry here. The first trip around the DQRR ring
2023 : : * will be much less efficient than all subsequent trips around
2024 : : * it...
2025 : : */
2026 : 0 : uint8_t pi = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_DQPI) &
2027 : : QMAN_DQRR_PI_MASK;
2028 : :
2029 : : /* there are new entries if pi != next_idx */
2030 [ # # ]: 0 : if (pi == s->dqrr.next_idx)
2031 : : return NULL;
2032 : :
2033 : : /* if next_idx is/was the last ring index, and 'pi' is
2034 : : * different, we can disable the workaround as all the ring
2035 : : * entries have now been DMA'd to so valid-bit checking is
2036 : : * repaired. Note: this logic needs to be based on next_idx
2037 : : * (which increments one at a time), rather than on pi (which
2038 : : * can burst and wrap-around between our snapshots of it).
2039 : : */
2040 : : QBMAN_BUG_ON((s->dqrr.dqrr_size - 1) < 0);
2041 [ # # ]: 0 : if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1u)) {
2042 : : pr_debug("DEBUG: next_idx=%d, pi=%d, clear reset bug\n",
2043 : : s->dqrr.next_idx, pi);
2044 : 0 : s->dqrr.reset_bug = 0;
2045 : : }
2046 : : qbman_cena_invalidate_prefetch(&s->sys,
2047 : : QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
2048 : : }
2049 : 0 : p = qbman_cena_read_wo_shadow(&s->sys,
2050 [ # # ]: 0 : QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
2051 : :
2052 : 0 : verb = p->dq.verb;
2053 : :
2054 : : /* If the valid-bit isn't of the expected polarity, nothing there. Note,
2055 : : * in the DQRR reset bug workaround, we shouldn't need to skip these
2056 : : * check, because we've already determined that a new entry is available
2057 : : * and we've invalidated the cacheline before reading it, so the
2058 : : * valid-bit behaviour is repaired and should tell us what we already
2059 : : * knew from reading PI.
2060 : : */
2061 [ # # ]: 0 : if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit)
2062 : : return NULL;
2063 : :
2064 : : /* There's something there. Move "next_idx" attention to the next ring
2065 : : * entry (and prefetch it) before returning what we found.
2066 : : */
2067 : 0 : s->dqrr.next_idx++;
2068 [ # # ]: 0 : if (s->dqrr.next_idx == s->dqrr.dqrr_size) {
2069 : 0 : s->dqrr.next_idx = 0;
2070 : 0 : s->dqrr.valid_bit ^= QB_VALID_BIT;
2071 : : }
2072 : : /* If this is the final response to a volatile dequeue command
2073 : : * indicate that the vdq is no longer busy
2074 : : */
2075 : 0 : flags = p->dq.stat;
2076 : : response_verb = verb & QBMAN_RESPONSE_VERB_MASK;
2077 [ # # ]: 0 : if ((response_verb == QBMAN_RESULT_DQ) &&
2078 [ # # ]: 0 : (flags & QBMAN_DQ_STAT_VOLATILE) &&
2079 : : (flags & QBMAN_DQ_STAT_EXPIRED))
2080 : : atomic_inc(&s->vdq.busy);
2081 : :
2082 : : return p;
2083 : : }
2084 : :
2085 : 0 : const struct qbman_result *qbman_swp_dqrr_next_cinh_direct(struct qbman_swp *s)
2086 : : {
2087 : : uint32_t verb;
2088 : : uint32_t response_verb;
2089 : : uint32_t flags;
2090 : : const struct qbman_result *p;
2091 : :
2092 : : /* Before using valid-bit to detect if something is there, we have to
2093 : : * handle the case of the DQRR reset bug...
2094 : : */
2095 [ # # ]: 0 : if (s->dqrr.reset_bug) {
2096 : : /* We pick up new entries by cache-inhibited producer index,
2097 : : * which means that a non-coherent mapping would require us to
2098 : : * invalidate and read *only* once that PI has indicated that
2099 : : * there's an entry here. The first trip around the DQRR ring
2100 : : * will be much less efficient than all subsequent trips around
2101 : : * it...
2102 : : */
2103 : 0 : uint8_t pi = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_DQPI) &
2104 : : QMAN_DQRR_PI_MASK;
2105 : :
2106 : : /* there are new entries if pi != next_idx */
2107 [ # # ]: 0 : if (pi == s->dqrr.next_idx)
2108 : : return NULL;
2109 : :
2110 : : /* if next_idx is/was the last ring index, and 'pi' is
2111 : : * different, we can disable the workaround as all the ring
2112 : : * entries have now been DMA'd to so valid-bit checking is
2113 : : * repaired. Note: this logic needs to be based on next_idx
2114 : : * (which increments one at a time), rather than on pi (which
2115 : : * can burst and wrap-around between our snapshots of it).
2116 : : */
2117 : : QBMAN_BUG_ON((s->dqrr.dqrr_size - 1) < 0);
2118 [ # # ]: 0 : if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1u)) {
2119 : : pr_debug("DEBUG: next_idx=%d, pi=%d, clear reset bug\n",
2120 : : s->dqrr.next_idx, pi);
2121 : 0 : s->dqrr.reset_bug = 0;
2122 : : }
2123 : : }
2124 : 0 : p = qbman_cinh_read_wo_shadow(&s->sys,
2125 [ # # ]: 0 : QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
2126 : :
2127 : 0 : verb = p->dq.verb;
2128 : :
2129 : : /* If the valid-bit isn't of the expected polarity, nothing there. Note,
2130 : : * in the DQRR reset bug workaround, we shouldn't need to skip these
2131 : : * check, because we've already determined that a new entry is available
2132 : : * and we've invalidated the cacheline before reading it, so the
2133 : : * valid-bit behaviour is repaired and should tell us what we already
2134 : : * knew from reading PI.
2135 : : */
2136 [ # # ]: 0 : if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit)
2137 : : return NULL;
2138 : :
2139 : : /* There's something there. Move "next_idx" attention to the next ring
2140 : : * entry (and prefetch it) before returning what we found.
2141 : : */
2142 : 0 : s->dqrr.next_idx++;
2143 [ # # ]: 0 : if (s->dqrr.next_idx == s->dqrr.dqrr_size) {
2144 : 0 : s->dqrr.next_idx = 0;
2145 : 0 : s->dqrr.valid_bit ^= QB_VALID_BIT;
2146 : : }
2147 : : /* If this is the final response to a volatile dequeue command
2148 : : * indicate that the vdq is no longer busy
2149 : : */
2150 : 0 : flags = p->dq.stat;
2151 : : response_verb = verb & QBMAN_RESPONSE_VERB_MASK;
2152 [ # # ]: 0 : if ((response_verb == QBMAN_RESULT_DQ) &&
2153 [ # # ]: 0 : (flags & QBMAN_DQ_STAT_VOLATILE) &&
2154 : : (flags & QBMAN_DQ_STAT_EXPIRED))
2155 : : atomic_inc(&s->vdq.busy);
2156 : :
2157 : : return p;
2158 : : }
2159 : :
2160 : 0 : const struct qbman_result *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s)
2161 : : {
2162 : : uint32_t verb;
2163 : : uint32_t response_verb;
2164 : : uint32_t flags;
2165 : : const struct qbman_result *p;
2166 : :
2167 : 0 : p = qbman_cena_read_wo_shadow(&s->sys,
2168 [ # # ]: 0 : QBMAN_CENA_SWP_DQRR_MEM(s->dqrr.next_idx));
2169 : :
2170 : 0 : verb = p->dq.verb;
2171 : :
2172 : : /* If the valid-bit isn't of the expected polarity, nothing there. Note,
2173 : : * in the DQRR reset bug workaround, we shouldn't need to skip these
2174 : : * check, because we've already determined that a new entry is available
2175 : : * and we've invalidated the cacheline before reading it, so the
2176 : : * valid-bit behaviour is repaired and should tell us what we already
2177 : : * knew from reading PI.
2178 : : */
2179 [ # # ]: 0 : if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit)
2180 : : return NULL;
2181 : :
2182 : : /* There's something there. Move "next_idx" attention to the next ring
2183 : : * entry (and prefetch it) before returning what we found.
2184 : : */
2185 : 0 : s->dqrr.next_idx++;
2186 [ # # ]: 0 : if (s->dqrr.next_idx == s->dqrr.dqrr_size) {
2187 : 0 : s->dqrr.next_idx = 0;
2188 : 0 : s->dqrr.valid_bit ^= QB_VALID_BIT;
2189 : : }
2190 : : /* If this is the final response to a volatile dequeue command
2191 : : * indicate that the vdq is no longer busy
2192 : : */
2193 : 0 : flags = p->dq.stat;
2194 : : response_verb = verb & QBMAN_RESPONSE_VERB_MASK;
2195 [ # # ]: 0 : if ((response_verb == QBMAN_RESULT_DQ)
2196 : : && (flags & QBMAN_DQ_STAT_VOLATILE)
2197 [ # # ]: 0 : && (flags & QBMAN_DQ_STAT_EXPIRED))
2198 : : atomic_inc(&s->vdq.busy);
2199 : : return p;
2200 : : }
2201 : :
2202 : : /* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */
2203 : 0 : void qbman_swp_dqrr_consume(struct qbman_swp *s,
2204 : : const struct qbman_result *dq)
2205 : : {
2206 : 0 : qbman_cinh_write(&s->sys,
2207 : 0 : QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq));
2208 : 0 : }
2209 : :
2210 : : /* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */
2211 : 0 : void qbman_swp_dqrr_idx_consume(struct qbman_swp *s,
2212 : : uint8_t dqrr_index)
2213 : : {
2214 : 0 : qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, dqrr_index);
2215 : 0 : }
2216 : :
2217 : : /*********************************/
2218 : : /* Polling user-provided storage */
2219 : : /*********************************/
2220 : :
2221 : 0 : int qbman_result_has_new_result(struct qbman_swp *s,
2222 : : struct qbman_result *dq)
2223 : : {
2224 [ # # ]: 0 : if (dq->dq.tok == 0)
2225 : : return 0;
2226 : :
2227 : : /*
2228 : : * Set token to be 0 so we will detect change back to 1
2229 : : * next time the looping is traversed. Const is cast away here
2230 : : * as we want users to treat the dequeue responses as read only.
2231 : : */
2232 : 0 : ((struct qbman_result *)dq)->dq.tok = 0;
2233 : :
2234 : : /*
2235 : : * VDQCR "no longer busy" hook - not quite the same as DQRR, because
2236 : : * the fact "VDQCR" shows busy doesn't mean that we hold the result
2237 : : * that makes it available. Eg. we may be looking at our 10th dequeue
2238 : : * result, having released VDQCR after the 1st result and it is now
2239 : : * busy due to some other command!
2240 : : */
2241 [ # # ]: 0 : if (s->vdq.storage == dq) {
2242 : 0 : s->vdq.storage = NULL;
2243 : : atomic_inc(&s->vdq.busy);
2244 : : }
2245 : :
2246 : : return 1;
2247 : : }
2248 : :
2249 : 0 : int qbman_check_new_result(struct qbman_result *dq)
2250 : : {
2251 [ # # ]: 0 : if (dq->dq.tok == 0)
2252 : : return 0;
2253 : :
2254 : : /*
2255 : : * Set token to be 0 so we will detect change back to 1
2256 : : * next time the looping is traversed. Const is cast away here
2257 : : * as we want users to treat the dequeue responses as read only.
2258 : : */
2259 : 0 : ((struct qbman_result *)dq)->dq.tok = 0;
2260 : :
2261 : 0 : return 1;
2262 : : }
2263 : :
2264 : 0 : int qbman_check_command_complete(struct qbman_result *dq)
2265 : : {
2266 : : struct qbman_swp *s;
2267 : :
2268 [ # # ]: 0 : if (dq->dq.tok == 0)
2269 : : return 0;
2270 : :
2271 : 0 : s = portal_idx_map[dq->dq.tok - 1];
2272 : : /*
2273 : : * VDQCR "no longer busy" hook - not quite the same as DQRR, because
2274 : : * the fact "VDQCR" shows busy doesn't mean that we hold the result
2275 : : * that makes it available. Eg. we may be looking at our 10th dequeue
2276 : : * result, having released VDQCR after the 1st result and it is now
2277 : : * busy due to some other command!
2278 : : */
2279 [ # # ]: 0 : if (s->vdq.storage == dq) {
2280 : 0 : s->vdq.storage = NULL;
2281 : : atomic_inc(&s->vdq.busy);
2282 : : }
2283 : :
2284 : : return 1;
2285 : : }
2286 : :
2287 : : /********************************/
2288 : : /* Categorising qbman results */
2289 : : /********************************/
2290 : :
2291 : : static inline int __qbman_result_is_x(const struct qbman_result *dq,
2292 : : uint8_t x)
2293 : : {
2294 : 0 : uint8_t response_verb = dq->dq.verb & QBMAN_RESPONSE_VERB_MASK;
2295 : :
2296 : 0 : return (response_verb == x);
2297 : : }
2298 : :
2299 : 0 : int qbman_result_is_DQ(const struct qbman_result *dq)
2300 : : {
2301 : 0 : return __qbman_result_is_x(dq, QBMAN_RESULT_DQ);
2302 : : }
2303 : :
2304 : 0 : int qbman_result_is_FQDAN(const struct qbman_result *dq)
2305 : : {
2306 : 0 : return __qbman_result_is_x(dq, QBMAN_RESULT_FQDAN);
2307 : : }
2308 : :
2309 : 0 : int qbman_result_is_CDAN(const struct qbman_result *dq)
2310 : : {
2311 : 0 : return __qbman_result_is_x(dq, QBMAN_RESULT_CDAN);
2312 : : }
2313 : :
2314 : 0 : int qbman_result_is_CSCN(const struct qbman_result *dq)
2315 : : {
2316 [ # # # # ]: 0 : return __qbman_result_is_x(dq, QBMAN_RESULT_CSCN_MEM) ||
2317 : : __qbman_result_is_x(dq, QBMAN_RESULT_CSCN_WQ);
2318 : : }
2319 : :
2320 : 0 : int qbman_result_is_BPSCN(const struct qbman_result *dq)
2321 : : {
2322 : 0 : return __qbman_result_is_x(dq, QBMAN_RESULT_BPSCN);
2323 : : }
2324 : :
2325 : 0 : int qbman_result_is_CGCU(const struct qbman_result *dq)
2326 : : {
2327 : 0 : return __qbman_result_is_x(dq, QBMAN_RESULT_CGCU);
2328 : : }
2329 : :
2330 : 0 : int qbman_result_is_FQRN(const struct qbman_result *dq)
2331 : : {
2332 : 0 : return __qbman_result_is_x(dq, QBMAN_RESULT_FQRN);
2333 : : }
2334 : :
2335 : 0 : int qbman_result_is_FQRNI(const struct qbman_result *dq)
2336 : : {
2337 : 0 : return __qbman_result_is_x(dq, QBMAN_RESULT_FQRNI);
2338 : : }
2339 : :
2340 : 0 : int qbman_result_is_FQPN(const struct qbman_result *dq)
2341 : : {
2342 : 0 : return __qbman_result_is_x(dq, QBMAN_RESULT_FQPN);
2343 : : }
2344 : :
2345 : : /*********************************/
2346 : : /* Parsing frame dequeue results */
2347 : : /*********************************/
2348 : :
2349 : : /* These APIs assume qbman_result_is_DQ() is TRUE */
2350 : :
2351 : 0 : uint8_t qbman_result_DQ_flags(const struct qbman_result *dq)
2352 : : {
2353 : 0 : return dq->dq.stat;
2354 : : }
2355 : :
2356 : 0 : uint16_t qbman_result_DQ_seqnum(const struct qbman_result *dq)
2357 : : {
2358 : 0 : return dq->dq.seqnum;
2359 : : }
2360 : :
2361 : 0 : uint16_t qbman_result_DQ_odpid(const struct qbman_result *dq)
2362 : : {
2363 : 0 : return dq->dq.oprid;
2364 : : }
2365 : :
2366 : 0 : uint32_t qbman_result_DQ_fqid(const struct qbman_result *dq)
2367 : : {
2368 : 0 : return dq->dq.fqid;
2369 : : }
2370 : :
2371 : 0 : uint32_t qbman_result_DQ_byte_count(const struct qbman_result *dq)
2372 : : {
2373 : 0 : return dq->dq.fq_byte_cnt;
2374 : : }
2375 : :
2376 : 0 : uint32_t qbman_result_DQ_frame_count(const struct qbman_result *dq)
2377 : : {
2378 : 0 : return dq->dq.fq_frm_cnt;
2379 : : }
2380 : :
2381 : 0 : uint64_t qbman_result_DQ_fqd_ctx(const struct qbman_result *dq)
2382 : : {
2383 : 0 : return dq->dq.fqd_ctx;
2384 : : }
2385 : :
2386 : 0 : const struct qbman_fd *qbman_result_DQ_fd(const struct qbman_result *dq)
2387 : : {
2388 : 0 : return (const struct qbman_fd *)&dq->dq.fd[0];
2389 : : }
2390 : :
2391 : : /**************************************/
2392 : : /* Parsing state-change notifications */
2393 : : /**************************************/
2394 : 0 : uint8_t qbman_result_SCN_state(const struct qbman_result *scn)
2395 : : {
2396 : 0 : return scn->scn.state;
2397 : : }
2398 : :
2399 : 0 : uint32_t qbman_result_SCN_rid(const struct qbman_result *scn)
2400 : : {
2401 : 0 : return scn->scn.rid_tok;
2402 : : }
2403 : :
2404 : 0 : uint64_t qbman_result_SCN_ctx(const struct qbman_result *scn)
2405 : : {
2406 : 0 : return scn->scn.ctx;
2407 : : }
2408 : :
2409 : : /*****************/
2410 : : /* Parsing BPSCN */
2411 : : /*****************/
2412 : 0 : uint16_t qbman_result_bpscn_bpid(const struct qbman_result *scn)
2413 : : {
2414 : 0 : return (uint16_t)qbman_result_SCN_rid(scn) & 0x3FFF;
2415 : : }
2416 : :
2417 : 0 : int qbman_result_bpscn_has_free_bufs(const struct qbman_result *scn)
2418 : : {
2419 : 0 : return !(int)(qbman_result_SCN_state(scn) & 0x1);
2420 : : }
2421 : :
2422 : 0 : int qbman_result_bpscn_is_depleted(const struct qbman_result *scn)
2423 : : {
2424 : 0 : return (int)(qbman_result_SCN_state(scn) & 0x2);
2425 : : }
2426 : :
2427 : 0 : int qbman_result_bpscn_is_surplus(const struct qbman_result *scn)
2428 : : {
2429 : 0 : return (int)(qbman_result_SCN_state(scn) & 0x4);
2430 : : }
2431 : :
2432 : 0 : uint64_t qbman_result_bpscn_ctx(const struct qbman_result *scn)
2433 : : {
2434 : 0 : return qbman_result_SCN_ctx(scn);
2435 : : }
2436 : :
2437 : : /*****************/
2438 : : /* Parsing CGCU */
2439 : : /*****************/
2440 : 0 : uint16_t qbman_result_cgcu_cgid(const struct qbman_result *scn)
2441 : : {
2442 : 0 : return (uint16_t)qbman_result_SCN_rid(scn) & 0xFFFF;
2443 : : }
2444 : :
2445 : 0 : uint64_t qbman_result_cgcu_icnt(const struct qbman_result *scn)
2446 : : {
2447 : 0 : return qbman_result_SCN_ctx(scn);
2448 : : }
2449 : :
2450 : : /********************/
2451 : : /* Parsing EQ RESP */
2452 : : /********************/
2453 : 0 : struct qbman_fd *qbman_result_eqresp_fd(struct qbman_result *eqresp)
2454 : : {
2455 : 0 : return (struct qbman_fd *)&eqresp->eq_resp.fd[0];
2456 : : }
2457 : :
2458 : 0 : void qbman_result_eqresp_set_rspid(struct qbman_result *eqresp, uint8_t val)
2459 : : {
2460 : 0 : eqresp->eq_resp.rspid = val;
2461 : 0 : }
2462 : :
2463 : 0 : uint8_t qbman_result_eqresp_rspid(struct qbman_result *eqresp)
2464 : : {
2465 : 0 : return eqresp->eq_resp.rspid;
2466 : : }
2467 : :
2468 : 0 : uint8_t qbman_result_eqresp_rc(struct qbman_result *eqresp)
2469 : : {
2470 [ # # ]: 0 : if (eqresp->eq_resp.rc == 0xE)
2471 : : return 0;
2472 : : else
2473 : 0 : return -1;
2474 : : }
2475 : :
2476 : : /******************/
2477 : : /* Buffer release */
2478 : : /******************/
2479 : : #define QB_BR_RC_VALID_SHIFT 5
2480 : : #define QB_BR_RCDI_SHIFT 6
2481 : :
2482 : 0 : void qbman_release_desc_clear(struct qbman_release_desc *d)
2483 : : {
2484 : : memset(d, 0, sizeof(*d));
2485 : 0 : d->br.verb = 1 << QB_BR_RC_VALID_SHIFT;
2486 : 0 : }
2487 : :
2488 : 0 : void qbman_release_desc_set_bpid(struct qbman_release_desc *d, uint16_t bpid)
2489 : : {
2490 : 0 : d->br.bpid = bpid;
2491 : 0 : }
2492 : :
2493 : 0 : void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable)
2494 : : {
2495 [ # # ]: 0 : if (enable)
2496 : 0 : d->br.verb |= 1 << QB_BR_RCDI_SHIFT;
2497 : : else
2498 : 0 : d->br.verb &= ~(1 << QB_BR_RCDI_SHIFT);
2499 : 0 : }
2500 : :
2501 : : #define RAR_IDX(rar) ((rar) & 0x7)
2502 : : #define RAR_VB(rar) ((rar) & 0x80)
2503 : : #define RAR_SUCCESS(rar) ((rar) & 0x100)
2504 : :
2505 [ # # ]: 0 : static int qbman_swp_release_direct(struct qbman_swp *s,
2506 : : const struct qbman_release_desc *d,
2507 : : const uint64_t *buffers,
2508 : : unsigned int num_buffers)
2509 : : {
2510 : : uint32_t *p;
2511 : : const uint32_t *cl = qb_cl(d);
2512 : : uint32_t rar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_RAR);
2513 : :
2514 : : pr_debug("RAR=%08x\n", rar);
2515 [ # # ]: 0 : if (!RAR_SUCCESS(rar))
2516 : : return -EBUSY;
2517 : :
2518 : : QBMAN_BUG_ON(!num_buffers || (num_buffers > 7));
2519 : :
2520 : : /* Start the release command */
2521 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
2522 : 0 : QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
2523 : :
2524 : : /* Copy the caller's buffer pointers to the command */
2525 : 0 : u64_to_le32_copy(&p[2], buffers, num_buffers);
2526 : :
2527 : : /* Set the verb byte, have to substitute in the valid-bit and the
2528 : : * number of buffers.
2529 : : */
2530 : : lwsync();
2531 : 0 : p[0] = cl[0] | RAR_VB(rar) | num_buffers;
2532 : : qbman_cena_write_complete_wo_shadow(&s->sys,
2533 : : QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
2534 : :
2535 : 0 : return 0;
2536 : : }
2537 : :
2538 [ # # ]: 0 : static int qbman_swp_release_cinh_direct(struct qbman_swp *s,
2539 : : const struct qbman_release_desc *d,
2540 : : const uint64_t *buffers,
2541 : : unsigned int num_buffers)
2542 : : {
2543 : : uint32_t *p;
2544 : : const uint32_t *cl = qb_cl(d);
2545 : : uint32_t rar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_RAR);
2546 : :
2547 : : pr_debug("RAR=%08x\n", rar);
2548 [ # # ]: 0 : if (!RAR_SUCCESS(rar))
2549 : : return -EBUSY;
2550 : :
2551 : : QBMAN_BUG_ON(!num_buffers || (num_buffers > 7));
2552 : :
2553 : : /* Start the release command */
2554 : 0 : p = qbman_cinh_write_start_wo_shadow(&s->sys,
2555 : 0 : QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
2556 : :
2557 : : /* Copy the caller's buffer pointers to the command */
2558 : 0 : memcpy_byte_by_byte(&p[2], buffers, num_buffers * sizeof(uint64_t));
2559 : :
2560 : : /* Set the verb byte, have to substitute in the valid-bit and the
2561 : : * number of buffers.
2562 : : */
2563 : : lwsync();
2564 : 0 : p[0] = cl[0] | RAR_VB(rar) | num_buffers;
2565 : :
2566 : 0 : return 0;
2567 : : }
2568 : :
2569 [ # # ]: 0 : static int qbman_swp_release_mem_back(struct qbman_swp *s,
2570 : : const struct qbman_release_desc *d,
2571 : : const uint64_t *buffers,
2572 : : unsigned int num_buffers)
2573 : : {
2574 : : uint32_t *p;
2575 : : const uint32_t *cl = qb_cl(d);
2576 : : uint32_t rar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_RAR);
2577 : :
2578 : : pr_debug("RAR=%08x\n", rar);
2579 [ # # ]: 0 : if (!RAR_SUCCESS(rar))
2580 : : return -EBUSY;
2581 : :
2582 : : QBMAN_BUG_ON(!num_buffers || (num_buffers > 7));
2583 : :
2584 : : /* Start the release command */
2585 : 0 : p = qbman_cena_write_start_wo_shadow(&s->sys,
2586 : 0 : QBMAN_CENA_SWP_RCR_MEM(RAR_IDX(rar)));
2587 : :
2588 : : /* Copy the caller's buffer pointers to the command */
2589 : 0 : u64_to_le32_copy(&p[2], buffers, num_buffers);
2590 : :
2591 : : /* Set the verb byte, have to substitute in the valid-bit and the
2592 : : * number of buffers.
2593 : : */
2594 : 0 : p[0] = cl[0] | RAR_VB(rar) | num_buffers;
2595 : : lwsync();
2596 : 0 : qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_RCR_AM_RT +
2597 : 0 : RAR_IDX(rar) * 4, QMAN_RT_MODE);
2598 : :
2599 : 0 : return 0;
2600 : : }
2601 : :
2602 : 0 : int qbman_swp_release(struct qbman_swp *s,
2603 : : const struct qbman_release_desc *d,
2604 : : const uint64_t *buffers,
2605 : : unsigned int num_buffers)
2606 : : {
2607 [ # # ]: 0 : if (!s->stash_off)
2608 : 0 : return qbman_swp_release_ptr(s, d, buffers, num_buffers);
2609 : : else
2610 : 0 : return qbman_swp_release_cinh_direct(s, d, buffers,
2611 : : num_buffers);
2612 : : }
2613 : :
2614 : : /*******************/
2615 : : /* Buffer acquires */
2616 : : /*******************/
2617 : : struct qbman_acquire_desc {
2618 : : uint8_t verb;
2619 : : uint8_t reserved;
2620 : : uint16_t bpid;
2621 : : uint8_t num;
2622 : : uint8_t reserved2[59];
2623 : : };
2624 : :
2625 : : struct qbman_acquire_rslt {
2626 : : uint8_t verb;
2627 : : uint8_t rslt;
2628 : : uint16_t reserved;
2629 : : uint8_t num;
2630 : : uint8_t reserved2[3];
2631 : : uint64_t buf[7];
2632 : : };
2633 : :
2634 : 0 : static int qbman_swp_acquire_direct(struct qbman_swp *s, uint16_t bpid,
2635 : : uint64_t *buffers, unsigned int num_buffers)
2636 : : {
2637 : : struct qbman_acquire_desc *p;
2638 : : struct qbman_acquire_rslt *r;
2639 : :
2640 [ # # ]: 0 : if (!num_buffers || (num_buffers > 7))
2641 : : return -EINVAL;
2642 : :
2643 : : /* Start the management command */
2644 : 0 : p = qbman_swp_mc_start(s);
2645 : :
2646 [ # # ]: 0 : if (!p)
2647 : : return -EBUSY;
2648 : :
2649 : : /* Encode the caller-provided attributes */
2650 : 0 : p->bpid = bpid;
2651 : 0 : p->num = num_buffers;
2652 : :
2653 : : /* Complete the management command */
2654 : 0 : r = qbman_swp_mc_complete(s, p, QBMAN_MC_ACQUIRE);
2655 [ # # ]: 0 : if (!r) {
2656 : 0 : pr_err("qbman: acquire from BPID %d failed, no response\n",
2657 : : bpid);
2658 : 0 : return -EIO;
2659 : : }
2660 : :
2661 : : /* Decode the outcome */
2662 : : QBMAN_BUG_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_MC_ACQUIRE);
2663 : :
2664 : : /* Determine success or failure */
2665 [ # # ]: 0 : if (r->rslt != QBMAN_MC_RSLT_OK) {
2666 : 0 : pr_err("Acquire buffers from BPID 0x%x failed, code=0x%02x\n",
2667 : : bpid, r->rslt);
2668 : 0 : return -EIO;
2669 : : }
2670 : :
2671 : : QBMAN_BUG_ON(r->num > num_buffers);
2672 : :
2673 : : /* Copy the acquired buffers to the caller's array */
2674 : 0 : u64_from_le32_copy(buffers, &r->buf[0], r->num);
2675 : :
2676 : 0 : return (int)r->num;
2677 : : }
2678 : :
2679 : 0 : static int qbman_swp_acquire_cinh_direct(struct qbman_swp *s, uint16_t bpid,
2680 : : uint64_t *buffers, unsigned int num_buffers)
2681 : : {
2682 : : struct qbman_acquire_desc *p;
2683 : : struct qbman_acquire_rslt *r;
2684 : :
2685 [ # # ]: 0 : if (!num_buffers || (num_buffers > 7))
2686 : : return -EINVAL;
2687 : :
2688 : : /* Start the management command */
2689 : 0 : p = qbman_swp_mc_start(s);
2690 : :
2691 [ # # ]: 0 : if (!p)
2692 : : return -EBUSY;
2693 : :
2694 : : /* Encode the caller-provided attributes */
2695 : 0 : p->bpid = bpid;
2696 : 0 : p->num = num_buffers;
2697 : :
2698 : : /* Complete the management command */
2699 : 0 : r = qbman_swp_mc_complete_cinh(s, p, QBMAN_MC_ACQUIRE);
2700 [ # # ]: 0 : if (!r) {
2701 : 0 : pr_err("qbman: acquire from BPID %d failed, no response\n",
2702 : : bpid);
2703 : 0 : return -EIO;
2704 : : }
2705 : :
2706 : : /* Decode the outcome */
2707 : : QBMAN_BUG_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != QBMAN_MC_ACQUIRE);
2708 : :
2709 : : /* Determine success or failure */
2710 [ # # ]: 0 : if (r->rslt != QBMAN_MC_RSLT_OK) {
2711 : 0 : pr_err("Acquire buffers from BPID 0x%x failed, code=0x%02x\n",
2712 : : bpid, r->rslt);
2713 : 0 : return -EIO;
2714 : : }
2715 : :
2716 : : QBMAN_BUG_ON(r->num > num_buffers);
2717 : :
2718 : : /* Copy the acquired buffers to the caller's array */
2719 : 0 : u64_from_le32_copy(buffers, &r->buf[0], r->num);
2720 : :
2721 : 0 : return (int)r->num;
2722 : : }
2723 : :
2724 : 0 : int qbman_swp_acquire(struct qbman_swp *s, uint16_t bpid, uint64_t *buffers,
2725 : : unsigned int num_buffers)
2726 : : {
2727 [ # # ]: 0 : if (!s->stash_off)
2728 : 0 : return qbman_swp_acquire_direct(s, bpid, buffers, num_buffers);
2729 : : else
2730 : 0 : return qbman_swp_acquire_cinh_direct(s, bpid, buffers,
2731 : : num_buffers);
2732 : : }
2733 : :
2734 : : /*****************/
2735 : : /* FQ management */
2736 : : /*****************/
2737 : : struct qbman_alt_fq_state_desc {
2738 : : uint8_t verb;
2739 : : uint8_t reserved[3];
2740 : : uint32_t fqid;
2741 : : uint8_t reserved2[56];
2742 : : };
2743 : :
2744 : : struct qbman_alt_fq_state_rslt {
2745 : : uint8_t verb;
2746 : : uint8_t rslt;
2747 : : uint8_t reserved[62];
2748 : : };
2749 : :
2750 : : #define ALT_FQ_FQID_MASK 0x00FFFFFF
2751 : :
2752 : 0 : static int qbman_swp_alt_fq_state(struct qbman_swp *s, uint32_t fqid,
2753 : : uint8_t alt_fq_verb)
2754 : : {
2755 : : struct qbman_alt_fq_state_desc *p;
2756 : : struct qbman_alt_fq_state_rslt *r;
2757 : :
2758 : : /* Start the management command */
2759 : 0 : p = qbman_swp_mc_start(s);
2760 [ # # ]: 0 : if (!p)
2761 : : return -EBUSY;
2762 : :
2763 : 0 : p->fqid = fqid & ALT_FQ_FQID_MASK;
2764 : :
2765 : : /* Complete the management command */
2766 : 0 : r = qbman_swp_mc_complete(s, p, alt_fq_verb);
2767 [ # # ]: 0 : if (!r) {
2768 : 0 : pr_err("qbman: mgmt cmd failed, no response (verb=0x%x)\n",
2769 : : alt_fq_verb);
2770 : 0 : return -EIO;
2771 : : }
2772 : :
2773 : : /* Decode the outcome */
2774 : : QBMAN_BUG_ON((r->verb & QBMAN_RESPONSE_VERB_MASK) != alt_fq_verb);
2775 : :
2776 : : /* Determine success or failure */
2777 [ # # ]: 0 : if (r->rslt != QBMAN_MC_RSLT_OK) {
2778 : 0 : pr_err("ALT FQID %d failed: verb = 0x%08x, code = 0x%02x\n",
2779 : : fqid, alt_fq_verb, r->rslt);
2780 : 0 : return -EIO;
2781 : : }
2782 : :
2783 : : return 0;
2784 : : }
2785 : :
2786 : 0 : int qbman_swp_fq_schedule(struct qbman_swp *s, uint32_t fqid)
2787 : : {
2788 : 0 : return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_SCHEDULE);
2789 : : }
2790 : :
2791 : 0 : int qbman_swp_fq_force(struct qbman_swp *s, uint32_t fqid)
2792 : : {
2793 : 0 : return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_FORCE);
2794 : : }
2795 : :
2796 : 0 : int qbman_swp_fq_xon(struct qbman_swp *s, uint32_t fqid)
2797 : : {
2798 : 0 : return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XON);
2799 : : }
2800 : :
2801 : 0 : int qbman_swp_fq_xoff(struct qbman_swp *s, uint32_t fqid)
2802 : : {
2803 : 0 : return qbman_swp_alt_fq_state(s, fqid, QBMAN_FQ_XOFF);
2804 : : }
2805 : :
2806 : : /**********************/
2807 : : /* Channel management */
2808 : : /**********************/
2809 : :
2810 : : struct qbman_cdan_ctrl_desc {
2811 : : uint8_t verb;
2812 : : uint8_t reserved;
2813 : : uint16_t ch;
2814 : : uint8_t we;
2815 : : uint8_t ctrl;
2816 : : uint16_t reserved2;
2817 : : uint64_t cdan_ctx;
2818 : : uint8_t reserved3[48];
2819 : :
2820 : : };
2821 : :
2822 : : struct qbman_cdan_ctrl_rslt {
2823 : : uint8_t verb;
2824 : : uint8_t rslt;
2825 : : uint16_t ch;
2826 : : uint8_t reserved[60];
2827 : : };
2828 : :
2829 : : /* Hide "ICD" for now as we don't use it, don't set it, and don't test it, so it
2830 : : * would be irresponsible to expose it.
2831 : : */
2832 : : #define CODE_CDAN_WE_EN 0x1
2833 : : #define CODE_CDAN_WE_CTX 0x4
2834 : :
2835 : 0 : static int qbman_swp_CDAN_set(struct qbman_swp *s, uint16_t channelid,
2836 : : uint8_t we_mask, uint8_t cdan_en,
2837 : : uint64_t ctx)
2838 : : {
2839 : : struct qbman_cdan_ctrl_desc *p;
2840 : : struct qbman_cdan_ctrl_rslt *r;
2841 : :
2842 : : /* Start the management command */
2843 : 0 : p = qbman_swp_mc_start(s);
2844 [ # # ]: 0 : if (!p)
2845 : : return -EBUSY;
2846 : :
2847 : : /* Encode the caller-provided attributes */
2848 : 0 : p->ch = channelid;
2849 : 0 : p->we = we_mask;
2850 [ # # ]: 0 : if (cdan_en)
2851 : 0 : p->ctrl = 1;
2852 : : else
2853 : 0 : p->ctrl = 0;
2854 : 0 : p->cdan_ctx = ctx;
2855 : :
2856 : : /* Complete the management command */
2857 : 0 : r = qbman_swp_mc_complete(s, p, QBMAN_WQCHAN_CONFIGURE);
2858 [ # # ]: 0 : if (!r) {
2859 : 0 : pr_err("qbman: wqchan config failed, no response\n");
2860 : 0 : return -EIO;
2861 : : }
2862 : :
2863 : : /* Decode the outcome */
2864 : : QBMAN_BUG_ON((r->verb & QBMAN_RESPONSE_VERB_MASK)
2865 : : != QBMAN_WQCHAN_CONFIGURE);
2866 : :
2867 : : /* Determine success or failure */
2868 [ # # ]: 0 : if (r->rslt != QBMAN_MC_RSLT_OK) {
2869 : 0 : pr_err("CDAN cQID %d failed: code = 0x%02x\n",
2870 : : channelid, r->rslt);
2871 : 0 : return -EIO;
2872 : : }
2873 : :
2874 : : return 0;
2875 : : }
2876 : :
2877 : 0 : int qbman_swp_CDAN_set_context(struct qbman_swp *s, uint16_t channelid,
2878 : : uint64_t ctx)
2879 : : {
2880 : 0 : return qbman_swp_CDAN_set(s, channelid,
2881 : : CODE_CDAN_WE_CTX,
2882 : : 0, ctx);
2883 : : }
2884 : :
2885 : 0 : int qbman_swp_CDAN_enable(struct qbman_swp *s, uint16_t channelid)
2886 : : {
2887 : 0 : return qbman_swp_CDAN_set(s, channelid,
2888 : : CODE_CDAN_WE_EN,
2889 : : 1, 0);
2890 : : }
2891 : :
2892 : 0 : int qbman_swp_CDAN_disable(struct qbman_swp *s, uint16_t channelid)
2893 : : {
2894 : 0 : return qbman_swp_CDAN_set(s, channelid,
2895 : : CODE_CDAN_WE_EN,
2896 : : 0, 0);
2897 : : }
2898 : :
2899 : 0 : int qbman_swp_CDAN_set_context_enable(struct qbman_swp *s, uint16_t channelid,
2900 : : uint64_t ctx)
2901 : : {
2902 : 0 : return qbman_swp_CDAN_set(s, channelid,
2903 : : CODE_CDAN_WE_EN | CODE_CDAN_WE_CTX,
2904 : : 1, ctx);
2905 : : }
2906 : :
2907 : 0 : uint8_t qbman_get_dqrr_idx(const struct qbman_result *dqrr)
2908 : : {
2909 : 0 : return QBMAN_IDX_FROM_DQRR(dqrr);
2910 : : }
2911 : :
2912 : 0 : struct qbman_result *qbman_get_dqrr_from_idx(struct qbman_swp *s, uint8_t idx)
2913 : : {
2914 : : struct qbman_result *dq;
2915 : :
2916 : 0 : dq = qbman_cena_read(&s->sys, QBMAN_CENA_SWP_DQRR(idx));
2917 : 0 : return dq;
2918 : : }
|