1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright © 2021-2022 Dmitry Salychev
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 /*
30 * The DPAA2 Resource Container (DPRC) bus driver.
31 *
32 * DPRC holds all the resources and object information that a software context
33 * (kernel, virtual machine, etc.) can access or use.
34 */
35
36 #include <sys/param.h>
37 #include <sys/kernel.h>
38 #include <sys/bus.h>
39 #include <sys/rman.h>
40 #include <sys/module.h>
41 #include <sys/malloc.h>
42 #include <sys/mutex.h>
43 #include <sys/condvar.h>
44 #include <sys/lock.h>
45 #include <sys/time.h>
46 #include <sys/types.h>
47 #include <sys/systm.h>
48 #include <sys/smp.h>
49
50 #include <machine/bus.h>
51 #include <machine/resource.h>
52
53 #include "pcib_if.h"
54 #include "pci_if.h"
55
56 #include "dpaa2_mcp.h"
57 #include "dpaa2_mc.h"
58 #include "dpaa2_ni.h"
59 #include "dpaa2_mc_if.h"
60 #include "dpaa2_cmd_if.h"
61
62 /* Timeouts to wait for a command response from MC. */
63 #define CMD_SPIN_TIMEOUT 100u /* us */
64 #define CMD_SPIN_ATTEMPTS 2000u /* max. 200 ms */
65
66 #define TYPE_LEN_MAX 16u
67 #define LABEL_LEN_MAX 16u
68
69 MALLOC_DEFINE(M_DPAA2_RC, "dpaa2_rc", "DPAA2 Resource Container");
70
71 /* Discover and add devices to the resource container. */
72 static int dpaa2_rc_discover(struct dpaa2_rc_softc *);
73 static int dpaa2_rc_add_child(struct dpaa2_rc_softc *, struct dpaa2_cmd *,
74 struct dpaa2_obj *);
75 static int dpaa2_rc_add_managed_child(struct dpaa2_rc_softc *,
76 struct dpaa2_cmd *, struct dpaa2_obj *);
77
78 /* Helper routines. */
79 static int dpaa2_rc_enable_irq(struct dpaa2_mcp *, struct dpaa2_cmd *, uint8_t,
80 bool, uint16_t);
81 static int dpaa2_rc_configure_irq(device_t, device_t, int, uint64_t, uint32_t);
82 static int dpaa2_rc_add_res(device_t, device_t, enum dpaa2_dev_type, int *, int);
83 static int dpaa2_rc_print_type(struct resource_list *, enum dpaa2_dev_type);
84 static struct dpaa2_mcp *dpaa2_rc_select_portal(device_t, device_t);
85
86 /* Routines to send commands to MC. */
87 static int dpaa2_rc_exec_cmd(struct dpaa2_mcp *, struct dpaa2_cmd *, uint16_t);
88 static int dpaa2_rc_send_cmd(struct dpaa2_mcp *, struct dpaa2_cmd *);
89 static int dpaa2_rc_wait_for_cmd(struct dpaa2_mcp *, struct dpaa2_cmd *);
90 static int dpaa2_rc_reset_cmd_params(struct dpaa2_cmd *);
91
92 static int
dpaa2_rc_probe(device_t dev)93 dpaa2_rc_probe(device_t dev)
94 {
95 /* DPRC device will be added by the parent DPRC or MC bus itself. */
96 device_set_desc(dev, "DPAA2 Resource Container");
97 return (BUS_PROBE_DEFAULT);
98 }
99
100 static int
dpaa2_rc_detach(device_t dev)101 dpaa2_rc_detach(device_t dev)
102 {
103 struct dpaa2_devinfo *dinfo;
104 int error;
105
106 error = bus_generic_detach(dev);
107 if (error)
108 return (error);
109
110 dinfo = device_get_ivars(dev);
111
112 if (dinfo->portal)
113 dpaa2_mcp_free_portal(dinfo->portal);
114 if (dinfo)
115 free(dinfo, M_DPAA2_RC);
116
117 return (device_delete_children(dev));
118 }
119
120 static int
dpaa2_rc_attach(device_t dev)121 dpaa2_rc_attach(device_t dev)
122 {
123 device_t pdev;
124 struct dpaa2_mc_softc *mcsc;
125 struct dpaa2_rc_softc *sc;
126 struct dpaa2_devinfo *dinfo = NULL;
127 int error;
128
129 sc = device_get_softc(dev);
130 sc->dev = dev;
131 sc->unit = device_get_unit(dev);
132
133 if (sc->unit == 0) {
134 /* Root DPRC should be attached directly to the MC bus. */
135 pdev = device_get_parent(dev);
136 mcsc = device_get_softc(pdev);
137
138 KASSERT(strcmp(device_get_name(pdev), "dpaa2_mc") == 0,
139 ("root DPRC should be attached to the MC bus"));
140
141 /*
142 * Allocate devinfo to let the parent MC bus access ICID of the
143 * DPRC object.
144 */
145 dinfo = malloc(sizeof(struct dpaa2_devinfo), M_DPAA2_RC,
146 M_WAITOK | M_ZERO);
147 if (!dinfo) {
148 device_printf(dev, "%s: failed to allocate "
149 "dpaa2_devinfo\n", __func__);
150 dpaa2_rc_detach(dev);
151 return (ENXIO);
152 }
153 device_set_ivars(dev, dinfo);
154
155 dinfo->pdev = pdev;
156 dinfo->dev = dev;
157 dinfo->dtype = DPAA2_DEV_RC;
158 dinfo->portal = NULL;
159
160 /* Prepare helper portal object to send commands to MC. */
161 error = dpaa2_mcp_init_portal(&dinfo->portal, mcsc->res[0],
162 &mcsc->map[0], DPAA2_PORTAL_DEF);
163 if (error) {
164 device_printf(dev, "%s: failed to initialize dpaa2_mcp: "
165 "error=%d\n", __func__, error);
166 dpaa2_rc_detach(dev);
167 return (ENXIO);
168 }
169 } else {
170 /* TODO: Child DPRCs aren't supported yet. */
171 return (ENXIO);
172 }
173
174 /* Create DPAA2 devices for objects in this container. */
175 error = dpaa2_rc_discover(sc);
176 if (error) {
177 device_printf(dev, "%s: failed to discover objects in "
178 "container: error=%d\n", __func__, error);
179 dpaa2_rc_detach(dev);
180 return (error);
181 }
182
183 return (0);
184 }
185
186 /*
187 * Bus interface.
188 */
189
190 static struct resource_list *
dpaa2_rc_get_resource_list(device_t rcdev,device_t child)191 dpaa2_rc_get_resource_list(device_t rcdev, device_t child)
192 {
193 struct dpaa2_devinfo *dinfo = device_get_ivars(child);
194
195 return (&dinfo->resources);
196 }
197
198 static void
dpaa2_rc_delete_resource(device_t rcdev,device_t child,int type,int rid)199 dpaa2_rc_delete_resource(device_t rcdev, device_t child, int type, int rid)
200 {
201 struct resource_list *rl;
202 struct resource_list_entry *rle;
203 struct dpaa2_devinfo *dinfo;
204
205 if (device_get_parent(child) != rcdev)
206 return;
207
208 dinfo = device_get_ivars(child);
209 rl = &dinfo->resources;
210 rle = resource_list_find(rl, type, rid);
211 if (rle == NULL)
212 return;
213
214 if (rle->res) {
215 if (rman_get_flags(rle->res) & RF_ACTIVE ||
216 resource_list_busy(rl, type, rid)) {
217 device_printf(rcdev, "%s: resource still owned by "
218 "child: type=%d, rid=%d, start=%jx\n", __func__,
219 type, rid, rman_get_start(rle->res));
220 return;
221 }
222 resource_list_unreserve(rl, rcdev, child, type, rid);
223 }
224 resource_list_delete(rl, type, rid);
225 }
226
227 static struct resource *
dpaa2_rc_alloc_multi_resource(device_t rcdev,device_t child,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)228 dpaa2_rc_alloc_multi_resource(device_t rcdev, device_t child, int type, int *rid,
229 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
230 {
231 struct resource_list *rl;
232 struct dpaa2_devinfo *dinfo;
233
234 dinfo = device_get_ivars(child);
235 rl = &dinfo->resources;
236
237 /*
238 * By default, software portal interrupts are message-based, that is,
239 * they are issued from QMan using a 4 byte write.
240 *
241 * TODO: However this default behavior can be changed by programming one
242 * or more software portals to issue their interrupts via a
243 * dedicated software portal interrupt wire.
244 * See registers SWP_INTW0_CFG to SWP_INTW3_CFG for details.
245 */
246 if (type == SYS_RES_IRQ && *rid == 0)
247 return (NULL);
248
249 return (resource_list_alloc(rl, rcdev, child, type, rid,
250 start, end, count, flags));
251 }
252
253 static struct resource *
dpaa2_rc_alloc_resource(device_t rcdev,device_t child,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)254 dpaa2_rc_alloc_resource(device_t rcdev, device_t child, int type, int *rid,
255 rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
256 {
257 if (device_get_parent(child) != rcdev)
258 return (BUS_ALLOC_RESOURCE(device_get_parent(rcdev), child,
259 type, rid, start, end, count, flags));
260
261 return (dpaa2_rc_alloc_multi_resource(rcdev, child, type, rid, start,
262 end, count, flags));
263 }
264
265 static int
dpaa2_rc_release_resource(device_t rcdev,device_t child,int type,int rid,struct resource * r)266 dpaa2_rc_release_resource(device_t rcdev, device_t child, int type, int rid,
267 struct resource *r)
268 {
269 struct resource_list *rl;
270 struct dpaa2_devinfo *dinfo;
271
272 if (device_get_parent(child) != rcdev)
273 return (BUS_RELEASE_RESOURCE(device_get_parent(rcdev), child,
274 type, rid, r));
275
276 dinfo = device_get_ivars(child);
277 rl = &dinfo->resources;
278 return (resource_list_release(rl, rcdev, child, type, rid, r));
279 }
280
281 static void
dpaa2_rc_child_deleted(device_t rcdev,device_t child)282 dpaa2_rc_child_deleted(device_t rcdev, device_t child)
283 {
284 struct dpaa2_devinfo *dinfo;
285 struct resource_list *rl;
286 struct resource_list_entry *rle;
287
288 dinfo = device_get_ivars(child);
289 rl = &dinfo->resources;
290
291 /* Free all allocated resources */
292 STAILQ_FOREACH(rle, rl, link) {
293 if (rle->res) {
294 if (rman_get_flags(rle->res) & RF_ACTIVE ||
295 resource_list_busy(rl, rle->type, rle->rid)) {
296 device_printf(child, "%s: resource still owned: "
297 "type=%d, rid=%d, addr=%lx\n", __func__,
298 rle->type, rle->rid,
299 rman_get_start(rle->res));
300 bus_release_resource(child, rle->type, rle->rid,
301 rle->res);
302 }
303 resource_list_unreserve(rl, rcdev, child, rle->type,
304 rle->rid);
305 }
306 }
307 resource_list_free(rl);
308
309 if (dinfo)
310 free(dinfo, M_DPAA2_RC);
311 }
312
313 static void
dpaa2_rc_child_detached(device_t rcdev,device_t child)314 dpaa2_rc_child_detached(device_t rcdev, device_t child)
315 {
316 struct dpaa2_devinfo *dinfo;
317 struct resource_list *rl;
318
319 dinfo = device_get_ivars(child);
320 rl = &dinfo->resources;
321
322 if (resource_list_release_active(rl, rcdev, child, SYS_RES_IRQ) != 0)
323 device_printf(child, "%s: leaked IRQ resources!\n", __func__);
324 if (dinfo->msi.msi_alloc != 0) {
325 device_printf(child, "%s: leaked %d MSI vectors!\n", __func__,
326 dinfo->msi.msi_alloc);
327 PCI_RELEASE_MSI(rcdev, child);
328 }
329 if (resource_list_release_active(rl, rcdev, child, SYS_RES_MEMORY) != 0)
330 device_printf(child, "%s: leaked memory resources!\n", __func__);
331 }
332
333 static int
dpaa2_rc_setup_intr(device_t rcdev,device_t child,struct resource * irq,int flags,driver_filter_t * filter,driver_intr_t * intr,void * arg,void ** cookiep)334 dpaa2_rc_setup_intr(device_t rcdev, device_t child, struct resource *irq,
335 int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
336 void **cookiep)
337 {
338 struct dpaa2_devinfo *dinfo;
339 uint64_t addr;
340 uint32_t data;
341 void *cookie;
342 int error, rid;
343
344 error = bus_generic_setup_intr(rcdev, child, irq, flags, filter, intr,
345 arg, &cookie);
346 if (error) {
347 device_printf(rcdev, "%s: bus_generic_setup_intr() failed: "
348 "error=%d\n", __func__, error);
349 return (error);
350 }
351
352 /* If this is not a direct child, just bail out. */
353 if (device_get_parent(child) != rcdev) {
354 *cookiep = cookie;
355 return (0);
356 }
357
358 rid = rman_get_rid(irq);
359 if (rid == 0) {
360 if (bootverbose)
361 device_printf(rcdev, "%s: cannot setup interrupt with "
362 "rid=0: INTx are not supported by DPAA2 objects "
363 "yet\n", __func__);
364 return (EINVAL);
365 } else {
366 dinfo = device_get_ivars(child);
367 KASSERT(dinfo->msi.msi_alloc > 0,
368 ("No MSI interrupts allocated"));
369
370 /*
371 * Ask our parent to map the MSI and give us the address and
372 * data register values. If we fail for some reason, teardown
373 * the interrupt handler.
374 */
375 error = PCIB_MAP_MSI(device_get_parent(rcdev), child,
376 rman_get_start(irq), &addr, &data);
377 if (error) {
378 device_printf(rcdev, "%s: PCIB_MAP_MSI failed: "
379 "error=%d\n", __func__, error);
380 (void)bus_generic_teardown_intr(rcdev, child, irq,
381 cookie);
382 return (error);
383 }
384
385 /* Configure MSI for this DPAA2 object. */
386 error = dpaa2_rc_configure_irq(rcdev, child, rid, addr, data);
387 if (error) {
388 device_printf(rcdev, "%s: failed to configure IRQ for "
389 "DPAA2 object: rid=%d, type=%s, unit=%d\n", __func__,
390 rid, dpaa2_ttos(dinfo->dtype),
391 device_get_unit(child));
392 return (error);
393 }
394 dinfo->msi.msi_handlers++;
395 }
396 *cookiep = cookie;
397 return (0);
398 }
399
400 static int
dpaa2_rc_teardown_intr(device_t rcdev,device_t child,struct resource * irq,void * cookie)401 dpaa2_rc_teardown_intr(device_t rcdev, device_t child, struct resource *irq,
402 void *cookie)
403 {
404 struct resource_list_entry *rle;
405 struct dpaa2_devinfo *dinfo;
406 int error, rid;
407
408 if (irq == NULL || !(rman_get_flags(irq) & RF_ACTIVE))
409 return (EINVAL);
410
411 /* If this isn't a direct child, just bail out */
412 if (device_get_parent(child) != rcdev)
413 return(bus_generic_teardown_intr(rcdev, child, irq, cookie));
414
415 rid = rman_get_rid(irq);
416 if (rid == 0) {
417 if (bootverbose)
418 device_printf(rcdev, "%s: cannot teardown interrupt "
419 "with rid=0: INTx are not supported by DPAA2 "
420 "objects yet\n", __func__);
421 return (EINVAL);
422 } else {
423 dinfo = device_get_ivars(child);
424 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, rid);
425 if (rle->res != irq)
426 return (EINVAL);
427 dinfo->msi.msi_handlers--;
428 }
429
430 error = bus_generic_teardown_intr(rcdev, child, irq, cookie);
431 if (rid > 0)
432 KASSERT(error == 0,
433 ("%s: generic teardown failed for MSI", __func__));
434 return (error);
435 }
436
437 static int
dpaa2_rc_print_child(device_t rcdev,device_t child)438 dpaa2_rc_print_child(device_t rcdev, device_t child)
439 {
440 struct dpaa2_devinfo *dinfo = device_get_ivars(child);
441 struct resource_list *rl = &dinfo->resources;
442 int retval = 0;
443
444 retval += bus_print_child_header(rcdev, child);
445
446 retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#jx");
447 retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#jx");
448 retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%jd");
449
450 /* Print DPAA2-specific resources. */
451 retval += dpaa2_rc_print_type(rl, DPAA2_DEV_IO);
452 retval += dpaa2_rc_print_type(rl, DPAA2_DEV_BP);
453 retval += dpaa2_rc_print_type(rl, DPAA2_DEV_CON);
454 retval += dpaa2_rc_print_type(rl, DPAA2_DEV_MCP);
455
456 retval += printf(" at %s (id=%u)", dpaa2_ttos(dinfo->dtype), dinfo->id);
457
458 retval += bus_print_child_domain(rcdev, child);
459 retval += bus_print_child_footer(rcdev, child);
460
461 return (retval);
462 }
463
464 /*
465 * Pseudo-PCI interface.
466 */
467
468 /*
469 * Attempt to allocate *count MSI messages. The actual number allocated is
470 * returned in *count. After this function returns, each message will be
471 * available to the driver as SYS_RES_IRQ resources starting at a rid 1.
472 *
473 * NOTE: Implementation is similar to sys/dev/pci/pci.c.
474 */
475 static int
dpaa2_rc_alloc_msi(device_t rcdev,device_t child,int * count)476 dpaa2_rc_alloc_msi(device_t rcdev, device_t child, int *count)
477 {
478 struct dpaa2_devinfo *rcinfo = device_get_ivars(rcdev);
479 struct dpaa2_devinfo *dinfo = device_get_ivars(child);
480 int error, actual, i, run, irqs[32];
481
482 /* Don't let count == 0 get us into trouble. */
483 if (*count == 0)
484 return (EINVAL);
485
486 /* MSI should be allocated by the resource container. */
487 if (rcinfo->dtype != DPAA2_DEV_RC)
488 return (ENODEV);
489
490 /* Already have allocated messages? */
491 if (dinfo->msi.msi_alloc != 0)
492 return (ENXIO);
493
494 /* Don't ask for more than the device supports. */
495 actual = min(*count, dinfo->msi.msi_msgnum);
496
497 /* Don't ask for more than 32 messages. */
498 actual = min(actual, 32);
499
500 /* MSI requires power of 2 number of messages. */
501 if (!powerof2(actual))
502 return (EINVAL);
503
504 for (;;) {
505 /* Try to allocate N messages. */
506 error = PCIB_ALLOC_MSI(device_get_parent(rcdev), child, actual,
507 actual, irqs);
508 if (error == 0)
509 break;
510 if (actual == 1)
511 return (error);
512
513 /* Try N / 2. */
514 actual >>= 1;
515 }
516
517 /*
518 * We now have N actual messages mapped onto SYS_RES_IRQ resources in
519 * the irqs[] array, so add new resources starting at rid 1.
520 */
521 for (i = 0; i < actual; i++)
522 resource_list_add(&dinfo->resources, SYS_RES_IRQ, i + 1,
523 irqs[i], irqs[i], 1);
524
525 if (bootverbose) {
526 if (actual == 1) {
527 device_printf(child, "using IRQ %d for MSI\n", irqs[0]);
528 } else {
529 /*
530 * Be fancy and try to print contiguous runs
531 * of IRQ values as ranges. 'run' is true if
532 * we are in a range.
533 */
534 device_printf(child, "using IRQs %d", irqs[0]);
535 run = 0;
536 for (i = 1; i < actual; i++) {
537 /* Still in a run? */
538 if (irqs[i] == irqs[i - 1] + 1) {
539 run = 1;
540 continue;
541 }
542
543 /* Finish previous range. */
544 if (run) {
545 printf("-%d", irqs[i - 1]);
546 run = 0;
547 }
548
549 /* Start new range. */
550 printf(",%d", irqs[i]);
551 }
552
553 /* Unfinished range? */
554 if (run)
555 printf("-%d", irqs[actual - 1]);
556 printf(" for MSI\n");
557 }
558 }
559
560 /* Update counts of alloc'd messages. */
561 dinfo->msi.msi_alloc = actual;
562 dinfo->msi.msi_handlers = 0;
563 *count = actual;
564 return (0);
565 }
566
567 /*
568 * Release the MSI messages associated with this DPAA2 device.
569 *
570 * NOTE: Implementation is similar to sys/dev/pci/pci.c.
571 */
572 static int
dpaa2_rc_release_msi(device_t rcdev,device_t child)573 dpaa2_rc_release_msi(device_t rcdev, device_t child)
574 {
575 struct dpaa2_devinfo *rcinfo = device_get_ivars(rcdev);
576 struct dpaa2_devinfo *dinfo = device_get_ivars(child);
577 struct resource_list_entry *rle;
578 int i, irqs[32];
579
580 /* MSI should be released by the resource container. */
581 if (rcinfo->dtype != DPAA2_DEV_RC)
582 return (ENODEV);
583
584 /* Do we have any messages to release? */
585 if (dinfo->msi.msi_alloc == 0)
586 return (ENODEV);
587 KASSERT(dinfo->msi.msi_alloc <= 32,
588 ("more than 32 alloc'd MSI messages"));
589
590 /* Make sure none of the resources are allocated. */
591 if (dinfo->msi.msi_handlers > 0)
592 return (EBUSY);
593 for (i = 0; i < dinfo->msi.msi_alloc; i++) {
594 rle = resource_list_find(&dinfo->resources, SYS_RES_IRQ, i + 1);
595 KASSERT(rle != NULL, ("missing MSI resource"));
596 if (rle->res != NULL)
597 return (EBUSY);
598 irqs[i] = rle->start;
599 }
600
601 /* Release the messages. */
602 PCIB_RELEASE_MSI(device_get_parent(rcdev), child, dinfo->msi.msi_alloc,
603 irqs);
604 for (i = 0; i < dinfo->msi.msi_alloc; i++)
605 resource_list_delete(&dinfo->resources, SYS_RES_IRQ, i + 1);
606
607 /* Update alloc count. */
608 dinfo->msi.msi_alloc = 0;
609 return (0);
610 }
611
612 /**
613 * @brief Return the maximum number of the MSI supported by this DPAA2 device.
614 */
615 static int
dpaa2_rc_msi_count(device_t rcdev,device_t child)616 dpaa2_rc_msi_count(device_t rcdev, device_t child)
617 {
618 struct dpaa2_devinfo *dinfo = device_get_ivars(child);
619
620 return (dinfo->msi.msi_msgnum);
621 }
622
623 static int
dpaa2_rc_get_id(device_t rcdev,device_t child,enum pci_id_type type,uintptr_t * id)624 dpaa2_rc_get_id(device_t rcdev, device_t child, enum pci_id_type type,
625 uintptr_t *id)
626 {
627 struct dpaa2_devinfo *rcinfo = device_get_ivars(rcdev);
628
629 if (rcinfo->dtype != DPAA2_DEV_RC)
630 return (ENODEV);
631
632 return (PCIB_GET_ID(device_get_parent(rcdev), child, type, id));
633 }
634
635 /*
636 * DPAA2 MC command interface.
637 */
638
639 static int
dpaa2_rc_mng_get_version(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t * major,uint32_t * minor,uint32_t * rev)640 dpaa2_rc_mng_get_version(device_t dev, device_t child, struct dpaa2_cmd *cmd,
641 uint32_t *major, uint32_t *minor, uint32_t *rev)
642 {
643 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
644 int error;
645
646 if (portal == NULL || cmd == NULL || major == NULL || minor == NULL ||
647 rev == NULL)
648 return (DPAA2_CMD_STAT_ERR);
649
650 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MNG_GET_VER);
651 if (!error) {
652 *major = cmd->params[0] >> 32;
653 *minor = cmd->params[1] & 0xFFFFFFFF;
654 *rev = cmd->params[0] & 0xFFFFFFFF;
655 }
656
657 return (error);
658 }
659
660 static int
dpaa2_rc_mng_get_soc_version(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t * pvr,uint32_t * svr)661 dpaa2_rc_mng_get_soc_version(device_t dev, device_t child, struct dpaa2_cmd *cmd,
662 uint32_t *pvr, uint32_t *svr)
663 {
664 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
665 int error;
666
667 if (portal == NULL || cmd == NULL || pvr == NULL || svr == NULL)
668 return (DPAA2_CMD_STAT_ERR);
669
670 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MNG_GET_SOC_VER);
671 if (!error) {
672 *pvr = cmd->params[0] >> 32;
673 *svr = cmd->params[0] & 0xFFFFFFFF;
674 }
675
676 return (error);
677 }
678
679 static int
dpaa2_rc_mng_get_container_id(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t * cont_id)680 dpaa2_rc_mng_get_container_id(device_t dev, device_t child,
681 struct dpaa2_cmd *cmd, uint32_t *cont_id)
682 {
683 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
684 int error;
685
686 if (portal == NULL || cmd == NULL || cont_id == NULL)
687 return (DPAA2_CMD_STAT_ERR);
688
689 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MNG_GET_CONT_ID);
690 if (!error)
691 *cont_id = cmd->params[0] & 0xFFFFFFFF;
692
693 return (error);
694 }
695
696 static int
dpaa2_rc_open(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t cont_id,uint16_t * token)697 dpaa2_rc_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
698 uint32_t cont_id, uint16_t *token)
699 {
700 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
701 struct dpaa2_cmd_header *hdr;
702 int error;
703
704 if (portal == NULL || cmd == NULL || token == NULL)
705 return (DPAA2_CMD_STAT_ERR);
706
707 cmd->params[0] = cont_id;
708
709 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_OPEN);
710 if (!error) {
711 hdr = (struct dpaa2_cmd_header *) &cmd->header;
712 *token = hdr->token;
713 }
714
715 return (error);
716 }
717
718 static int
dpaa2_rc_close(device_t dev,device_t child,struct dpaa2_cmd * cmd)719 dpaa2_rc_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
720 {
721 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
722
723 if (portal == NULL || cmd == NULL)
724 return (DPAA2_CMD_STAT_ERR);
725
726 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_CLOSE));
727 }
728
729 static int
dpaa2_rc_get_obj_count(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t * obj_count)730 dpaa2_rc_get_obj_count(device_t dev, device_t child, struct dpaa2_cmd *cmd,
731 uint32_t *obj_count)
732 {
733 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
734 int error;
735
736 if (portal == NULL || cmd == NULL || obj_count == NULL)
737 return (DPAA2_CMD_STAT_ERR);
738
739 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_OBJ_COUNT);
740 if (!error)
741 *obj_count = (uint32_t)(cmd->params[0] >> 32);
742
743 return (error);
744 }
745
746 static int
dpaa2_rc_get_obj(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t obj_idx,struct dpaa2_obj * obj)747 dpaa2_rc_get_obj(device_t dev, device_t child, struct dpaa2_cmd *cmd,
748 uint32_t obj_idx, struct dpaa2_obj *obj)
749 {
750 struct __packed dpaa2_obj_resp {
751 uint32_t _reserved1;
752 uint32_t id;
753 uint16_t vendor;
754 uint8_t irq_count;
755 uint8_t reg_count;
756 uint32_t state;
757 uint16_t ver_major;
758 uint16_t ver_minor;
759 uint16_t flags;
760 uint16_t _reserved2;
761 uint8_t type[16];
762 uint8_t label[16];
763 } *pobj;
764 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
765 int error;
766
767 if (portal == NULL || cmd == NULL || obj == NULL)
768 return (DPAA2_CMD_STAT_ERR);
769
770 cmd->params[0] = obj_idx;
771
772 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_OBJ);
773 if (!error) {
774 pobj = (struct dpaa2_obj_resp *) &cmd->params[0];
775 obj->id = pobj->id;
776 obj->vendor = pobj->vendor;
777 obj->irq_count = pobj->irq_count;
778 obj->reg_count = pobj->reg_count;
779 obj->state = pobj->state;
780 obj->ver_major = pobj->ver_major;
781 obj->ver_minor = pobj->ver_minor;
782 obj->flags = pobj->flags;
783 obj->type = dpaa2_stot((const char *) pobj->type);
784 memcpy(obj->label, pobj->label, sizeof(pobj->label));
785 }
786
787 /* Some DPAA2 objects might not be supported by the driver yet. */
788 if (obj->type == DPAA2_DEV_NOTYPE)
789 error = DPAA2_CMD_STAT_UNKNOWN_OBJ;
790
791 return (error);
792 }
793
794 static int
dpaa2_rc_get_obj_descriptor(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t obj_id,enum dpaa2_dev_type dtype,struct dpaa2_obj * obj)795 dpaa2_rc_get_obj_descriptor(device_t dev, device_t child,
796 struct dpaa2_cmd *cmd, uint32_t obj_id, enum dpaa2_dev_type dtype,
797 struct dpaa2_obj *obj)
798 {
799 struct __packed get_obj_desc_args {
800 uint32_t obj_id;
801 uint32_t _reserved1;
802 uint8_t type[16];
803 } *args;
804 struct __packed dpaa2_obj_resp {
805 uint32_t _reserved1;
806 uint32_t id;
807 uint16_t vendor;
808 uint8_t irq_count;
809 uint8_t reg_count;
810 uint32_t state;
811 uint16_t ver_major;
812 uint16_t ver_minor;
813 uint16_t flags;
814 uint16_t _reserved2;
815 uint8_t type[16];
816 uint8_t label[16];
817 } *pobj;
818 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
819 const char *type = dpaa2_ttos(dtype);
820 int error;
821
822 if (portal == NULL || cmd == NULL || obj == NULL)
823 return (DPAA2_CMD_STAT_ERR);
824
825 args = (struct get_obj_desc_args *) &cmd->params[0];
826 args->obj_id = obj_id;
827 memcpy(args->type, type, min(strlen(type) + 1, TYPE_LEN_MAX));
828
829 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_OBJ_DESC);
830 if (!error) {
831 pobj = (struct dpaa2_obj_resp *) &cmd->params[0];
832 obj->id = pobj->id;
833 obj->vendor = pobj->vendor;
834 obj->irq_count = pobj->irq_count;
835 obj->reg_count = pobj->reg_count;
836 obj->state = pobj->state;
837 obj->ver_major = pobj->ver_major;
838 obj->ver_minor = pobj->ver_minor;
839 obj->flags = pobj->flags;
840 obj->type = dpaa2_stot((const char *) pobj->type);
841 memcpy(obj->label, pobj->label, sizeof(pobj->label));
842 }
843
844 /* Some DPAA2 objects might not be supported by the driver yet. */
845 if (obj->type == DPAA2_DEV_NOTYPE)
846 error = DPAA2_CMD_STAT_UNKNOWN_OBJ;
847
848 return (error);
849 }
850
851 static int
dpaa2_rc_get_attributes(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_rc_attr * attr)852 dpaa2_rc_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
853 struct dpaa2_rc_attr *attr)
854 {
855 struct __packed dpaa2_rc_attr {
856 uint32_t cont_id;
857 uint32_t icid;
858 uint32_t options;
859 uint32_t portal_id;
860 } *pattr;
861 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
862 int error;
863
864 if (portal == NULL || cmd == NULL || attr == NULL)
865 return (DPAA2_CMD_STAT_ERR);
866
867 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_ATTR);
868 if (!error) {
869 pattr = (struct dpaa2_rc_attr *) &cmd->params[0];
870 attr->cont_id = pattr->cont_id;
871 attr->portal_id = pattr->portal_id;
872 attr->options = pattr->options;
873 attr->icid = pattr->icid;
874 }
875
876 return (error);
877 }
878
879 static int
dpaa2_rc_get_obj_region(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t obj_id,uint8_t reg_idx,enum dpaa2_dev_type dtype,struct dpaa2_rc_obj_region * reg)880 dpaa2_rc_get_obj_region(device_t dev, device_t child, struct dpaa2_cmd *cmd,
881 uint32_t obj_id, uint8_t reg_idx, enum dpaa2_dev_type dtype,
882 struct dpaa2_rc_obj_region *reg)
883 {
884 struct __packed obj_region_args {
885 uint32_t obj_id;
886 uint16_t _reserved1;
887 uint8_t reg_idx;
888 uint8_t _reserved2;
889 uint64_t _reserved3;
890 uint64_t _reserved4;
891 uint8_t type[16];
892 } *args;
893 struct __packed obj_region {
894 uint64_t _reserved1;
895 uint64_t base_offset;
896 uint32_t size;
897 uint32_t type;
898 uint32_t flags;
899 uint32_t _reserved2;
900 uint64_t base_paddr;
901 } *resp;
902 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
903 uint16_t cmdid, api_major, api_minor;
904 const char *type = dpaa2_ttos(dtype);
905 int error;
906
907 if (portal == NULL || cmd == NULL || reg == NULL)
908 return (DPAA2_CMD_STAT_ERR);
909
910 /*
911 * If the DPRC object version was not yet cached, cache it now.
912 * Otherwise use the already cached value.
913 */
914 if (!portal->rc_api_major && !portal->rc_api_minor) {
915 error = DPAA2_CMD_RC_GET_API_VERSION(dev, child, cmd,
916 &api_major, &api_minor);
917 if (error)
918 return (error);
919 portal->rc_api_major = api_major;
920 portal->rc_api_minor = api_minor;
921 } else {
922 api_major = portal->rc_api_major;
923 api_minor = portal->rc_api_minor;
924 }
925
926 /* TODO: Remove magic numbers. */
927 if (api_major > 6u || (api_major == 6u && api_minor >= 6u))
928 /*
929 * MC API version 6.6 changed the size of the MC portals and
930 * software portals to 64K (as implemented by hardware).
931 */
932 cmdid = CMDID_RC_GET_OBJ_REG_V3;
933 else if (api_major == 6u && api_minor >= 3u)
934 /*
935 * MC API version 6.3 introduced a new field to the region
936 * descriptor: base_address.
937 */
938 cmdid = CMDID_RC_GET_OBJ_REG_V2;
939 else
940 cmdid = CMDID_RC_GET_OBJ_REG;
941
942 args = (struct obj_region_args *) &cmd->params[0];
943 args->obj_id = obj_id;
944 args->reg_idx = reg_idx;
945 memcpy(args->type, type, min(strlen(type) + 1, TYPE_LEN_MAX));
946
947 error = dpaa2_rc_exec_cmd(portal, cmd, cmdid);
948 if (!error) {
949 resp = (struct obj_region *) &cmd->params[0];
950 reg->base_paddr = resp->base_paddr;
951 reg->base_offset = resp->base_offset;
952 reg->size = resp->size;
953 reg->flags = resp->flags;
954 reg->type = resp->type & 0xFu;
955 }
956
957 return (error);
958 }
959
960 static int
dpaa2_rc_get_api_version(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint16_t * major,uint16_t * minor)961 dpaa2_rc_get_api_version(device_t dev, device_t child, struct dpaa2_cmd *cmd,
962 uint16_t *major, uint16_t *minor)
963 {
964 struct __packed rc_api_version {
965 uint16_t major;
966 uint16_t minor;
967 } *resp;
968 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
969 int error;
970
971 if (portal == NULL || cmd == NULL || major == NULL || minor == NULL)
972 return (DPAA2_CMD_STAT_ERR);
973
974 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_API_VERSION);
975 if (!error) {
976 resp = (struct rc_api_version *) &cmd->params[0];
977 *major = resp->major;
978 *minor = resp->minor;
979 }
980
981 return (error);
982 }
983
984 static int
dpaa2_rc_set_irq_enable(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t irq_idx,uint8_t enable)985 dpaa2_rc_set_irq_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd,
986 uint8_t irq_idx, uint8_t enable)
987 {
988 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
989
990 if (portal == NULL || cmd == NULL)
991 return (DPAA2_CMD_STAT_ERR);
992
993 return (dpaa2_rc_enable_irq(portal, cmd, irq_idx, enable,
994 CMDID_RC_SET_IRQ_ENABLE));
995 }
996
997 static int
dpaa2_rc_set_obj_irq(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t irq_idx,uint64_t addr,uint32_t data,uint32_t irq_usr,uint32_t obj_id,enum dpaa2_dev_type dtype)998 dpaa2_rc_set_obj_irq(device_t dev, device_t child, struct dpaa2_cmd *cmd,
999 uint8_t irq_idx, uint64_t addr, uint32_t data, uint32_t irq_usr,
1000 uint32_t obj_id, enum dpaa2_dev_type dtype)
1001 {
1002 struct __packed set_obj_irq_args {
1003 uint32_t data;
1004 uint8_t irq_idx;
1005 uint8_t _reserved1[3];
1006 uint64_t addr;
1007 uint32_t irq_usr;
1008 uint32_t obj_id;
1009 uint8_t type[16];
1010 } *args;
1011 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1012 const char *type = dpaa2_ttos(dtype);
1013
1014 if (portal == NULL || cmd == NULL)
1015 return (DPAA2_CMD_STAT_ERR);
1016
1017 args = (struct set_obj_irq_args *) &cmd->params[0];
1018 args->irq_idx = irq_idx;
1019 args->addr = addr;
1020 args->data = data;
1021 args->irq_usr = irq_usr;
1022 args->obj_id = obj_id;
1023 memcpy(args->type, type, min(strlen(type) + 1, TYPE_LEN_MAX));
1024
1025 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_SET_OBJ_IRQ));
1026 }
1027
1028 static int
dpaa2_rc_get_conn(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_ep_desc * ep1_desc,struct dpaa2_ep_desc * ep2_desc,uint32_t * link_stat)1029 dpaa2_rc_get_conn(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1030 struct dpaa2_ep_desc *ep1_desc, struct dpaa2_ep_desc *ep2_desc,
1031 uint32_t *link_stat)
1032 {
1033 struct __packed get_conn_args {
1034 uint32_t ep1_id;
1035 uint32_t ep1_ifid;
1036 uint8_t ep1_type[16];
1037 uint64_t _reserved[4];
1038 } *args;
1039 struct __packed get_conn_resp {
1040 uint64_t _reserved1[3];
1041 uint32_t ep2_id;
1042 uint32_t ep2_ifid;
1043 uint8_t ep2_type[16];
1044 uint32_t link_stat;
1045 uint32_t _reserved2;
1046 } *resp;
1047 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1048 int error;
1049
1050 if (portal == NULL || cmd == NULL || ep1_desc == NULL ||
1051 ep2_desc == NULL)
1052 return (DPAA2_CMD_STAT_ERR);
1053
1054 args = (struct get_conn_args *) &cmd->params[0];
1055 args->ep1_id = ep1_desc->obj_id;
1056 args->ep1_ifid = ep1_desc->if_id;
1057 /* TODO: Remove magic number. */
1058 strncpy(args->ep1_type, dpaa2_ttos(ep1_desc->type), 16);
1059
1060 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_RC_GET_CONN);
1061 if (!error) {
1062 resp = (struct get_conn_resp *) &cmd->params[0];
1063 ep2_desc->obj_id = resp->ep2_id;
1064 ep2_desc->if_id = resp->ep2_ifid;
1065 ep2_desc->type = dpaa2_stot((const char *) resp->ep2_type);
1066 if (link_stat != NULL)
1067 *link_stat = resp->link_stat;
1068 }
1069
1070 return (error);
1071 }
1072
1073 static int
dpaa2_rc_ni_open(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t dpni_id,uint16_t * token)1074 dpaa2_rc_ni_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1075 uint32_t dpni_id, uint16_t *token)
1076 {
1077 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1078 struct dpaa2_cmd_header *hdr;
1079 int error;
1080
1081 if (portal == NULL || cmd == NULL || token == NULL)
1082 return (DPAA2_CMD_STAT_ERR);
1083
1084 cmd->params[0] = dpni_id;
1085 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_OPEN);
1086 if (!error) {
1087 hdr = (struct dpaa2_cmd_header *) &cmd->header;
1088 *token = hdr->token;
1089 }
1090
1091 return (error);
1092 }
1093
1094 static int
dpaa2_rc_ni_close(device_t dev,device_t child,struct dpaa2_cmd * cmd)1095 dpaa2_rc_ni_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1096 {
1097 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1098
1099 if (portal == NULL || cmd == NULL)
1100 return (DPAA2_CMD_STAT_ERR);
1101
1102 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_CLOSE));
1103 }
1104
1105 static int
dpaa2_rc_ni_enable(device_t dev,device_t child,struct dpaa2_cmd * cmd)1106 dpaa2_rc_ni_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1107 {
1108 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1109
1110 if (portal == NULL || cmd == NULL)
1111 return (DPAA2_CMD_STAT_ERR);
1112
1113 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_ENABLE));
1114 }
1115
1116 static int
dpaa2_rc_ni_disable(device_t dev,device_t child,struct dpaa2_cmd * cmd)1117 dpaa2_rc_ni_disable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1118 {
1119 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1120
1121 if (portal == NULL || cmd == NULL)
1122 return (DPAA2_CMD_STAT_ERR);
1123
1124 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_DISABLE));
1125 }
1126
1127 static int
dpaa2_rc_ni_get_api_version(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint16_t * major,uint16_t * minor)1128 dpaa2_rc_ni_get_api_version(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1129 uint16_t *major, uint16_t *minor)
1130 {
1131 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1132 int error;
1133
1134 if (portal == NULL || cmd == NULL || major == NULL || minor == NULL)
1135 return (DPAA2_CMD_STAT_ERR);
1136
1137 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_API_VER);
1138 if (!error) {
1139 *major = cmd->params[0] & 0xFFFFU;
1140 *minor = (cmd->params[0] >> 16) & 0xFFFFU;
1141 }
1142
1143 return (error);
1144 }
1145
1146 static int
dpaa2_rc_ni_reset(device_t dev,device_t child,struct dpaa2_cmd * cmd)1147 dpaa2_rc_ni_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1148 {
1149 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1150
1151 if (portal == NULL || cmd == NULL)
1152 return (DPAA2_CMD_STAT_ERR);
1153
1154 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_RESET));
1155 }
1156
1157 static int
dpaa2_rc_ni_get_attributes(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_ni_attr * attr)1158 dpaa2_rc_ni_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1159 struct dpaa2_ni_attr *attr)
1160 {
1161 struct __packed ni_attr {
1162 uint32_t options;
1163 uint8_t num_queues;
1164 uint8_t num_rx_tcs;
1165 uint8_t mac_entries;
1166 uint8_t num_tx_tcs;
1167 uint8_t vlan_entries;
1168 uint8_t num_channels;
1169 uint8_t qos_entries;
1170 uint8_t _reserved1;
1171 uint16_t fs_entries;
1172 uint16_t _reserved2;
1173 uint8_t qos_key_size;
1174 uint8_t fs_key_size;
1175 uint16_t wriop_ver;
1176 uint8_t num_cgs;
1177 uint8_t _reserved3;
1178 uint16_t _reserved4;
1179 uint64_t _reserved5[4];
1180 } *resp;
1181 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1182 int error;
1183
1184 if (portal == NULL || cmd == NULL || attr == NULL)
1185 return (DPAA2_CMD_STAT_ERR);
1186
1187 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_ATTR);
1188 if (!error) {
1189 resp = (struct ni_attr *) &cmd->params[0];
1190
1191 attr->options = resp->options;
1192 attr->wriop_ver = resp->wriop_ver;
1193
1194 attr->entries.fs = resp->fs_entries;
1195 attr->entries.mac = resp->mac_entries;
1196 attr->entries.vlan = resp->vlan_entries;
1197 attr->entries.qos = resp->qos_entries;
1198
1199 attr->num.queues = resp->num_queues;
1200 attr->num.rx_tcs = resp->num_rx_tcs;
1201 attr->num.tx_tcs = resp->num_tx_tcs;
1202 attr->num.channels = resp->num_channels;
1203 attr->num.cgs = resp->num_cgs;
1204
1205 attr->key_size.fs = resp->fs_key_size;
1206 attr->key_size.qos = resp->qos_key_size;
1207 }
1208
1209 return (error);
1210 }
1211
1212 static int
dpaa2_rc_ni_set_buf_layout(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_ni_buf_layout * bl)1213 dpaa2_rc_ni_set_buf_layout(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1214 struct dpaa2_ni_buf_layout *bl)
1215 {
1216 struct __packed set_buf_layout_args {
1217 uint8_t queue_type;
1218 uint8_t _reserved1;
1219 uint16_t _reserved2;
1220 uint16_t options;
1221 uint8_t params;
1222 uint8_t _reserved3;
1223 uint16_t priv_data_size;
1224 uint16_t data_align;
1225 uint16_t head_room;
1226 uint16_t tail_room;
1227 uint64_t _reserved4[5];
1228 } *args;
1229 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1230
1231 if (portal == NULL || cmd == NULL || bl == NULL)
1232 return (DPAA2_CMD_STAT_ERR);
1233
1234 args = (struct set_buf_layout_args *) &cmd->params[0];
1235 args->queue_type = (uint8_t) bl->queue_type;
1236 args->options = bl->options;
1237 args->params = 0;
1238 args->priv_data_size = bl->pd_size;
1239 args->data_align = bl->fd_align;
1240 args->head_room = bl->head_size;
1241 args->tail_room = bl->tail_size;
1242
1243 args->params |= bl->pass_timestamp ? 1U : 0U;
1244 args->params |= bl->pass_parser_result ? 2U : 0U;
1245 args->params |= bl->pass_frame_status ? 4U : 0U;
1246 args->params |= bl->pass_sw_opaque ? 8U : 0U;
1247
1248 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_BUF_LAYOUT));
1249 }
1250
1251 static int
dpaa2_rc_ni_get_tx_data_offset(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint16_t * offset)1252 dpaa2_rc_ni_get_tx_data_offset(device_t dev, device_t child,
1253 struct dpaa2_cmd *cmd, uint16_t *offset)
1254 {
1255 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1256 int error;
1257
1258 if (portal == NULL || cmd == NULL || offset == NULL)
1259 return (DPAA2_CMD_STAT_ERR);
1260
1261 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_TX_DATA_OFF);
1262 if (!error)
1263 *offset = cmd->params[0] & 0xFFFFU;
1264
1265 return (error);
1266 }
1267
1268 static int
dpaa2_rc_ni_get_port_mac_addr(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t * mac)1269 dpaa2_rc_ni_get_port_mac_addr(device_t dev, device_t child,
1270 struct dpaa2_cmd *cmd, uint8_t *mac)
1271 {
1272 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1273 int error;
1274
1275 if (portal == NULL || cmd == NULL || mac == NULL)
1276 return (DPAA2_CMD_STAT_ERR);
1277
1278 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_PORT_MAC_ADDR);
1279 if (!error) {
1280 mac[0] = (cmd->params[0] >> 56) & 0xFFU;
1281 mac[1] = (cmd->params[0] >> 48) & 0xFFU;
1282 mac[2] = (cmd->params[0] >> 40) & 0xFFU;
1283 mac[3] = (cmd->params[0] >> 32) & 0xFFU;
1284 mac[4] = (cmd->params[0] >> 24) & 0xFFU;
1285 mac[5] = (cmd->params[0] >> 16) & 0xFFU;
1286 }
1287
1288 return (error);
1289 }
1290
1291 static int
dpaa2_rc_ni_set_prim_mac_addr(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t * mac)1292 dpaa2_rc_ni_set_prim_mac_addr(device_t dev, device_t child,
1293 struct dpaa2_cmd *cmd, uint8_t *mac)
1294 {
1295 struct __packed set_prim_mac_args {
1296 uint8_t _reserved[2];
1297 uint8_t mac[ETHER_ADDR_LEN];
1298 } *args;
1299 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1300
1301 if (portal == NULL || cmd == NULL || mac == NULL)
1302 return (DPAA2_CMD_STAT_EINVAL);
1303
1304 args = (struct set_prim_mac_args *) &cmd->params[0];
1305 for (int i = 1; i <= ETHER_ADDR_LEN; i++)
1306 args->mac[i - 1] = mac[ETHER_ADDR_LEN - i];
1307
1308 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_PRIM_MAC_ADDR));
1309 }
1310
1311 static int
dpaa2_rc_ni_get_prim_mac_addr(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t * mac)1312 dpaa2_rc_ni_get_prim_mac_addr(device_t dev, device_t child,
1313 struct dpaa2_cmd *cmd, uint8_t *mac)
1314 {
1315 struct __packed get_prim_mac_resp {
1316 uint8_t _reserved[2];
1317 uint8_t mac[ETHER_ADDR_LEN];
1318 } *resp;
1319 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1320 int error;
1321
1322 if (portal == NULL || cmd == NULL || mac == NULL)
1323 return (DPAA2_CMD_STAT_EINVAL);
1324
1325 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_PRIM_MAC_ADDR);
1326 if (!error) {
1327 resp = (struct get_prim_mac_resp *) &cmd->params[0];
1328 for (int i = 1; i <= ETHER_ADDR_LEN; i++)
1329 mac[ETHER_ADDR_LEN - i] = resp->mac[i - 1];
1330 }
1331
1332 return (error);
1333 }
1334
1335 static int
dpaa2_rc_ni_set_link_cfg(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_ni_link_cfg * cfg)1336 dpaa2_rc_ni_set_link_cfg(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1337 struct dpaa2_ni_link_cfg *cfg)
1338 {
1339 struct __packed link_cfg_args {
1340 uint64_t _reserved1;
1341 uint32_t rate;
1342 uint32_t _reserved2;
1343 uint64_t options;
1344 uint64_t adv_speeds;
1345 uint64_t _reserved3[3];
1346 } *args;
1347 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1348
1349 if (portal == NULL || cmd == NULL || cfg == NULL)
1350 return (DPAA2_CMD_STAT_EINVAL);
1351
1352 args = (struct link_cfg_args *) &cmd->params[0];
1353 args->rate = cfg->rate;
1354 args->options = cfg->options;
1355 args->adv_speeds = cfg->adv_speeds;
1356
1357 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_LINK_CFG));
1358 }
1359
1360 static int
dpaa2_rc_ni_get_link_cfg(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_ni_link_cfg * cfg)1361 dpaa2_rc_ni_get_link_cfg(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1362 struct dpaa2_ni_link_cfg *cfg)
1363 {
1364 struct __packed link_cfg_resp {
1365 uint64_t _reserved1;
1366 uint32_t rate;
1367 uint32_t _reserved2;
1368 uint64_t options;
1369 uint64_t adv_speeds;
1370 uint64_t _reserved3[3];
1371 } *resp;
1372 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1373 int error;
1374
1375 if (portal == NULL || cmd == NULL || cfg == NULL)
1376 return (DPAA2_CMD_STAT_EINVAL);
1377
1378 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_LINK_CFG);
1379 if (!error) {
1380 resp = (struct link_cfg_resp *) &cmd->params[0];
1381 cfg->rate = resp->rate;
1382 cfg->options = resp->options;
1383 cfg->adv_speeds = resp->adv_speeds;
1384 }
1385
1386 return (error);
1387 }
1388
1389 static int
dpaa2_rc_ni_get_link_state(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_ni_link_state * state)1390 dpaa2_rc_ni_get_link_state(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1391 struct dpaa2_ni_link_state *state)
1392 {
1393 struct __packed link_state_resp {
1394 uint32_t _reserved1;
1395 uint32_t flags;
1396 uint32_t rate;
1397 uint32_t _reserved2;
1398 uint64_t options;
1399 uint64_t supported;
1400 uint64_t advert;
1401 } *resp;
1402 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1403 int error;
1404
1405 if (portal == NULL || cmd == NULL || state == NULL)
1406 return (DPAA2_CMD_STAT_EINVAL);
1407
1408 dpaa2_rc_reset_cmd_params(cmd);
1409
1410 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_LINK_STATE);
1411 if (!error) {
1412 resp = (struct link_state_resp *) &cmd->params[0];
1413 state->options = resp->options;
1414 state->adv_speeds = resp->advert;
1415 state->sup_speeds = resp->supported;
1416 state->rate = resp->rate;
1417
1418 state->link_up = resp->flags & 0x1u ? true : false;
1419 state->state_valid = resp->flags & 0x2u ? true : false;
1420 }
1421
1422 return (error);
1423 }
1424
1425 static int
dpaa2_rc_ni_set_qos_table(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_ni_qos_table * tbl)1426 dpaa2_rc_ni_set_qos_table(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1427 struct dpaa2_ni_qos_table *tbl)
1428 {
1429 struct __packed qos_table_args {
1430 uint32_t _reserved1;
1431 uint8_t default_tc;
1432 uint8_t options;
1433 uint16_t _reserved2;
1434 uint64_t _reserved[5];
1435 uint64_t kcfg_busaddr;
1436 } *args;
1437 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1438
1439 if (portal == NULL || cmd == NULL || tbl == NULL)
1440 return (DPAA2_CMD_STAT_EINVAL);
1441
1442 dpaa2_rc_reset_cmd_params(cmd);
1443
1444 args = (struct qos_table_args *) &cmd->params[0];
1445 args->default_tc = tbl->default_tc;
1446 args->kcfg_busaddr = tbl->kcfg_busaddr;
1447
1448 args->options |= tbl->discard_on_miss ? 1U : 0U;
1449 args->options |= tbl->keep_entries ? 2U : 0U;
1450
1451 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_QOS_TABLE));
1452 }
1453
1454 static int
dpaa2_rc_ni_clear_qos_table(device_t dev,device_t child,struct dpaa2_cmd * cmd)1455 dpaa2_rc_ni_clear_qos_table(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1456 {
1457 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1458
1459 if (portal == NULL || cmd == NULL)
1460 return (DPAA2_CMD_STAT_EINVAL);
1461
1462 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_CLEAR_QOS_TABLE));
1463 }
1464
1465 static int
dpaa2_rc_ni_set_pools(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_ni_pools_cfg * cfg)1466 dpaa2_rc_ni_set_pools(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1467 struct dpaa2_ni_pools_cfg *cfg)
1468 {
1469 struct __packed set_pools_args {
1470 uint8_t pools_num;
1471 uint8_t backup_pool_mask;
1472 uint8_t _reserved1;
1473 uint8_t pool_as; /* assigning: 0 - QPRI, 1 - QDBIN */
1474 uint32_t bp_obj_id[DPAA2_NI_MAX_POOLS];
1475 uint16_t buf_sz[DPAA2_NI_MAX_POOLS];
1476 uint32_t _reserved2;
1477 } *args;
1478 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1479
1480 if (portal == NULL || cmd == NULL || cfg == NULL)
1481 return (DPAA2_CMD_STAT_EINVAL);
1482
1483 dpaa2_rc_reset_cmd_params(cmd);
1484
1485 args = (struct set_pools_args *) &cmd->params[0];
1486 args->pools_num = cfg->pools_num < DPAA2_NI_MAX_POOLS
1487 ? cfg->pools_num : DPAA2_NI_MAX_POOLS;
1488 for (uint32_t i = 0; i < args->pools_num; i++) {
1489 args->bp_obj_id[i] = cfg->pools[i].bp_obj_id;
1490 args->buf_sz[i] = cfg->pools[i].buf_sz;
1491 args->backup_pool_mask |= (cfg->pools[i].backup_flag & 1) << i;
1492 }
1493
1494 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_POOLS));
1495 }
1496
1497 static int
dpaa2_rc_ni_set_err_behavior(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_ni_err_cfg * cfg)1498 dpaa2_rc_ni_set_err_behavior(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1499 struct dpaa2_ni_err_cfg *cfg)
1500 {
1501 struct __packed err_behavior_args {
1502 uint32_t err_mask;
1503 uint8_t flags;
1504 } *args;
1505 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1506
1507 if (portal == NULL || cmd == NULL || cfg == NULL)
1508 return (DPAA2_CMD_STAT_EINVAL);
1509
1510 dpaa2_rc_reset_cmd_params(cmd);
1511
1512 args = (struct err_behavior_args *) &cmd->params[0];
1513 args->err_mask = cfg->err_mask;
1514
1515 args->flags |= cfg->set_err_fas ? 0x10u : 0u;
1516 args->flags |= ((uint8_t) cfg->action) & 0x0Fu;
1517
1518 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_ERR_BEHAVIOR));
1519 }
1520
1521 static int
dpaa2_rc_ni_get_queue(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_ni_queue_cfg * cfg)1522 dpaa2_rc_ni_get_queue(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1523 struct dpaa2_ni_queue_cfg *cfg)
1524 {
1525 struct __packed get_queue_args {
1526 uint8_t queue_type;
1527 uint8_t tc;
1528 uint8_t idx;
1529 uint8_t chan_id;
1530 } *args;
1531 struct __packed get_queue_resp {
1532 uint64_t _reserved1;
1533 uint32_t dest_id;
1534 uint16_t _reserved2;
1535 uint8_t priority;
1536 uint8_t flags;
1537 uint64_t flc;
1538 uint64_t user_ctx;
1539 uint32_t fqid;
1540 uint16_t qdbin;
1541 uint16_t _reserved3;
1542 uint8_t cgid;
1543 uint8_t _reserved[15];
1544 } *resp;
1545 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1546 int error;
1547
1548 if (portal == NULL || cmd == NULL || cfg == NULL)
1549 return (DPAA2_CMD_STAT_EINVAL);
1550
1551 dpaa2_rc_reset_cmd_params(cmd);
1552
1553 args = (struct get_queue_args *) &cmd->params[0];
1554 args->queue_type = (uint8_t) cfg->type;
1555 args->tc = cfg->tc;
1556 args->idx = cfg->idx;
1557 args->chan_id = cfg->chan_id;
1558
1559 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_QUEUE);
1560 if (!error) {
1561 resp = (struct get_queue_resp *) &cmd->params[0];
1562
1563 cfg->dest_id = resp->dest_id;
1564 cfg->priority = resp->priority;
1565 cfg->flow_ctx = resp->flc;
1566 cfg->user_ctx = resp->user_ctx;
1567 cfg->fqid = resp->fqid;
1568 cfg->qdbin = resp->qdbin;
1569 cfg->cgid = resp->cgid;
1570
1571 cfg->dest_type = (enum dpaa2_ni_dest_type) resp->flags & 0x0Fu;
1572 cfg->cgid_valid = (resp->flags & 0x20u) > 0u ? true : false;
1573 cfg->stash_control = (resp->flags & 0x40u) > 0u ? true : false;
1574 cfg->hold_active = (resp->flags & 0x80u) > 0u ? true : false;
1575 }
1576
1577 return (error);
1578 }
1579
1580 static int
dpaa2_rc_ni_set_queue(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_ni_queue_cfg * cfg)1581 dpaa2_rc_ni_set_queue(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1582 struct dpaa2_ni_queue_cfg *cfg)
1583 {
1584 struct __packed set_queue_args {
1585 uint8_t queue_type;
1586 uint8_t tc;
1587 uint8_t idx;
1588 uint8_t options;
1589 uint32_t _reserved1;
1590 uint32_t dest_id;
1591 uint16_t _reserved2;
1592 uint8_t priority;
1593 uint8_t flags;
1594 uint64_t flc;
1595 uint64_t user_ctx;
1596 uint8_t cgid;
1597 uint8_t chan_id;
1598 uint8_t _reserved[23];
1599 } *args;
1600 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1601
1602 if (portal == NULL || cmd == NULL || cfg == NULL)
1603 return (DPAA2_CMD_STAT_EINVAL);
1604
1605 dpaa2_rc_reset_cmd_params(cmd);
1606
1607 args = (struct set_queue_args *) &cmd->params[0];
1608 args->queue_type = (uint8_t) cfg->type;
1609 args->tc = cfg->tc;
1610 args->idx = cfg->idx;
1611 args->options = cfg->options;
1612 args->dest_id = cfg->dest_id;
1613 args->priority = cfg->priority;
1614 args->flc = cfg->flow_ctx;
1615 args->user_ctx = cfg->user_ctx;
1616 args->cgid = cfg->cgid;
1617 args->chan_id = cfg->chan_id;
1618
1619 args->flags |= (uint8_t)(cfg->dest_type & 0x0Fu);
1620 args->flags |= cfg->stash_control ? 0x40u : 0u;
1621 args->flags |= cfg->hold_active ? 0x80u : 0u;
1622
1623 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_QUEUE));
1624 }
1625
1626 static int
dpaa2_rc_ni_get_qdid(device_t dev,device_t child,struct dpaa2_cmd * cmd,enum dpaa2_ni_queue_type type,uint16_t * qdid)1627 dpaa2_rc_ni_get_qdid(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1628 enum dpaa2_ni_queue_type type, uint16_t *qdid)
1629 {
1630 struct __packed get_qdid_args {
1631 uint8_t queue_type;
1632 } *args;
1633 struct __packed get_qdid_resp {
1634 uint16_t qdid;
1635 } *resp;
1636 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1637 int error;
1638
1639 if (portal == NULL || cmd == NULL || qdid == NULL)
1640 return (DPAA2_CMD_STAT_EINVAL);
1641
1642 dpaa2_rc_reset_cmd_params(cmd);
1643
1644 args = (struct get_qdid_args *) &cmd->params[0];
1645 args->queue_type = (uint8_t) type;
1646
1647 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_QDID);
1648 if (!error) {
1649 resp = (struct get_qdid_resp *) &cmd->params[0];
1650 *qdid = resp->qdid;
1651 }
1652
1653 return (error);
1654 }
1655
1656 static int
dpaa2_rc_ni_add_mac_addr(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t * mac)1657 dpaa2_rc_ni_add_mac_addr(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1658 uint8_t *mac)
1659 {
1660 struct __packed add_mac_args {
1661 uint8_t flags;
1662 uint8_t _reserved;
1663 uint8_t mac[ETHER_ADDR_LEN];
1664 uint8_t tc_id;
1665 uint8_t fq_id;
1666 } *args;
1667 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1668
1669 if (portal == NULL || cmd == NULL || mac == NULL)
1670 return (DPAA2_CMD_STAT_EINVAL);
1671
1672 dpaa2_rc_reset_cmd_params(cmd);
1673
1674 args = (struct add_mac_args *) &cmd->params[0];
1675 for (int i = 1; i <= ETHER_ADDR_LEN; i++)
1676 args->mac[i - 1] = mac[ETHER_ADDR_LEN - i];
1677
1678 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_ADD_MAC_ADDR));
1679 }
1680
1681 static int
dpaa2_rc_ni_remove_mac_addr(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t * mac)1682 dpaa2_rc_ni_remove_mac_addr(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1683 uint8_t *mac)
1684 {
1685 struct __packed rem_mac_args {
1686 uint16_t _reserved;
1687 uint8_t mac[ETHER_ADDR_LEN];
1688 uint64_t _reserved1[6];
1689 } *args;
1690 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1691
1692 if (portal == NULL || cmd == NULL || mac == NULL)
1693 return (DPAA2_CMD_STAT_EINVAL);
1694
1695 dpaa2_rc_reset_cmd_params(cmd);
1696
1697 args = (struct rem_mac_args *) &cmd->params[0];
1698 for (int i = 1; i <= ETHER_ADDR_LEN; i++)
1699 args->mac[i - 1] = mac[ETHER_ADDR_LEN - i];
1700
1701 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_REMOVE_MAC_ADDR));
1702 }
1703
1704 static int
dpaa2_rc_ni_clear_mac_filters(device_t dev,device_t child,struct dpaa2_cmd * cmd,bool rm_uni,bool rm_multi)1705 dpaa2_rc_ni_clear_mac_filters(device_t dev, device_t child,
1706 struct dpaa2_cmd *cmd, bool rm_uni, bool rm_multi)
1707 {
1708 struct __packed clear_mac_filters_args {
1709 uint8_t flags;
1710 } *args;
1711 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1712
1713 if (portal == NULL || cmd == NULL)
1714 return (DPAA2_CMD_STAT_EINVAL);
1715
1716 dpaa2_rc_reset_cmd_params(cmd);
1717
1718 args = (struct clear_mac_filters_args *) &cmd->params[0];
1719 args->flags |= rm_uni ? 0x1 : 0x0;
1720 args->flags |= rm_multi ? 0x2 : 0x0;
1721
1722 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_CLEAR_MAC_FILTERS));
1723 }
1724
1725 static int
dpaa2_rc_ni_set_mfl(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint16_t length)1726 dpaa2_rc_ni_set_mfl(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1727 uint16_t length)
1728 {
1729 struct __packed set_mfl_args {
1730 uint16_t length;
1731 } *args;
1732 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1733
1734 if (portal == NULL || cmd == NULL)
1735 return (DPAA2_CMD_STAT_EINVAL);
1736
1737 dpaa2_rc_reset_cmd_params(cmd);
1738
1739 args = (struct set_mfl_args *) &cmd->params[0];
1740 args->length = length;
1741
1742 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_MFL));
1743 }
1744
1745 static int
dpaa2_rc_ni_set_offload(device_t dev,device_t child,struct dpaa2_cmd * cmd,enum dpaa2_ni_ofl_type ofl_type,bool en)1746 dpaa2_rc_ni_set_offload(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1747 enum dpaa2_ni_ofl_type ofl_type, bool en)
1748 {
1749 struct __packed set_ofl_args {
1750 uint8_t _reserved[3];
1751 uint8_t ofl_type;
1752 uint32_t config;
1753 } *args;
1754 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1755
1756 if (portal == NULL || cmd == NULL)
1757 return (DPAA2_CMD_STAT_EINVAL);
1758
1759 dpaa2_rc_reset_cmd_params(cmd);
1760
1761 args = (struct set_ofl_args *) &cmd->params[0];
1762 args->ofl_type = (uint8_t) ofl_type;
1763 args->config = en ? 1u : 0u;
1764
1765 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_OFFLOAD));
1766 }
1767
1768 static int
dpaa2_rc_ni_set_irq_mask(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t irq_idx,uint32_t mask)1769 dpaa2_rc_ni_set_irq_mask(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1770 uint8_t irq_idx, uint32_t mask)
1771 {
1772 struct __packed set_irq_mask_args {
1773 uint32_t mask;
1774 uint8_t irq_idx;
1775 } *args;
1776 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1777
1778 if (portal == NULL || cmd == NULL)
1779 return (DPAA2_CMD_STAT_EINVAL);
1780
1781 dpaa2_rc_reset_cmd_params(cmd);
1782
1783 args = (struct set_irq_mask_args *) &cmd->params[0];
1784 args->mask = mask;
1785 args->irq_idx = irq_idx;
1786
1787 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_IRQ_MASK));
1788 }
1789
1790 static int
dpaa2_rc_ni_set_irq_enable(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t irq_idx,bool en)1791 dpaa2_rc_ni_set_irq_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1792 uint8_t irq_idx, bool en)
1793 {
1794 struct __packed set_irq_enable_args {
1795 uint32_t en;
1796 uint8_t irq_idx;
1797 } *args;
1798 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1799
1800 if (portal == NULL || cmd == NULL)
1801 return (DPAA2_CMD_STAT_EINVAL);
1802
1803 dpaa2_rc_reset_cmd_params(cmd);
1804
1805 args = (struct set_irq_enable_args *) &cmd->params[0];
1806 args->en = en ? 1u : 0u;
1807 args->irq_idx = irq_idx;
1808
1809 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_IRQ_ENABLE));
1810 }
1811
1812 static int
dpaa2_rc_ni_get_irq_status(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t irq_idx,uint32_t * status)1813 dpaa2_rc_ni_get_irq_status(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1814 uint8_t irq_idx, uint32_t *status)
1815 {
1816 struct __packed get_irq_stat_args {
1817 uint32_t status;
1818 uint8_t irq_idx;
1819 } *args;
1820 struct __packed get_irq_stat_resp {
1821 uint32_t status;
1822 } *resp;
1823 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1824 int error;
1825
1826 if (portal == NULL || cmd == NULL || status == NULL)
1827 return (DPAA2_CMD_STAT_EINVAL);
1828
1829 dpaa2_rc_reset_cmd_params(cmd);
1830
1831 args = (struct get_irq_stat_args *) &cmd->params[0];
1832 args->status = *status;
1833 args->irq_idx = irq_idx;
1834
1835 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_IRQ_STATUS);
1836 if (!error) {
1837 resp = (struct get_irq_stat_resp *) &cmd->params[0];
1838 *status = resp->status;
1839 }
1840
1841 return (error);
1842 }
1843
1844 static int
dpaa2_rc_ni_set_uni_promisc(device_t dev,device_t child,struct dpaa2_cmd * cmd,bool en)1845 dpaa2_rc_ni_set_uni_promisc(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1846 bool en)
1847 {
1848 struct __packed set_uni_promisc_args {
1849 uint8_t en;
1850 } *args;
1851 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1852
1853 if (portal == NULL || cmd == NULL)
1854 return (DPAA2_CMD_STAT_EINVAL);
1855
1856 dpaa2_rc_reset_cmd_params(cmd);
1857
1858 args = (struct set_uni_promisc_args *) &cmd->params[0];
1859 args->en = en ? 1u : 0u;
1860
1861 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_UNI_PROMISC));
1862 }
1863
1864 static int
dpaa2_rc_ni_set_multi_promisc(device_t dev,device_t child,struct dpaa2_cmd * cmd,bool en)1865 dpaa2_rc_ni_set_multi_promisc(device_t dev, device_t child,
1866 struct dpaa2_cmd *cmd, bool en)
1867 {
1868 /* TODO: Implementation is the same as for ni_set_uni_promisc(). */
1869 struct __packed set_multi_promisc_args {
1870 uint8_t en;
1871 } *args;
1872 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1873
1874 if (portal == NULL || cmd == NULL)
1875 return (DPAA2_CMD_STAT_EINVAL);
1876
1877 dpaa2_rc_reset_cmd_params(cmd);
1878
1879 args = (struct set_multi_promisc_args *) &cmd->params[0];
1880 args->en = en ? 1u : 0u;
1881
1882 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_MULTI_PROMISC));
1883 }
1884
1885 static int
dpaa2_rc_ni_get_statistics(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t page,uint16_t param,uint64_t * cnt)1886 dpaa2_rc_ni_get_statistics(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1887 uint8_t page, uint16_t param, uint64_t *cnt)
1888 {
1889 struct __packed get_statistics_args {
1890 uint8_t page;
1891 uint16_t param;
1892 } *args;
1893 struct __packed get_statistics_resp {
1894 uint64_t cnt[7];
1895 } *resp;
1896 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1897 int error;
1898
1899 if (portal == NULL || cmd == NULL || cnt == NULL)
1900 return (DPAA2_CMD_STAT_EINVAL);
1901
1902 dpaa2_rc_reset_cmd_params(cmd);
1903
1904 args = (struct get_statistics_args *) &cmd->params[0];
1905 args->page = page;
1906 args->param = param;
1907
1908 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_STATISTICS);
1909 if (!error) {
1910 resp = (struct get_statistics_resp *) &cmd->params[0];
1911 for (int i = 0; i < DPAA2_NI_STAT_COUNTERS; i++)
1912 cnt[i] = resp->cnt[i];
1913 }
1914
1915 return (error);
1916 }
1917
1918 static int
dpaa2_rc_ni_set_rx_tc_dist(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint16_t dist_size,uint8_t tc,enum dpaa2_ni_dist_mode dist_mode,bus_addr_t key_cfg_buf)1919 dpaa2_rc_ni_set_rx_tc_dist(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1920 uint16_t dist_size, uint8_t tc, enum dpaa2_ni_dist_mode dist_mode,
1921 bus_addr_t key_cfg_buf)
1922 {
1923 struct __packed set_rx_tc_dist_args {
1924 uint16_t dist_size;
1925 uint8_t tc;
1926 uint8_t ma_dm; /* miss action + dist. mode */
1927 uint32_t _reserved1;
1928 uint64_t _reserved2[5];
1929 uint64_t key_cfg_iova;
1930 } *args;
1931 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1932
1933 if (portal == NULL || cmd == NULL)
1934 return (DPAA2_CMD_STAT_EINVAL);
1935
1936 dpaa2_rc_reset_cmd_params(cmd);
1937
1938 args = (struct set_rx_tc_dist_args *) &cmd->params[0];
1939 args->dist_size = dist_size;
1940 args->tc = tc;
1941 args->ma_dm = ((uint8_t) dist_mode) & 0x0Fu;
1942 args->key_cfg_iova = key_cfg_buf;
1943
1944 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_SET_RX_TC_DIST));
1945 }
1946
1947 static int
dpaa2_rc_io_open(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t dpio_id,uint16_t * token)1948 dpaa2_rc_io_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
1949 uint32_t dpio_id, uint16_t *token)
1950 {
1951 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1952 struct dpaa2_cmd_header *hdr;
1953 int error;
1954
1955 if (portal == NULL || cmd == NULL || token == NULL)
1956 return (DPAA2_CMD_STAT_ERR);
1957
1958 cmd->params[0] = dpio_id;
1959 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_OPEN);
1960 if (!error) {
1961 hdr = (struct dpaa2_cmd_header *) &cmd->header;
1962 *token = hdr->token;
1963 }
1964
1965 return (error);
1966 }
1967
1968 static int
dpaa2_rc_io_close(device_t dev,device_t child,struct dpaa2_cmd * cmd)1969 dpaa2_rc_io_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1970 {
1971 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1972
1973 if (portal == NULL || cmd == NULL)
1974 return (DPAA2_CMD_STAT_ERR);
1975
1976 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_CLOSE));
1977 }
1978
1979 static int
dpaa2_rc_io_enable(device_t dev,device_t child,struct dpaa2_cmd * cmd)1980 dpaa2_rc_io_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1981 {
1982 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1983
1984 if (portal == NULL || cmd == NULL)
1985 return (DPAA2_CMD_STAT_ERR);
1986
1987 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_ENABLE));
1988 }
1989
1990 static int
dpaa2_rc_io_disable(device_t dev,device_t child,struct dpaa2_cmd * cmd)1991 dpaa2_rc_io_disable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
1992 {
1993 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
1994
1995 if (portal == NULL || cmd == NULL)
1996 return (DPAA2_CMD_STAT_ERR);
1997
1998 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_DISABLE));
1999 }
2000
2001 static int
dpaa2_rc_io_reset(device_t dev,device_t child,struct dpaa2_cmd * cmd)2002 dpaa2_rc_io_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2003 {
2004 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2005
2006 if (portal == NULL || cmd == NULL)
2007 return (DPAA2_CMD_STAT_ERR);
2008
2009 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_RESET));
2010 }
2011
2012 static int
dpaa2_rc_io_get_attributes(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_io_attr * attr)2013 dpaa2_rc_io_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2014 struct dpaa2_io_attr *attr)
2015 {
2016 struct __packed dpaa2_io_attr {
2017 uint32_t id;
2018 uint16_t swp_id;
2019 uint8_t priors_num;
2020 uint8_t chan_mode;
2021 uint64_t swp_ce_paddr;
2022 uint64_t swp_ci_paddr;
2023 uint32_t swp_version;
2024 uint32_t _reserved1;
2025 uint32_t swp_clk;
2026 uint32_t _reserved2[5];
2027 } *pattr;
2028 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2029 int error;
2030
2031 if (portal == NULL || cmd == NULL || attr == NULL)
2032 return (DPAA2_CMD_STAT_ERR);
2033
2034 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_GET_ATTR);
2035 if (!error) {
2036 pattr = (struct dpaa2_io_attr *) &cmd->params[0];
2037
2038 attr->swp_ce_paddr = pattr->swp_ce_paddr;
2039 attr->swp_ci_paddr = pattr->swp_ci_paddr;
2040 attr->swp_version = pattr->swp_version;
2041 attr->swp_clk = pattr->swp_clk;
2042 attr->id = pattr->id;
2043 attr->swp_id = pattr->swp_id;
2044 attr->priors_num = pattr->priors_num;
2045 attr->chan_mode = (enum dpaa2_io_chan_mode)
2046 pattr->chan_mode;
2047 }
2048
2049 return (error);
2050 }
2051
2052 static int
dpaa2_rc_io_set_irq_mask(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t irq_idx,uint32_t mask)2053 dpaa2_rc_io_set_irq_mask(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2054 uint8_t irq_idx, uint32_t mask)
2055 {
2056 /* TODO: Extract similar *_set_irq_mask() into one function. */
2057 struct __packed set_irq_mask_args {
2058 uint32_t mask;
2059 uint8_t irq_idx;
2060 } *args;
2061 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2062
2063 if (portal == NULL || cmd == NULL)
2064 return (DPAA2_CMD_STAT_EINVAL);
2065
2066 dpaa2_rc_reset_cmd_params(cmd);
2067
2068 args = (struct set_irq_mask_args *) &cmd->params[0];
2069 args->mask = mask;
2070 args->irq_idx = irq_idx;
2071
2072 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_SET_IRQ_MASK));
2073 }
2074
2075 static int
dpaa2_rc_io_get_irq_status(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t irq_idx,uint32_t * status)2076 dpaa2_rc_io_get_irq_status(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2077 uint8_t irq_idx, uint32_t *status)
2078 {
2079 /* TODO: Extract similar *_get_irq_status() into one function. */
2080 struct __packed get_irq_stat_args {
2081 uint32_t status;
2082 uint8_t irq_idx;
2083 } *args;
2084 struct __packed get_irq_stat_resp {
2085 uint32_t status;
2086 } *resp;
2087 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2088 int error;
2089
2090 if (portal == NULL || cmd == NULL || status == NULL)
2091 return (DPAA2_CMD_STAT_EINVAL);
2092
2093 dpaa2_rc_reset_cmd_params(cmd);
2094
2095 args = (struct get_irq_stat_args *) &cmd->params[0];
2096 args->status = *status;
2097 args->irq_idx = irq_idx;
2098
2099 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_GET_IRQ_STATUS);
2100 if (!error) {
2101 resp = (struct get_irq_stat_resp *) &cmd->params[0];
2102 *status = resp->status;
2103 }
2104
2105 return (error);
2106 }
2107
2108 static int
dpaa2_rc_io_set_irq_enable(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t irq_idx,bool en)2109 dpaa2_rc_io_set_irq_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2110 uint8_t irq_idx, bool en)
2111 {
2112 /* TODO: Extract similar *_set_irq_enable() into one function. */
2113 struct __packed set_irq_enable_args {
2114 uint32_t en;
2115 uint8_t irq_idx;
2116 } *args;
2117 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2118
2119 if (portal == NULL || cmd == NULL)
2120 return (DPAA2_CMD_STAT_EINVAL);
2121
2122 dpaa2_rc_reset_cmd_params(cmd);
2123
2124 args = (struct set_irq_enable_args *) &cmd->params[0];
2125 args->en = en ? 1u : 0u;
2126 args->irq_idx = irq_idx;
2127
2128 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_SET_IRQ_ENABLE));
2129 }
2130
2131 static int
dpaa2_rc_io_add_static_dq_chan(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t dpcon_id,uint8_t * chan_idx)2132 dpaa2_rc_io_add_static_dq_chan(device_t dev, device_t child,
2133 struct dpaa2_cmd *cmd, uint32_t dpcon_id, uint8_t *chan_idx)
2134 {
2135 struct __packed add_static_dq_chan_args {
2136 uint32_t dpcon_id;
2137 } *args;
2138 struct __packed add_static_dq_chan_resp {
2139 uint8_t chan_idx;
2140 } *resp;
2141 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2142 int error;
2143
2144 if (portal == NULL || cmd == NULL || chan_idx == NULL)
2145 return (DPAA2_CMD_STAT_EINVAL);
2146
2147 dpaa2_rc_reset_cmd_params(cmd);
2148
2149 args = (struct add_static_dq_chan_args *) &cmd->params[0];
2150 args->dpcon_id = dpcon_id;
2151
2152 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_IO_ADD_STATIC_DQ_CHAN);
2153 if (!error) {
2154 resp = (struct add_static_dq_chan_resp *) &cmd->params[0];
2155 *chan_idx = resp->chan_idx;
2156 }
2157
2158 return (error);
2159 }
2160
2161 static int
dpaa2_rc_bp_open(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t dpbp_id,uint16_t * token)2162 dpaa2_rc_bp_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2163 uint32_t dpbp_id, uint16_t *token)
2164 {
2165 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2166 struct dpaa2_cmd_header *hdr;
2167 int error;
2168
2169 if (portal == NULL || cmd == NULL || token == NULL)
2170 return (DPAA2_CMD_STAT_ERR);
2171
2172 cmd->params[0] = dpbp_id;
2173 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_OPEN);
2174 if (!error) {
2175 hdr = (struct dpaa2_cmd_header *) &cmd->header;
2176 *token = hdr->token;
2177 }
2178
2179 return (error);
2180 }
2181
2182 static int
dpaa2_rc_bp_close(device_t dev,device_t child,struct dpaa2_cmd * cmd)2183 dpaa2_rc_bp_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2184 {
2185 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2186
2187 if (portal == NULL || cmd == NULL)
2188 return (DPAA2_CMD_STAT_ERR);
2189
2190 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_CLOSE));
2191 }
2192
2193 static int
dpaa2_rc_bp_enable(device_t dev,device_t child,struct dpaa2_cmd * cmd)2194 dpaa2_rc_bp_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2195 {
2196 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2197
2198 if (portal == NULL || cmd == NULL)
2199 return (DPAA2_CMD_STAT_ERR);
2200
2201 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_ENABLE));
2202 }
2203
2204 static int
dpaa2_rc_bp_disable(device_t dev,device_t child,struct dpaa2_cmd * cmd)2205 dpaa2_rc_bp_disable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2206 {
2207 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2208
2209 if (portal == NULL || cmd == NULL)
2210 return (DPAA2_CMD_STAT_ERR);
2211
2212 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_DISABLE));
2213 }
2214
2215 static int
dpaa2_rc_bp_reset(device_t dev,device_t child,struct dpaa2_cmd * cmd)2216 dpaa2_rc_bp_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2217 {
2218 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2219
2220 if (portal == NULL || cmd == NULL)
2221 return (DPAA2_CMD_STAT_ERR);
2222
2223 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_RESET));
2224 }
2225
2226 static int
dpaa2_rc_bp_get_attributes(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_bp_attr * attr)2227 dpaa2_rc_bp_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2228 struct dpaa2_bp_attr *attr)
2229 {
2230 struct __packed dpaa2_bp_attr {
2231 uint16_t _reserved1;
2232 uint16_t bpid;
2233 uint32_t id;
2234 } *pattr;
2235 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2236 int error;
2237
2238 if (portal == NULL || cmd == NULL || attr == NULL)
2239 return (DPAA2_CMD_STAT_ERR);
2240
2241 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_BP_GET_ATTR);
2242 if (!error) {
2243 pattr = (struct dpaa2_bp_attr *) &cmd->params[0];
2244 attr->id = pattr->id;
2245 attr->bpid = pattr->bpid;
2246 }
2247
2248 return (error);
2249 }
2250
2251 static int
dpaa2_rc_mac_open(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t dpmac_id,uint16_t * token)2252 dpaa2_rc_mac_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2253 uint32_t dpmac_id, uint16_t *token)
2254 {
2255 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2256 struct dpaa2_cmd_header *hdr;
2257 int error;
2258
2259 if (portal == NULL || cmd == NULL || token == NULL)
2260 return (DPAA2_CMD_STAT_ERR);
2261
2262 cmd->params[0] = dpmac_id;
2263 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_OPEN);
2264 if (!error) {
2265 hdr = (struct dpaa2_cmd_header *) &cmd->header;
2266 *token = hdr->token;
2267 }
2268
2269 return (error);
2270 }
2271
2272 static int
dpaa2_rc_mac_close(device_t dev,device_t child,struct dpaa2_cmd * cmd)2273 dpaa2_rc_mac_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2274 {
2275 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2276
2277 if (portal == NULL || cmd == NULL)
2278 return (DPAA2_CMD_STAT_ERR);
2279
2280 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_CLOSE));
2281 }
2282
2283 static int
dpaa2_rc_mac_reset(device_t dev,device_t child,struct dpaa2_cmd * cmd)2284 dpaa2_rc_mac_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2285 {
2286 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2287
2288 if (portal == NULL || cmd == NULL)
2289 return (DPAA2_CMD_STAT_ERR);
2290
2291 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_RESET));
2292 }
2293
2294 static int
dpaa2_rc_mac_mdio_read(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t phy,uint16_t reg,uint16_t * val)2295 dpaa2_rc_mac_mdio_read(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2296 uint8_t phy, uint16_t reg, uint16_t *val)
2297 {
2298 struct __packed mdio_read_args {
2299 uint8_t clause; /* set to 0 by default */
2300 uint8_t phy;
2301 uint16_t reg;
2302 uint32_t _reserved1;
2303 uint64_t _reserved2[6];
2304 } *args;
2305 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2306 int error;
2307
2308 if (portal == NULL || cmd == NULL || val == NULL)
2309 return (DPAA2_CMD_STAT_ERR);
2310
2311 args = (struct mdio_read_args *) &cmd->params[0];
2312 args->phy = phy;
2313 args->reg = reg;
2314 args->clause = 0;
2315
2316 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_MDIO_READ);
2317 if (!error)
2318 *val = cmd->params[0] & 0xFFFF;
2319
2320 return (error);
2321 }
2322
2323 static int
dpaa2_rc_mac_mdio_write(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t phy,uint16_t reg,uint16_t val)2324 dpaa2_rc_mac_mdio_write(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2325 uint8_t phy, uint16_t reg, uint16_t val)
2326 {
2327 struct __packed mdio_write_args {
2328 uint8_t clause; /* set to 0 by default */
2329 uint8_t phy;
2330 uint16_t reg;
2331 uint16_t val;
2332 uint16_t _reserved1;
2333 uint64_t _reserved2[6];
2334 } *args;
2335 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2336
2337 if (portal == NULL || cmd == NULL)
2338 return (DPAA2_CMD_STAT_ERR);
2339
2340 args = (struct mdio_write_args *) &cmd->params[0];
2341 args->phy = phy;
2342 args->reg = reg;
2343 args->val = val;
2344 args->clause = 0;
2345
2346 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_MDIO_WRITE));
2347 }
2348
2349 static int
dpaa2_rc_mac_get_addr(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t * mac)2350 dpaa2_rc_mac_get_addr(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2351 uint8_t *mac)
2352 {
2353 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2354 int error;
2355
2356 if (portal == NULL || cmd == NULL || mac == NULL)
2357 return (DPAA2_CMD_STAT_ERR);
2358
2359 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_GET_ADDR);
2360 if (!error) {
2361 mac[0] = (cmd->params[0] >> 56) & 0xFFU;
2362 mac[1] = (cmd->params[0] >> 48) & 0xFFU;
2363 mac[2] = (cmd->params[0] >> 40) & 0xFFU;
2364 mac[3] = (cmd->params[0] >> 32) & 0xFFU;
2365 mac[4] = (cmd->params[0] >> 24) & 0xFFU;
2366 mac[5] = (cmd->params[0] >> 16) & 0xFFU;
2367 }
2368
2369 return (error);
2370 }
2371
2372 static int
dpaa2_rc_mac_get_attributes(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_mac_attr * attr)2373 dpaa2_rc_mac_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2374 struct dpaa2_mac_attr *attr)
2375 {
2376 struct __packed mac_attr_resp {
2377 uint8_t eth_if;
2378 uint8_t link_type;
2379 uint16_t id;
2380 uint32_t max_rate;
2381
2382 uint8_t fec_mode;
2383 uint8_t ifg_mode;
2384 uint8_t ifg_len;
2385 uint8_t _reserved1;
2386 uint32_t _reserved2;
2387
2388 uint8_t sgn_post_pre;
2389 uint8_t serdes_cfg_mode;
2390 uint8_t eq_amp_red;
2391 uint8_t eq_post1q;
2392 uint8_t eq_preq;
2393 uint8_t eq_type;
2394 uint16_t _reserved3;
2395
2396 uint64_t _reserved[4];
2397 } *resp;
2398 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2399 int error;
2400
2401 if (portal == NULL || cmd == NULL || attr == NULL)
2402 return (DPAA2_CMD_STAT_EINVAL);
2403
2404 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_GET_ATTR);
2405 if (!error) {
2406 resp = (struct mac_attr_resp *) &cmd->params[0];
2407 attr->id = resp->id;
2408 attr->max_rate = resp->max_rate;
2409 attr->eth_if = resp->eth_if;
2410 attr->link_type = resp->link_type;
2411 }
2412
2413 return (error);
2414 }
2415
2416 static int
dpaa2_rc_mac_set_link_state(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_mac_link_state * state)2417 dpaa2_rc_mac_set_link_state(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2418 struct dpaa2_mac_link_state *state)
2419 {
2420 struct __packed mac_set_link_args {
2421 uint64_t options;
2422 uint32_t rate;
2423 uint32_t _reserved1;
2424 uint32_t flags;
2425 uint32_t _reserved2;
2426 uint64_t supported;
2427 uint64_t advert;
2428 } *args;
2429 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2430
2431 if (portal == NULL || cmd == NULL || state == NULL)
2432 return (DPAA2_CMD_STAT_EINVAL);
2433
2434 dpaa2_rc_reset_cmd_params(cmd);
2435
2436 args = (struct mac_set_link_args *) &cmd->params[0];
2437 args->options = state->options;
2438 args->rate = state->rate;
2439 args->supported = state->supported;
2440 args->advert = state->advert;
2441
2442 args->flags |= state->up ? 0x1u : 0u;
2443 args->flags |= state->state_valid ? 0x2u : 0u;
2444
2445 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_SET_LINK_STATE));
2446 }
2447
2448 static int
dpaa2_rc_mac_set_irq_mask(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t irq_idx,uint32_t mask)2449 dpaa2_rc_mac_set_irq_mask(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2450 uint8_t irq_idx, uint32_t mask)
2451 {
2452 /* TODO: Implementation is the same as for ni_set_irq_mask(). */
2453 struct __packed set_irq_mask_args {
2454 uint32_t mask;
2455 uint8_t irq_idx;
2456 } *args;
2457 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2458
2459 if (portal == NULL || cmd == NULL)
2460 return (DPAA2_CMD_STAT_EINVAL);
2461
2462 dpaa2_rc_reset_cmd_params(cmd);
2463
2464 args = (struct set_irq_mask_args *) &cmd->params[0];
2465 args->mask = mask;
2466 args->irq_idx = irq_idx;
2467
2468 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_SET_IRQ_MASK));
2469 }
2470
2471 static int
dpaa2_rc_mac_set_irq_enable(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t irq_idx,bool en)2472 dpaa2_rc_mac_set_irq_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2473 uint8_t irq_idx, bool en)
2474 {
2475 /* TODO: Implementation is the same as for ni_set_irq_enable(). */
2476 struct __packed set_irq_enable_args {
2477 uint32_t en;
2478 uint8_t irq_idx;
2479 } *args;
2480 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2481
2482 if (portal == NULL || cmd == NULL)
2483 return (DPAA2_CMD_STAT_EINVAL);
2484
2485 dpaa2_rc_reset_cmd_params(cmd);
2486
2487 args = (struct set_irq_enable_args *) &cmd->params[0];
2488 args->en = en ? 1u : 0u;
2489 args->irq_idx = irq_idx;
2490
2491 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_SET_IRQ_ENABLE));
2492 }
2493
2494 static int
dpaa2_rc_mac_get_irq_status(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint8_t irq_idx,uint32_t * status)2495 dpaa2_rc_mac_get_irq_status(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2496 uint8_t irq_idx, uint32_t *status)
2497 {
2498 /* TODO: Implementation is the same as ni_get_irq_status(). */
2499 struct __packed get_irq_stat_args {
2500 uint32_t status;
2501 uint8_t irq_idx;
2502 } *args;
2503 struct __packed get_irq_stat_resp {
2504 uint32_t status;
2505 } *resp;
2506 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2507 int error;
2508
2509 if (portal == NULL || cmd == NULL || status == NULL)
2510 return (DPAA2_CMD_STAT_EINVAL);
2511
2512 dpaa2_rc_reset_cmd_params(cmd);
2513
2514 args = (struct get_irq_stat_args *) &cmd->params[0];
2515 args->status = *status;
2516 args->irq_idx = irq_idx;
2517
2518 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MAC_GET_IRQ_STATUS);
2519 if (!error) {
2520 resp = (struct get_irq_stat_resp *) &cmd->params[0];
2521 *status = resp->status;
2522 }
2523
2524 return (error);
2525 }
2526
2527 static int
dpaa2_rc_con_open(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t dpcon_id,uint16_t * token)2528 dpaa2_rc_con_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2529 uint32_t dpcon_id, uint16_t *token)
2530 {
2531 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2532 struct dpaa2_cmd_header *hdr;
2533 int error;
2534
2535 if (portal == NULL || cmd == NULL || token == NULL)
2536 return (DPAA2_CMD_STAT_ERR);
2537
2538 cmd->params[0] = dpcon_id;
2539 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_OPEN);
2540 if (!error) {
2541 hdr = (struct dpaa2_cmd_header *) &cmd->header;
2542 *token = hdr->token;
2543 }
2544
2545 return (error);
2546 }
2547
2548
2549 static int
dpaa2_rc_con_close(device_t dev,device_t child,struct dpaa2_cmd * cmd)2550 dpaa2_rc_con_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2551 {
2552 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2553
2554 if (portal == NULL || cmd == NULL)
2555 return (DPAA2_CMD_STAT_ERR);
2556
2557 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_CLOSE));
2558 }
2559
2560 static int
dpaa2_rc_con_reset(device_t dev,device_t child,struct dpaa2_cmd * cmd)2561 dpaa2_rc_con_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2562 {
2563 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2564
2565 if (portal == NULL || cmd == NULL)
2566 return (DPAA2_CMD_STAT_ERR);
2567
2568 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_RESET));
2569 }
2570
2571 static int
dpaa2_rc_con_enable(device_t dev,device_t child,struct dpaa2_cmd * cmd)2572 dpaa2_rc_con_enable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2573 {
2574 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2575
2576 if (portal == NULL || cmd == NULL)
2577 return (DPAA2_CMD_STAT_ERR);
2578
2579 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_ENABLE));
2580 }
2581
2582 static int
dpaa2_rc_con_disable(device_t dev,device_t child,struct dpaa2_cmd * cmd)2583 dpaa2_rc_con_disable(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2584 {
2585 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2586
2587 if (portal == NULL || cmd == NULL)
2588 return (DPAA2_CMD_STAT_ERR);
2589
2590 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_DISABLE));
2591 }
2592
2593 static int
dpaa2_rc_con_get_attributes(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_con_attr * attr)2594 dpaa2_rc_con_get_attributes(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2595 struct dpaa2_con_attr *attr)
2596 {
2597 struct __packed con_attr_resp {
2598 uint32_t id;
2599 uint16_t chan_id;
2600 uint8_t prior_num;
2601 uint8_t _reserved1;
2602 uint64_t _reserved2[6];
2603 } *resp;
2604 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2605 int error;
2606
2607 if (portal == NULL || cmd == NULL || attr == NULL)
2608 return (DPAA2_CMD_STAT_EINVAL);
2609
2610 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_GET_ATTR);
2611 if (!error) {
2612 resp = (struct con_attr_resp *) &cmd->params[0];
2613 attr->id = resp->id;
2614 attr->chan_id = resp->chan_id;
2615 attr->prior_num = resp->prior_num;
2616 }
2617
2618 return (error);
2619 }
2620
2621 static int
dpaa2_rc_con_set_notif(device_t dev,device_t child,struct dpaa2_cmd * cmd,struct dpaa2_con_notif_cfg * cfg)2622 dpaa2_rc_con_set_notif(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2623 struct dpaa2_con_notif_cfg *cfg)
2624 {
2625 struct __packed set_notif_args {
2626 uint32_t dpio_id;
2627 uint8_t prior;
2628 uint8_t _reserved1;
2629 uint16_t _reserved2;
2630 uint64_t ctx;
2631 uint64_t _reserved3[5];
2632 } *args;
2633 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2634
2635 if (portal == NULL || cmd == NULL || cfg == NULL)
2636 return (DPAA2_CMD_STAT_ERR);
2637
2638 args = (struct set_notif_args *) &cmd->params[0];
2639 args->dpio_id = cfg->dpio_id;
2640 args->prior = cfg->prior;
2641 args->ctx = cfg->qman_ctx;
2642
2643 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_CON_SET_NOTIF));
2644 }
2645
2646 static int
dpaa2_rc_mcp_create(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t portal_id,uint32_t options,uint32_t * dpmcp_id)2647 dpaa2_rc_mcp_create(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2648 uint32_t portal_id, uint32_t options, uint32_t *dpmcp_id)
2649 {
2650 struct __packed mcp_create_args {
2651 uint32_t portal_id;
2652 uint32_t options;
2653 uint64_t _reserved[6];
2654 } *args;
2655 struct __packed mcp_create_resp {
2656 uint32_t dpmcp_id;
2657 } *resp;
2658 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2659 int error;
2660
2661 if (portal == NULL || cmd == NULL || dpmcp_id == NULL)
2662 return (DPAA2_CMD_STAT_ERR);
2663
2664 args = (struct mcp_create_args *) &cmd->params[0];
2665 args->portal_id = portal_id;
2666 args->options = options;
2667
2668 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MCP_CREATE);
2669 if (!error) {
2670 resp = (struct mcp_create_resp *) &cmd->params[0];
2671 *dpmcp_id = resp->dpmcp_id;
2672 }
2673
2674 return (error);
2675 }
2676
2677 static int
dpaa2_rc_mcp_destroy(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t dpmcp_id)2678 dpaa2_rc_mcp_destroy(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2679 uint32_t dpmcp_id)
2680 {
2681 struct __packed mcp_destroy_args {
2682 uint32_t dpmcp_id;
2683 } *args;
2684 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2685
2686 if (portal == NULL || cmd == NULL)
2687 return (DPAA2_CMD_STAT_ERR);
2688
2689 args = (struct mcp_destroy_args *) &cmd->params[0];
2690 args->dpmcp_id = dpmcp_id;
2691
2692 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MCP_DESTROY));
2693 }
2694
2695 static int
dpaa2_rc_mcp_open(device_t dev,device_t child,struct dpaa2_cmd * cmd,uint32_t dpmcp_id,uint16_t * token)2696 dpaa2_rc_mcp_open(device_t dev, device_t child, struct dpaa2_cmd *cmd,
2697 uint32_t dpmcp_id, uint16_t *token)
2698 {
2699 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2700 struct dpaa2_cmd_header *hdr;
2701 int error;
2702
2703 if (portal == NULL || cmd == NULL || token == NULL)
2704 return (DPAA2_CMD_STAT_ERR);
2705
2706 cmd->params[0] = dpmcp_id;
2707 error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_MCP_OPEN);
2708 if (!error) {
2709 hdr = (struct dpaa2_cmd_header *) &cmd->header;
2710 *token = hdr->token;
2711 }
2712
2713 return (error);
2714 }
2715
2716 static int
dpaa2_rc_mcp_close(device_t dev,device_t child,struct dpaa2_cmd * cmd)2717 dpaa2_rc_mcp_close(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2718 {
2719 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2720
2721 if (portal == NULL || cmd == NULL)
2722 return (DPAA2_CMD_STAT_ERR);
2723
2724 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MCP_CLOSE));
2725 }
2726
2727 static int
dpaa2_rc_mcp_reset(device_t dev,device_t child,struct dpaa2_cmd * cmd)2728 dpaa2_rc_mcp_reset(device_t dev, device_t child, struct dpaa2_cmd *cmd)
2729 {
2730 struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child);
2731
2732 if (portal == NULL || cmd == NULL)
2733 return (DPAA2_CMD_STAT_ERR);
2734
2735 return (dpaa2_rc_exec_cmd(portal, cmd, CMDID_MCP_RESET));
2736 }
2737
2738 /**
2739 * @brief Create and add devices for DPAA2 objects in this resource container.
2740 */
2741 static int
dpaa2_rc_discover(struct dpaa2_rc_softc * sc)2742 dpaa2_rc_discover(struct dpaa2_rc_softc *sc)
2743 {
2744 device_t rcdev = sc->dev;
2745 device_t child = sc->dev;
2746 struct dpaa2_devinfo *rcinfo = device_get_ivars(rcdev);
2747 struct dpaa2_cmd cmd;
2748 struct dpaa2_rc_attr dprc_attr;
2749 struct dpaa2_obj obj;
2750 uint32_t major, minor, rev, obj_count;
2751 uint16_t rc_token;
2752 int rc;
2753
2754 DPAA2_CMD_INIT(&cmd);
2755
2756 /* Print MC firmware version. */
2757 rc = DPAA2_CMD_MNG_GET_VERSION(rcdev, child, &cmd, &major, &minor, &rev);
2758 if (rc) {
2759 device_printf(rcdev, "%s: failed to get MC firmware version: "
2760 "error=%d\n", __func__, rc);
2761 return (ENXIO);
2762 }
2763 device_printf(rcdev, "MC firmware version: %u.%u.%u\n", major, minor,
2764 rev);
2765
2766 /* Obtain container ID associated with a given MC portal. */
2767 rc = DPAA2_CMD_MNG_GET_CONTAINER_ID(rcdev, child, &cmd, &sc->cont_id);
2768 if (rc) {
2769 device_printf(rcdev, "%s: failed to get container id: "
2770 "error=%d\n", __func__, rc);
2771 return (ENXIO);
2772 }
2773 if (bootverbose) {
2774 device_printf(rcdev, "Resource container ID: %u\n", sc->cont_id);
2775 }
2776
2777 /* Open the resource container. */
2778 rc = DPAA2_CMD_RC_OPEN(rcdev, child, &cmd, sc->cont_id, &rc_token);
2779 if (rc) {
2780 device_printf(rcdev, "%s: failed to open container: cont_id=%u, "
2781 "error=%d\n", __func__, sc->cont_id, rc);
2782 return (ENXIO);
2783 }
2784
2785 /* Obtain a number of objects in this container. */
2786 rc = DPAA2_CMD_RC_GET_OBJ_COUNT(rcdev, child, &cmd, &obj_count);
2787 if (rc) {
2788 device_printf(rcdev, "%s: failed to count objects in container: "
2789 "cont_id=%u, error=%d\n", __func__, sc->cont_id, rc);
2790 (void)DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
2791 return (ENXIO);
2792 }
2793 if (bootverbose) {
2794 device_printf(rcdev, "Objects in container: %u\n", obj_count);
2795 }
2796
2797 rc = DPAA2_CMD_RC_GET_ATTRIBUTES(rcdev, child, &cmd, &dprc_attr);
2798 if (rc) {
2799 device_printf(rcdev, "%s: failed to get attributes of the "
2800 "container: cont_id=%u, error=%d\n", __func__, sc->cont_id,
2801 rc);
2802 DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
2803 return (ENXIO);
2804 }
2805 if (bootverbose) {
2806 device_printf(rcdev, "Isolation context ID: %u\n",
2807 dprc_attr.icid);
2808 }
2809 if (rcinfo) {
2810 rcinfo->id = dprc_attr.cont_id;
2811 rcinfo->portal_id = dprc_attr.portal_id;
2812 rcinfo->icid = dprc_attr.icid;
2813 }
2814
2815 /*
2816 * Add MC portals before everything else.
2817 * TODO: Discover DPAA2 objects on-demand.
2818 */
2819 for (uint32_t i = 0; i < obj_count; i++) {
2820 rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, &cmd, i, &obj);
2821 if (rc) {
2822 continue; /* Skip silently for now. */
2823 }
2824 if (obj.type != DPAA2_DEV_MCP) {
2825 continue;
2826 }
2827 dpaa2_rc_add_managed_child(sc, &cmd, &obj);
2828 }
2829 /* Probe and attach MC portals. */
2830 bus_generic_probe(rcdev);
2831 rc = bus_generic_attach(rcdev);
2832 if (rc) {
2833 DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
2834 return (rc);
2835 }
2836
2837 /* Add managed devices (except DPMCPs) to the resource container. */
2838 for (uint32_t i = 0; i < obj_count; i++) {
2839 rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, &cmd, i, &obj);
2840 if (rc && bootverbose) {
2841 if (rc == DPAA2_CMD_STAT_UNKNOWN_OBJ) {
2842 device_printf(rcdev, "%s: skip unsupported "
2843 "DPAA2 object: idx=%u\n", __func__, i);
2844 continue;
2845 } else {
2846 device_printf(rcdev, "%s: failed to get "
2847 "information about DPAA2 object: idx=%u, "
2848 "error=%d\n", __func__, i, rc);
2849 continue;
2850 }
2851 }
2852 if (obj.type == DPAA2_DEV_MCP) {
2853 continue; /* Already added. */
2854 }
2855 dpaa2_rc_add_managed_child(sc, &cmd, &obj);
2856 }
2857 /* Probe and attach managed devices properly. */
2858 bus_generic_probe(rcdev);
2859 rc = bus_generic_attach(rcdev);
2860 if (rc) {
2861 DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
2862 return (rc);
2863 }
2864
2865 /* Add other devices to the resource container. */
2866 for (uint32_t i = 0; i < obj_count; i++) {
2867 rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, &cmd, i, &obj);
2868 if (rc == DPAA2_CMD_STAT_UNKNOWN_OBJ && bootverbose) {
2869 device_printf(rcdev, "%s: skip unsupported DPAA2 "
2870 "object: idx=%u\n", __func__, i);
2871 continue;
2872 } else if (rc) {
2873 device_printf(rcdev, "%s: failed to get object: "
2874 "idx=%u, error=%d\n", __func__, i, rc);
2875 continue;
2876 }
2877 dpaa2_rc_add_child(sc, &cmd, &obj);
2878 }
2879
2880 DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
2881
2882 /* Probe and attach the rest of devices. */
2883 bus_generic_probe(rcdev);
2884 return (bus_generic_attach(rcdev));
2885 }
2886
2887 /**
2888 * @brief Add a new DPAA2 device to the resource container bus.
2889 */
2890 static int
dpaa2_rc_add_child(struct dpaa2_rc_softc * sc,struct dpaa2_cmd * cmd,struct dpaa2_obj * obj)2891 dpaa2_rc_add_child(struct dpaa2_rc_softc *sc, struct dpaa2_cmd *cmd,
2892 struct dpaa2_obj *obj)
2893 {
2894 device_t rcdev, dev;
2895 struct dpaa2_devinfo *rcinfo;
2896 struct dpaa2_devinfo *dinfo;
2897 struct resource_spec *res_spec;
2898 const char *devclass;
2899 int dpio_n = 0; /* to limit DPIOs by # of CPUs */
2900 int dpcon_n = 0; /* to limit DPCONs by # of CPUs */
2901 int rid, error;
2902
2903 rcdev = sc->dev;
2904 rcinfo = device_get_ivars(rcdev);
2905
2906 switch (obj->type) {
2907 case DPAA2_DEV_NI:
2908 devclass = "dpaa2_ni";
2909 res_spec = dpaa2_ni_spec;
2910 break;
2911 default:
2912 return (ENXIO);
2913 }
2914
2915 /* Add a device for the DPAA2 object. */
2916 dev = device_add_child(rcdev, devclass, -1);
2917 if (dev == NULL) {
2918 device_printf(rcdev, "%s: failed to add a device for DPAA2 "
2919 "object: type=%s, id=%u\n", __func__, dpaa2_ttos(obj->type),
2920 obj->id);
2921 return (ENXIO);
2922 }
2923
2924 /* Allocate devinfo for a child. */
2925 dinfo = malloc(sizeof(struct dpaa2_devinfo), M_DPAA2_RC,
2926 M_WAITOK | M_ZERO);
2927 if (!dinfo) {
2928 device_printf(rcdev, "%s: failed to allocate dpaa2_devinfo "
2929 "for: type=%s, id=%u\n", __func__, dpaa2_ttos(obj->type),
2930 obj->id);
2931 return (ENXIO);
2932 }
2933 device_set_ivars(dev, dinfo);
2934
2935 dinfo->pdev = rcdev;
2936 dinfo->dev = dev;
2937 dinfo->id = obj->id;
2938 dinfo->dtype = obj->type;
2939 dinfo->portal = NULL;
2940 /* Children share their parent container's ICID and portal ID. */
2941 dinfo->icid = rcinfo->icid;
2942 dinfo->portal_id = rcinfo->portal_id;
2943 /* MSI configuration */
2944 dinfo->msi.msi_msgnum = obj->irq_count;
2945 dinfo->msi.msi_alloc = 0;
2946 dinfo->msi.msi_handlers = 0;
2947
2948 /* Initialize a resource list for the child. */
2949 resource_list_init(&dinfo->resources);
2950
2951 /* Add DPAA2-specific resources to the resource list. */
2952 for (; res_spec && res_spec->type != -1; res_spec++) {
2953 if (res_spec->type < DPAA2_DEV_MC)
2954 continue; /* Skip non-DPAA2 resource. */
2955 rid = res_spec->rid;
2956
2957 /* Limit DPIOs and DPCONs by number of CPUs. */
2958 if (res_spec->type == DPAA2_DEV_IO && dpio_n >= mp_ncpus) {
2959 dpio_n++;
2960 continue;
2961 }
2962 if (res_spec->type == DPAA2_DEV_CON && dpcon_n >= mp_ncpus) {
2963 dpcon_n++;
2964 continue;
2965 }
2966
2967 error = dpaa2_rc_add_res(rcdev, dev, res_spec->type, &rid,
2968 res_spec->flags);
2969 if (error)
2970 device_printf(rcdev, "%s: dpaa2_rc_add_res() failed: "
2971 "error=%d\n", __func__, error);
2972
2973 if (res_spec->type == DPAA2_DEV_IO)
2974 dpio_n++;
2975 if (res_spec->type == DPAA2_DEV_CON)
2976 dpcon_n++;
2977 }
2978
2979 return (0);
2980 }
2981
2982 /**
2983 * @brief Add a new managed DPAA2 device to the resource container bus.
2984 *
2985 * There are DPAA2 objects (DPIO, DPBP) which have their own drivers and can be
2986 * allocated as resources or associated with the other DPAA2 objects. This
2987 * function is supposed to discover such managed objects in the resource
2988 * container and add them as children to perform a proper initialization.
2989 *
2990 * NOTE: It must be called together with bus_generic_probe() and
2991 * bus_generic_attach() before dpaa2_rc_add_child().
2992 */
2993 static int
dpaa2_rc_add_managed_child(struct dpaa2_rc_softc * sc,struct dpaa2_cmd * cmd,struct dpaa2_obj * obj)2994 dpaa2_rc_add_managed_child(struct dpaa2_rc_softc *sc, struct dpaa2_cmd *cmd,
2995 struct dpaa2_obj *obj)
2996 {
2997 device_t rcdev, dev, child;
2998 struct dpaa2_devinfo *rcinfo, *dinfo;
2999 struct dpaa2_rc_obj_region reg;
3000 struct resource_spec *res_spec;
3001 const char *devclass;
3002 uint64_t start, end, count;
3003 uint32_t flags = 0;
3004 int rid, error;
3005
3006 rcdev = sc->dev;
3007 child = sc->dev;
3008 rcinfo = device_get_ivars(rcdev);
3009
3010 switch (obj->type) {
3011 case DPAA2_DEV_IO:
3012 devclass = "dpaa2_io";
3013 res_spec = dpaa2_io_spec;
3014 flags = DPAA2_MC_DEV_ALLOCATABLE | DPAA2_MC_DEV_SHAREABLE;
3015 break;
3016 case DPAA2_DEV_BP:
3017 devclass = "dpaa2_bp";
3018 res_spec = dpaa2_bp_spec;
3019 flags = DPAA2_MC_DEV_ALLOCATABLE;
3020 break;
3021 case DPAA2_DEV_CON:
3022 devclass = "dpaa2_con";
3023 res_spec = dpaa2_con_spec;
3024 flags = DPAA2_MC_DEV_ALLOCATABLE;
3025 break;
3026 case DPAA2_DEV_MAC:
3027 devclass = "dpaa2_mac";
3028 res_spec = dpaa2_mac_spec;
3029 flags = DPAA2_MC_DEV_ASSOCIATED;
3030 break;
3031 case DPAA2_DEV_MCP:
3032 devclass = "dpaa2_mcp";
3033 res_spec = NULL;
3034 flags = DPAA2_MC_DEV_ALLOCATABLE | DPAA2_MC_DEV_SHAREABLE;
3035 break;
3036 default:
3037 /* Only managed devices above are supported. */
3038 return (EINVAL);
3039 }
3040
3041 /* Add a device for the DPAA2 object. */
3042 dev = device_add_child(rcdev, devclass, -1);
3043 if (dev == NULL) {
3044 device_printf(rcdev, "%s: failed to add a device for DPAA2 "
3045 "object: type=%s, id=%u\n", __func__, dpaa2_ttos(obj->type),
3046 obj->id);
3047 return (ENXIO);
3048 }
3049
3050 /* Allocate devinfo for the child. */
3051 dinfo = malloc(sizeof(struct dpaa2_devinfo), M_DPAA2_RC,
3052 M_WAITOK | M_ZERO);
3053 if (!dinfo) {
3054 device_printf(rcdev, "%s: failed to allocate dpaa2_devinfo "
3055 "for: type=%s, id=%u\n", __func__, dpaa2_ttos(obj->type),
3056 obj->id);
3057 return (ENXIO);
3058 }
3059 device_set_ivars(dev, dinfo);
3060
3061 dinfo->pdev = rcdev;
3062 dinfo->dev = dev;
3063 dinfo->id = obj->id;
3064 dinfo->dtype = obj->type;
3065 dinfo->portal = NULL;
3066 /* Children share their parent container's ICID and portal ID. */
3067 dinfo->icid = rcinfo->icid;
3068 dinfo->portal_id = rcinfo->portal_id;
3069 /* MSI configuration */
3070 dinfo->msi.msi_msgnum = obj->irq_count;
3071 dinfo->msi.msi_alloc = 0;
3072 dinfo->msi.msi_handlers = 0;
3073
3074 /* Initialize a resource list for the child. */
3075 resource_list_init(&dinfo->resources);
3076
3077 /* Add memory regions to the resource list. */
3078 for (uint8_t i = 0; i < obj->reg_count; i++) {
3079 error = DPAA2_CMD_RC_GET_OBJ_REGION(rcdev, child, cmd, obj->id,
3080 i, obj->type, ®);
3081 if (error) {
3082 device_printf(rcdev, "%s: failed to obtain memory "
3083 "region for type=%s, id=%u, reg_idx=%u: error=%d\n",
3084 __func__, dpaa2_ttos(obj->type), obj->id, i, error);
3085 continue;
3086 }
3087 count = reg.size;
3088 start = reg.base_paddr + reg.base_offset;
3089 end = reg.base_paddr + reg.base_offset + reg.size - 1;
3090
3091 resource_list_add(&dinfo->resources, SYS_RES_MEMORY, i, start,
3092 end, count);
3093 }
3094
3095 /* Add DPAA2-specific resources to the resource list. */
3096 for (; res_spec && res_spec->type != -1; res_spec++) {
3097 if (res_spec->type < DPAA2_DEV_MC)
3098 continue; /* Skip non-DPAA2 resource. */
3099 rid = res_spec->rid;
3100
3101 error = dpaa2_rc_add_res(rcdev, dev, res_spec->type, &rid,
3102 res_spec->flags);
3103 if (error)
3104 device_printf(rcdev, "%s: dpaa2_rc_add_res() failed: "
3105 "error=%d\n", __func__, error);
3106 }
3107
3108 /* Inform MC about a new managed device. */
3109 error = DPAA2_MC_MANAGE_DEV(rcdev, dev, flags);
3110 if (error) {
3111 device_printf(rcdev, "%s: failed to add a managed DPAA2 device: "
3112 "type=%s, id=%u, error=%d\n", __func__,
3113 dpaa2_ttos(obj->type), obj->id, error);
3114 return (ENXIO);
3115 }
3116
3117 return (0);
3118 }
3119
3120 /**
3121 * @brief Configure given IRQ using MC command interface.
3122 */
3123 static int
dpaa2_rc_configure_irq(device_t rcdev,device_t child,int rid,uint64_t addr,uint32_t data)3124 dpaa2_rc_configure_irq(device_t rcdev, device_t child, int rid, uint64_t addr,
3125 uint32_t data)
3126 {
3127 struct dpaa2_devinfo *rcinfo;
3128 struct dpaa2_devinfo *dinfo;
3129 struct dpaa2_cmd cmd;
3130 uint16_t rc_token;
3131 int rc = EINVAL;
3132
3133 DPAA2_CMD_INIT(&cmd);
3134
3135 if (device_get_parent(child) == rcdev && rid >= 1) {
3136 rcinfo = device_get_ivars(rcdev);
3137 dinfo = device_get_ivars(child);
3138
3139 rc = DPAA2_CMD_RC_OPEN(rcdev, child, &cmd, rcinfo->id,
3140 &rc_token);
3141 if (rc) {
3142 device_printf(rcdev, "%s: failed to open DPRC: "
3143 "error=%d\n", __func__, rc);
3144 return (ENODEV);
3145 }
3146 /* Set MSI address and value. */
3147 rc = DPAA2_CMD_RC_SET_OBJ_IRQ(rcdev, child, &cmd, rid - 1, addr,
3148 data, rid, dinfo->id, dinfo->dtype);
3149 if (rc) {
3150 device_printf(rcdev, "%s: failed to setup IRQ: "
3151 "rid=%d, addr=%jx, data=%x, error=%d\n", __func__,
3152 rid, addr, data, rc);
3153 return (ENODEV);
3154 }
3155 rc = DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd);
3156 if (rc) {
3157 device_printf(rcdev, "%s: failed to close DPRC: "
3158 "error=%d\n", __func__, rc);
3159 return (ENODEV);
3160 }
3161 rc = 0;
3162 }
3163
3164 return (rc);
3165 }
3166
3167 /**
3168 * @brief General implementation of the MC command to enable IRQ.
3169 */
3170 static int
dpaa2_rc_enable_irq(struct dpaa2_mcp * mcp,struct dpaa2_cmd * cmd,uint8_t irq_idx,bool enable,uint16_t cmdid)3171 dpaa2_rc_enable_irq(struct dpaa2_mcp *mcp, struct dpaa2_cmd *cmd,
3172 uint8_t irq_idx, bool enable, uint16_t cmdid)
3173 {
3174 struct __packed enable_irq_args {
3175 uint8_t enable;
3176 uint8_t _reserved1;
3177 uint16_t _reserved2;
3178 uint8_t irq_idx;
3179 uint8_t _reserved3;
3180 uint16_t _reserved4;
3181 uint64_t _reserved5[6];
3182 } *args;
3183
3184 if (!mcp || !cmd)
3185 return (DPAA2_CMD_STAT_ERR);
3186
3187 args = (struct enable_irq_args *) &cmd->params[0];
3188 args->irq_idx = irq_idx;
3189 args->enable = enable == 0u ? 0u : 1u;
3190
3191 return (dpaa2_rc_exec_cmd(mcp, cmd, cmdid));
3192 }
3193
3194 /**
3195 * @brief Sends a command to MC and waits for response.
3196 */
3197 static int
dpaa2_rc_exec_cmd(struct dpaa2_mcp * mcp,struct dpaa2_cmd * cmd,uint16_t cmdid)3198 dpaa2_rc_exec_cmd(struct dpaa2_mcp *mcp, struct dpaa2_cmd *cmd, uint16_t cmdid)
3199 {
3200 struct dpaa2_cmd_header *hdr;
3201 uint16_t flags;
3202 int error;
3203
3204 if (!mcp || !cmd)
3205 return (DPAA2_CMD_STAT_ERR);
3206
3207 /* Prepare a command for the MC hardware. */
3208 hdr = (struct dpaa2_cmd_header *) &cmd->header;
3209 hdr->cmdid = cmdid;
3210 hdr->status = DPAA2_CMD_STAT_READY;
3211
3212 DPAA2_MCP_LOCK(mcp, &flags);
3213 if (flags & DPAA2_PORTAL_DESTROYED) {
3214 /* Terminate operation if portal is destroyed. */
3215 DPAA2_MCP_UNLOCK(mcp);
3216 return (DPAA2_CMD_STAT_INVALID_STATE);
3217 }
3218
3219 /* Send a command to MC and wait for the result. */
3220 dpaa2_rc_send_cmd(mcp, cmd);
3221 error = dpaa2_rc_wait_for_cmd(mcp, cmd);
3222 if (error) {
3223 DPAA2_MCP_UNLOCK(mcp);
3224 return (DPAA2_CMD_STAT_ERR);
3225 }
3226 if (hdr->status != DPAA2_CMD_STAT_OK) {
3227 DPAA2_MCP_UNLOCK(mcp);
3228 return (int)(hdr->status);
3229 }
3230
3231 DPAA2_MCP_UNLOCK(mcp);
3232
3233 return (DPAA2_CMD_STAT_OK);
3234 }
3235
3236 /**
3237 * @brief Writes a command to the MC command portal.
3238 */
3239 static int
dpaa2_rc_send_cmd(struct dpaa2_mcp * mcp,struct dpaa2_cmd * cmd)3240 dpaa2_rc_send_cmd(struct dpaa2_mcp *mcp, struct dpaa2_cmd *cmd)
3241 {
3242 /* Write command parameters. */
3243 for (uint32_t i = 1; i <= DPAA2_CMD_PARAMS_N; i++)
3244 bus_write_8(mcp->map, sizeof(uint64_t) * i, cmd->params[i-1]);
3245
3246 bus_barrier(mcp->map, 0, sizeof(struct dpaa2_cmd),
3247 BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
3248
3249 /* Write command header to trigger execution. */
3250 bus_write_8(mcp->map, 0, cmd->header);
3251
3252 return (0);
3253 }
3254
3255 /**
3256 * @brief Polls the MC command portal in order to receive a result of the
3257 * command execution.
3258 */
3259 static int
dpaa2_rc_wait_for_cmd(struct dpaa2_mcp * mcp,struct dpaa2_cmd * cmd)3260 dpaa2_rc_wait_for_cmd(struct dpaa2_mcp *mcp, struct dpaa2_cmd *cmd)
3261 {
3262 struct dpaa2_cmd_header *hdr;
3263 uint64_t val;
3264 uint32_t i;
3265
3266 /* Wait for a command execution result from the MC hardware. */
3267 for (i = 1; i <= CMD_SPIN_ATTEMPTS; i++) {
3268 val = bus_read_8(mcp->map, 0);
3269 hdr = (struct dpaa2_cmd_header *) &val;
3270 if (hdr->status != DPAA2_CMD_STAT_READY) {
3271 break;
3272 }
3273 DELAY(CMD_SPIN_TIMEOUT);
3274 }
3275
3276 if (i > CMD_SPIN_ATTEMPTS) {
3277 /* Return an error on expired timeout. */
3278 return (DPAA2_CMD_STAT_TIMEOUT);
3279 } else {
3280 /* Read command response. */
3281 cmd->header = val;
3282 for (i = 1; i <= DPAA2_CMD_PARAMS_N; i++) {
3283 cmd->params[i-1] =
3284 bus_read_8(mcp->map, i * sizeof(uint64_t));
3285 }
3286 }
3287
3288 return (DPAA2_CMD_STAT_OK);
3289 }
3290
3291 /**
3292 * @brief Reserve a DPAA2-specific device of the given devtype for the child.
3293 */
3294 static int
dpaa2_rc_add_res(device_t rcdev,device_t child,enum dpaa2_dev_type devtype,int * rid,int flags)3295 dpaa2_rc_add_res(device_t rcdev, device_t child, enum dpaa2_dev_type devtype,
3296 int *rid, int flags)
3297 {
3298 device_t dpaa2_dev;
3299 struct dpaa2_devinfo *dinfo = device_get_ivars(child);
3300 struct resource *res;
3301 bool shared = false;
3302 int error;
3303
3304 /* Request a free DPAA2 device of the given type from MC. */
3305 error = DPAA2_MC_GET_FREE_DEV(rcdev, &dpaa2_dev, devtype);
3306 if (error && !(flags & RF_SHAREABLE)) {
3307 device_printf(rcdev, "%s: failed to obtain a free %s (rid=%d) "
3308 "for: %s (id=%u)\n", __func__, dpaa2_ttos(devtype), *rid,
3309 dpaa2_ttos(dinfo->dtype), dinfo->id);
3310 return (error);
3311 }
3312
3313 /* Request a shared DPAA2 device of the given type from MC. */
3314 if (error) {
3315 error = DPAA2_MC_GET_SHARED_DEV(rcdev, &dpaa2_dev, devtype);
3316 if (error) {
3317 device_printf(rcdev, "%s: failed to obtain a shared "
3318 "%s (rid=%d) for: %s (id=%u)\n", __func__,
3319 dpaa2_ttos(devtype), *rid, dpaa2_ttos(dinfo->dtype),
3320 dinfo->id);
3321 return (error);
3322 }
3323 shared = true;
3324 }
3325
3326 /* Add DPAA2 device to the resource list of the child device. */
3327 resource_list_add(&dinfo->resources, devtype, *rid,
3328 (rman_res_t) dpaa2_dev, (rman_res_t) dpaa2_dev, 1);
3329
3330 /* Reserve a newly added DPAA2 resource. */
3331 res = resource_list_reserve(&dinfo->resources, rcdev, child, devtype,
3332 rid, (rman_res_t) dpaa2_dev, (rman_res_t) dpaa2_dev, 1,
3333 flags & ~RF_ACTIVE);
3334 if (!res) {
3335 device_printf(rcdev, "%s: failed to reserve %s (rid=%d) for: %s "
3336 "(id=%u)\n", __func__, dpaa2_ttos(devtype), *rid,
3337 dpaa2_ttos(dinfo->dtype), dinfo->id);
3338 return (EBUSY);
3339 }
3340
3341 /* Reserve a shared DPAA2 device of the given type. */
3342 if (shared) {
3343 error = DPAA2_MC_RESERVE_DEV(rcdev, dpaa2_dev, devtype);
3344 if (error) {
3345 device_printf(rcdev, "%s: failed to reserve a shared "
3346 "%s (rid=%d) for: %s (id=%u)\n", __func__,
3347 dpaa2_ttos(devtype), *rid, dpaa2_ttos(dinfo->dtype),
3348 dinfo->id);
3349 return (error);
3350 }
3351 }
3352
3353 return (0);
3354 }
3355
3356 static int
dpaa2_rc_print_type(struct resource_list * rl,enum dpaa2_dev_type type)3357 dpaa2_rc_print_type(struct resource_list *rl, enum dpaa2_dev_type type)
3358 {
3359 struct dpaa2_devinfo *dinfo;
3360 struct resource_list_entry *rle;
3361 uint32_t prev_id;
3362 int printed = 0, series = 0;
3363 int retval = 0;
3364
3365 STAILQ_FOREACH(rle, rl, link) {
3366 if (rle->type == type) {
3367 dinfo = device_get_ivars((device_t) rle->start);
3368
3369 if (printed == 0) {
3370 retval += printf(" %s (id=",
3371 dpaa2_ttos(dinfo->dtype));
3372 } else {
3373 if (dinfo->id == prev_id + 1) {
3374 if (series == 0) {
3375 series = 1;
3376 retval += printf("-");
3377 }
3378 } else {
3379 if (series == 1) {
3380 retval += printf("%u", prev_id);
3381 series = 0;
3382 }
3383 retval += printf(",");
3384 }
3385 }
3386 printed++;
3387
3388 if (series == 0)
3389 retval += printf("%u", dinfo->id);
3390 prev_id = dinfo->id;
3391 }
3392 }
3393 if (printed) {
3394 if (series == 1)
3395 retval += printf("%u", prev_id);
3396 retval += printf(")");
3397 }
3398
3399 return (retval);
3400 }
3401
3402 static int
dpaa2_rc_reset_cmd_params(struct dpaa2_cmd * cmd)3403 dpaa2_rc_reset_cmd_params(struct dpaa2_cmd *cmd)
3404 {
3405 if (cmd != NULL) {
3406 memset(cmd->params, 0, sizeof(cmd->params[0]) *
3407 DPAA2_CMD_PARAMS_N);
3408 }
3409 return (0);
3410 }
3411
3412 static struct dpaa2_mcp *
dpaa2_rc_select_portal(device_t dev,device_t child)3413 dpaa2_rc_select_portal(device_t dev, device_t child)
3414 {
3415 struct dpaa2_devinfo *dinfo = device_get_ivars(dev);
3416 struct dpaa2_devinfo *cinfo = device_get_ivars(child);
3417
3418 if (cinfo == NULL || dinfo == NULL || dinfo->dtype != DPAA2_DEV_RC)
3419 return (NULL);
3420 return (cinfo->portal != NULL ? cinfo->portal : dinfo->portal);
3421 }
3422
3423 static device_method_t dpaa2_rc_methods[] = {
3424 /* Device interface */
3425 DEVMETHOD(device_probe, dpaa2_rc_probe),
3426 DEVMETHOD(device_attach, dpaa2_rc_attach),
3427 DEVMETHOD(device_detach, dpaa2_rc_detach),
3428
3429 /* Bus interface */
3430 DEVMETHOD(bus_get_resource_list, dpaa2_rc_get_resource_list),
3431 DEVMETHOD(bus_delete_resource, dpaa2_rc_delete_resource),
3432 DEVMETHOD(bus_alloc_resource, dpaa2_rc_alloc_resource),
3433 DEVMETHOD(bus_release_resource, dpaa2_rc_release_resource),
3434 DEVMETHOD(bus_child_deleted, dpaa2_rc_child_deleted),
3435 DEVMETHOD(bus_child_detached, dpaa2_rc_child_detached),
3436 DEVMETHOD(bus_setup_intr, dpaa2_rc_setup_intr),
3437 DEVMETHOD(bus_teardown_intr, dpaa2_rc_teardown_intr),
3438 DEVMETHOD(bus_print_child, dpaa2_rc_print_child),
3439 DEVMETHOD(bus_add_child, device_add_child_ordered),
3440 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
3441 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
3442 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
3443 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
3444 DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
3445
3446 /* Pseudo-PCI interface */
3447 DEVMETHOD(pci_alloc_msi, dpaa2_rc_alloc_msi),
3448 DEVMETHOD(pci_release_msi, dpaa2_rc_release_msi),
3449 DEVMETHOD(pci_msi_count, dpaa2_rc_msi_count),
3450 DEVMETHOD(pci_get_id, dpaa2_rc_get_id),
3451
3452 /* DPAA2 MC command interface */
3453 DEVMETHOD(dpaa2_cmd_mng_get_version, dpaa2_rc_mng_get_version),
3454 DEVMETHOD(dpaa2_cmd_mng_get_soc_version, dpaa2_rc_mng_get_soc_version),
3455 DEVMETHOD(dpaa2_cmd_mng_get_container_id, dpaa2_rc_mng_get_container_id),
3456 /* DPRC commands */
3457 DEVMETHOD(dpaa2_cmd_rc_open, dpaa2_rc_open),
3458 DEVMETHOD(dpaa2_cmd_rc_close, dpaa2_rc_close),
3459 DEVMETHOD(dpaa2_cmd_rc_get_obj_count, dpaa2_rc_get_obj_count),
3460 DEVMETHOD(dpaa2_cmd_rc_get_obj, dpaa2_rc_get_obj),
3461 DEVMETHOD(dpaa2_cmd_rc_get_obj_descriptor, dpaa2_rc_get_obj_descriptor),
3462 DEVMETHOD(dpaa2_cmd_rc_get_attributes, dpaa2_rc_get_attributes),
3463 DEVMETHOD(dpaa2_cmd_rc_get_obj_region, dpaa2_rc_get_obj_region),
3464 DEVMETHOD(dpaa2_cmd_rc_get_api_version, dpaa2_rc_get_api_version),
3465 DEVMETHOD(dpaa2_cmd_rc_set_irq_enable, dpaa2_rc_set_irq_enable),
3466 DEVMETHOD(dpaa2_cmd_rc_set_obj_irq, dpaa2_rc_set_obj_irq),
3467 DEVMETHOD(dpaa2_cmd_rc_get_conn, dpaa2_rc_get_conn),
3468 /* DPNI commands */
3469 DEVMETHOD(dpaa2_cmd_ni_open, dpaa2_rc_ni_open),
3470 DEVMETHOD(dpaa2_cmd_ni_close, dpaa2_rc_ni_close),
3471 DEVMETHOD(dpaa2_cmd_ni_enable, dpaa2_rc_ni_enable),
3472 DEVMETHOD(dpaa2_cmd_ni_disable, dpaa2_rc_ni_disable),
3473 DEVMETHOD(dpaa2_cmd_ni_get_api_version, dpaa2_rc_ni_get_api_version),
3474 DEVMETHOD(dpaa2_cmd_ni_reset, dpaa2_rc_ni_reset),
3475 DEVMETHOD(dpaa2_cmd_ni_get_attributes, dpaa2_rc_ni_get_attributes),
3476 DEVMETHOD(dpaa2_cmd_ni_set_buf_layout, dpaa2_rc_ni_set_buf_layout),
3477 DEVMETHOD(dpaa2_cmd_ni_get_tx_data_off, dpaa2_rc_ni_get_tx_data_offset),
3478 DEVMETHOD(dpaa2_cmd_ni_get_port_mac_addr, dpaa2_rc_ni_get_port_mac_addr),
3479 DEVMETHOD(dpaa2_cmd_ni_set_prim_mac_addr, dpaa2_rc_ni_set_prim_mac_addr),
3480 DEVMETHOD(dpaa2_cmd_ni_get_prim_mac_addr, dpaa2_rc_ni_get_prim_mac_addr),
3481 DEVMETHOD(dpaa2_cmd_ni_set_link_cfg, dpaa2_rc_ni_set_link_cfg),
3482 DEVMETHOD(dpaa2_cmd_ni_get_link_cfg, dpaa2_rc_ni_get_link_cfg),
3483 DEVMETHOD(dpaa2_cmd_ni_get_link_state, dpaa2_rc_ni_get_link_state),
3484 DEVMETHOD(dpaa2_cmd_ni_set_qos_table, dpaa2_rc_ni_set_qos_table),
3485 DEVMETHOD(dpaa2_cmd_ni_clear_qos_table, dpaa2_rc_ni_clear_qos_table),
3486 DEVMETHOD(dpaa2_cmd_ni_set_pools, dpaa2_rc_ni_set_pools),
3487 DEVMETHOD(dpaa2_cmd_ni_set_err_behavior,dpaa2_rc_ni_set_err_behavior),
3488 DEVMETHOD(dpaa2_cmd_ni_get_queue, dpaa2_rc_ni_get_queue),
3489 DEVMETHOD(dpaa2_cmd_ni_set_queue, dpaa2_rc_ni_set_queue),
3490 DEVMETHOD(dpaa2_cmd_ni_get_qdid, dpaa2_rc_ni_get_qdid),
3491 DEVMETHOD(dpaa2_cmd_ni_add_mac_addr, dpaa2_rc_ni_add_mac_addr),
3492 DEVMETHOD(dpaa2_cmd_ni_remove_mac_addr, dpaa2_rc_ni_remove_mac_addr),
3493 DEVMETHOD(dpaa2_cmd_ni_clear_mac_filters, dpaa2_rc_ni_clear_mac_filters),
3494 DEVMETHOD(dpaa2_cmd_ni_set_mfl, dpaa2_rc_ni_set_mfl),
3495 DEVMETHOD(dpaa2_cmd_ni_set_offload, dpaa2_rc_ni_set_offload),
3496 DEVMETHOD(dpaa2_cmd_ni_set_irq_mask, dpaa2_rc_ni_set_irq_mask),
3497 DEVMETHOD(dpaa2_cmd_ni_set_irq_enable, dpaa2_rc_ni_set_irq_enable),
3498 DEVMETHOD(dpaa2_cmd_ni_get_irq_status, dpaa2_rc_ni_get_irq_status),
3499 DEVMETHOD(dpaa2_cmd_ni_set_uni_promisc, dpaa2_rc_ni_set_uni_promisc),
3500 DEVMETHOD(dpaa2_cmd_ni_set_multi_promisc, dpaa2_rc_ni_set_multi_promisc),
3501 DEVMETHOD(dpaa2_cmd_ni_get_statistics, dpaa2_rc_ni_get_statistics),
3502 DEVMETHOD(dpaa2_cmd_ni_set_rx_tc_dist, dpaa2_rc_ni_set_rx_tc_dist),
3503 /* DPIO commands */
3504 DEVMETHOD(dpaa2_cmd_io_open, dpaa2_rc_io_open),
3505 DEVMETHOD(dpaa2_cmd_io_close, dpaa2_rc_io_close),
3506 DEVMETHOD(dpaa2_cmd_io_enable, dpaa2_rc_io_enable),
3507 DEVMETHOD(dpaa2_cmd_io_disable, dpaa2_rc_io_disable),
3508 DEVMETHOD(dpaa2_cmd_io_reset, dpaa2_rc_io_reset),
3509 DEVMETHOD(dpaa2_cmd_io_get_attributes, dpaa2_rc_io_get_attributes),
3510 DEVMETHOD(dpaa2_cmd_io_set_irq_mask, dpaa2_rc_io_set_irq_mask),
3511 DEVMETHOD(dpaa2_cmd_io_get_irq_status, dpaa2_rc_io_get_irq_status),
3512 DEVMETHOD(dpaa2_cmd_io_set_irq_enable, dpaa2_rc_io_set_irq_enable),
3513 DEVMETHOD(dpaa2_cmd_io_add_static_dq_chan, dpaa2_rc_io_add_static_dq_chan),
3514 /* DPBP commands */
3515 DEVMETHOD(dpaa2_cmd_bp_open, dpaa2_rc_bp_open),
3516 DEVMETHOD(dpaa2_cmd_bp_close, dpaa2_rc_bp_close),
3517 DEVMETHOD(dpaa2_cmd_bp_enable, dpaa2_rc_bp_enable),
3518 DEVMETHOD(dpaa2_cmd_bp_disable, dpaa2_rc_bp_disable),
3519 DEVMETHOD(dpaa2_cmd_bp_reset, dpaa2_rc_bp_reset),
3520 DEVMETHOD(dpaa2_cmd_bp_get_attributes, dpaa2_rc_bp_get_attributes),
3521 /* DPMAC commands */
3522 DEVMETHOD(dpaa2_cmd_mac_open, dpaa2_rc_mac_open),
3523 DEVMETHOD(dpaa2_cmd_mac_close, dpaa2_rc_mac_close),
3524 DEVMETHOD(dpaa2_cmd_mac_reset, dpaa2_rc_mac_reset),
3525 DEVMETHOD(dpaa2_cmd_mac_mdio_read, dpaa2_rc_mac_mdio_read),
3526 DEVMETHOD(dpaa2_cmd_mac_mdio_write, dpaa2_rc_mac_mdio_write),
3527 DEVMETHOD(dpaa2_cmd_mac_get_addr, dpaa2_rc_mac_get_addr),
3528 DEVMETHOD(dpaa2_cmd_mac_get_attributes, dpaa2_rc_mac_get_attributes),
3529 DEVMETHOD(dpaa2_cmd_mac_set_link_state, dpaa2_rc_mac_set_link_state),
3530 DEVMETHOD(dpaa2_cmd_mac_set_irq_mask, dpaa2_rc_mac_set_irq_mask),
3531 DEVMETHOD(dpaa2_cmd_mac_set_irq_enable, dpaa2_rc_mac_set_irq_enable),
3532 DEVMETHOD(dpaa2_cmd_mac_get_irq_status, dpaa2_rc_mac_get_irq_status),
3533 /* DPCON commands */
3534 DEVMETHOD(dpaa2_cmd_con_open, dpaa2_rc_con_open),
3535 DEVMETHOD(dpaa2_cmd_con_close, dpaa2_rc_con_close),
3536 DEVMETHOD(dpaa2_cmd_con_reset, dpaa2_rc_con_reset),
3537 DEVMETHOD(dpaa2_cmd_con_enable, dpaa2_rc_con_enable),
3538 DEVMETHOD(dpaa2_cmd_con_disable, dpaa2_rc_con_disable),
3539 DEVMETHOD(dpaa2_cmd_con_get_attributes, dpaa2_rc_con_get_attributes),
3540 DEVMETHOD(dpaa2_cmd_con_set_notif, dpaa2_rc_con_set_notif),
3541 /* DPMCP commands */
3542 DEVMETHOD(dpaa2_cmd_mcp_create, dpaa2_rc_mcp_create),
3543 DEVMETHOD(dpaa2_cmd_mcp_destroy, dpaa2_rc_mcp_destroy),
3544 DEVMETHOD(dpaa2_cmd_mcp_open, dpaa2_rc_mcp_open),
3545 DEVMETHOD(dpaa2_cmd_mcp_close, dpaa2_rc_mcp_close),
3546 DEVMETHOD(dpaa2_cmd_mcp_reset, dpaa2_rc_mcp_reset),
3547
3548 DEVMETHOD_END
3549 };
3550
3551 static driver_t dpaa2_rc_driver = {
3552 "dpaa2_rc",
3553 dpaa2_rc_methods,
3554 sizeof(struct dpaa2_rc_softc),
3555 };
3556
3557 /* For root container */
3558 DRIVER_MODULE(dpaa2_rc, dpaa2_mc, dpaa2_rc_driver, 0, 0);
3559 /* For child containers */
3560 DRIVER_MODULE(dpaa2_rc, dpaa2_rc, dpaa2_rc_driver, 0, 0);
3561