The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/dpaa2/dpaa2_rc.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: e7f3f96d2f6d851daad1e57da8198b82


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.