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