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