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