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