xref: /freebsd/sys/dev/dpaa2/dpaa2_rc.c (revision 257e70f1d5ee61037c8c59b116538d3b6b1427a2)
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
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
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
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 *
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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, &reg);
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
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
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
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
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
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
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
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
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 *
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