From 0746e1fe33f129706efd64e8f3fcec4887079000 Mon Sep 17 00:00:00 2001 From: Dmitry Salychev Date: Wed, 15 Feb 2023 19:43:17 +0100 Subject: [PATCH] dpaa2: Avoid re-using dpaa2_cmd to eliminate race condition There is work-in-progress to handle errors during drivers attach routines properly as well, i.e. kernel still panics as a result of drivers detaching. --- sys/dev/dpaa2/dpaa2_bp.c | 91 ++- sys/dev/dpaa2/dpaa2_bp.h | 6 - sys/dev/dpaa2/dpaa2_con.c | 110 +-- sys/dev/dpaa2/dpaa2_con.h | 5 - sys/dev/dpaa2/dpaa2_io.c | 153 ++-- sys/dev/dpaa2/dpaa2_io.h | 5 - sys/dev/dpaa2/dpaa2_mac.c | 177 +++-- sys/dev/dpaa2/dpaa2_mac.h | 7 +- sys/dev/dpaa2/dpaa2_mcp.c | 87 +-- sys/dev/dpaa2/dpaa2_mcp.h | 32 +- sys/dev/dpaa2/dpaa2_ni.c | 1413 +++++++++++++++++++++++----------- sys/dev/dpaa2/dpaa2_ni.h | 12 +- sys/dev/dpaa2/dpaa2_rc.c | 186 ++--- sys/dev/dpaa2/dpaa2_swp.c | 87 ++- sys/dev/dpaa2/dpaa2_swp.h | 2 + sys/dev/dpaa2/dpaa2_swp_if.m | 18 +- 16 files changed, 1482 insertions(+), 909 deletions(-) diff --git a/sys/dev/dpaa2/dpaa2_bp.c b/sys/dev/dpaa2/dpaa2_bp.c index 78e1ca68cdb16b..0d6feb4c280703 100644 --- a/sys/dev/dpaa2/dpaa2_bp.c +++ b/sys/dev/dpaa2/dpaa2_bp.c @@ -90,21 +90,32 @@ dpaa2_bp_detach(device_t dev) device_t child = dev; struct dpaa2_bp_softc *sc = device_get_softc(dev); struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_cmd cmd; + uint16_t rc_token, bp_token; + int error; - if (sc->cmd != NULL) { - (void)DPAA2_CMD_BP_DISABLE(dev, child, sc->cmd); - (void)DPAA2_CMD_BP_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, - sc->bp_token)); - (void)DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, - sc->rc_token)); + DPAA2_CMD_INIT(&cmd); - dpaa2_mcp_free_command(sc->cmd); - sc->cmd = NULL; + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: error=%d\n", + __func__, error); + goto free_res; } - - dinfo->portal = NULL; + error = DPAA2_CMD_BP_OPEN(dev, child, &cmd, dinfo->id, &bp_token); + if (error) { + device_printf(dev, "%s: failed to open DPBP: id=%d, error=%d\n", + __func__, dinfo->id, error); + goto close_rc; + } + DPAA2_CMD_BP_DISABLE(dev, child, DPAA2_CMD_TK(&cmd, bp_token)); + DPAA2_CMD_BP_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, bp_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +free_res: bus_release_resources(sc->dev, dpaa2_bp_spec, sc->res); - + dinfo->portal = NULL; return (0); } @@ -118,73 +129,73 @@ dpaa2_bp_attach(device_t dev) struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); struct dpaa2_devinfo *dinfo = device_get_ivars(dev); struct dpaa2_devinfo *mcp_dinfo; + struct dpaa2_cmd cmd; + uint16_t rc_token, bp_token; int error; sc->dev = dev; - sc->cmd = NULL; error = bus_alloc_resources(sc->dev, dpaa2_bp_spec, sc->res); if (error) { device_printf(dev, "%s: failed to allocate resources: " "error=%d\n", __func__, error); - return (ENXIO); + goto err_exit; } - /* Send commands to MC via allocated portal. */ + /* Setup allocated MC portal */ mcp_dev = (device_t) rman_get_start(sc->res[MCP_RID(0)]); mcp_dinfo = device_get_ivars(mcp_dev); dinfo->portal = mcp_dinfo->portal; - /* Allocate a command to send to MC hardware. */ - error = dpaa2_mcp_init_command(&sc->cmd, DPAA2_CMD_DEF); - if (error) { - device_printf(dev, "%s: failed to allocate dpaa2_cmd: " - "error=%d\n", __func__, error); - dpaa2_bp_detach(dev); - return (ENXIO); - } + DPAA2_CMD_INIT(&cmd); - /* Open resource container and DPBP object. */ - error = DPAA2_CMD_RC_OPEN(dev, child, sc->cmd, rcinfo->id, - &sc->rc_token); + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); if (error) { device_printf(dev, "%s: failed to open DPRC: error=%d\n", __func__, error); - dpaa2_bp_detach(dev); - return (ENXIO); + goto free_res; } - error = DPAA2_CMD_BP_OPEN(dev, child, sc->cmd, dinfo->id, &sc->bp_token); + error = DPAA2_CMD_BP_OPEN(dev, child, &cmd, dinfo->id, &bp_token); if (error) { device_printf(dev, "%s: failed to open DPBP: id=%d, error=%d\n", __func__, dinfo->id, error); - dpaa2_bp_detach(dev); - return (ENXIO); + goto close_rc; } - /* Prepare DPBP object. */ - error = DPAA2_CMD_BP_RESET(dev, child, sc->cmd); + error = DPAA2_CMD_BP_RESET(dev, child, &cmd); if (error) { device_printf(dev, "%s: failed to reset DPBP: id=%d, error=%d\n", __func__, dinfo->id, error); - dpaa2_bp_detach(dev); - return (ENXIO); + goto close_bp; } - error = DPAA2_CMD_BP_ENABLE(dev, child, sc->cmd); + error = DPAA2_CMD_BP_ENABLE(dev, child, &cmd); if (error) { device_printf(dev, "%s: failed to enable DPBP: id=%d, " "error=%d\n", __func__, dinfo->id, error); - dpaa2_bp_detach(dev); - return (ENXIO); + goto close_bp; } - error = DPAA2_CMD_BP_GET_ATTRIBUTES(dev, child, sc->cmd, &sc->attr); + error = DPAA2_CMD_BP_GET_ATTRIBUTES(dev, child, &cmd, &sc->attr); if (error) { device_printf(dev, "%s: failed to get DPBP attributes: id=%d, " "error=%d\n", __func__, dinfo->id, error); - dpaa2_bp_detach(dev); - return (ENXIO); + goto disable_bp; } + DPAA2_CMD_BP_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, bp_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); return (0); + +disable_bp: + DPAA2_CMD_BP_DISABLE(dev, child, DPAA2_CMD_TK(&cmd, bp_token)); +close_bp: + DPAA2_CMD_BP_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, bp_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +free_res: + bus_release_resources(sc->dev, dpaa2_bp_spec, sc->res); +err_exit: + dinfo->portal = NULL; + return (ENXIO); } static device_method_t dpaa2_bp_methods[] = { diff --git a/sys/dev/dpaa2/dpaa2_bp.h b/sys/dev/dpaa2/dpaa2_bp.h index 3ba7196eb0306c..d05cb399cc1757 100644 --- a/sys/dev/dpaa2/dpaa2_bp.h +++ b/sys/dev/dpaa2/dpaa2_bp.h @@ -60,12 +60,6 @@ struct dpaa2_bp_conf { struct dpaa2_bp_softc { device_t dev; struct dpaa2_bp_attr attr; - - /* Help to send commands to MC. */ - struct dpaa2_cmd *cmd; - uint16_t rc_token; - uint16_t bp_token; - struct resource *res[DPAA2_BP_MAX_RESOURCES]; }; diff --git a/sys/dev/dpaa2/dpaa2_con.c b/sys/dev/dpaa2/dpaa2_con.c index 602497c2c8deb7..2f8dfc45bdbce0 100644 --- a/sys/dev/dpaa2/dpaa2_con.c +++ b/sys/dev/dpaa2/dpaa2_con.c @@ -93,7 +93,7 @@ static int dpaa2_con_detach(device_t dev); static int dpaa2_con_probe(device_t dev) { - /* DPCON device will be added by a parent resource container itself. */ + /* DPCON device will be added by the parent resource container itself. */ device_set_desc(dev, "DPAA2 Concentrator"); return (BUS_PROBE_DEFAULT); } @@ -101,17 +101,41 @@ dpaa2_con_probe(device_t dev) static int dpaa2_con_detach(device_t dev) { + device_t pdev = device_get_parent(dev); device_t child = dev; struct dpaa2_con_softc *sc = device_get_softc(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_cmd cmd; + uint16_t rc_token, con_token; + int error; - DPAA2_CMD_CON_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->con_token)); - DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->rc_token)); - dpaa2_mcp_free_command(sc->cmd); + DPAA2_CMD_INIT(&cmd); - sc->cmd = NULL; - sc->con_token = 0; - sc->rc_token = 0; + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: error=%d\n", + __func__, error); + goto free_res; + } + error = DPAA2_CMD_CON_OPEN(dev, child, &cmd, dinfo->id, &con_token); + if (error) { + device_printf(dev, "%s: failed to open DPCON: id=%d, error=%d\n", + __func__, dinfo->id, error); + goto close_rc; + } + error = DPAA2_CMD_CON_RESET(dev, child, &cmd); + if (error) { + device_printf(dev, "%s: failed to reset DPCON: id=%d, error=%d\n", + __func__, dinfo->id, error); + } + DPAA2_CMD_CON_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, con_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +free_res: + dinfo->portal = NULL; + bus_release_resources(sc->dev, dpaa2_con_spec, sc->res); return (0); } @@ -125,6 +149,8 @@ dpaa2_con_attach(device_t dev) struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); struct dpaa2_devinfo *dinfo = device_get_ivars(dev); struct dpaa2_devinfo *mcp_dinfo; + struct dpaa2_cmd cmd; + uint16_t rc_token, con_token; int error; sc->dev = dev; @@ -133,65 +159,59 @@ dpaa2_con_attach(device_t dev) if (error) { device_printf(dev, "%s: failed to allocate resources: " "error=%d\n", __func__, error); - return (ENXIO); + goto err_exit; } - /* Obtain MC portal. */ + /* Setup allocated MC portal */ mcp_dev = (device_t) rman_get_start(sc->res[MCP_RID(0)]); mcp_dinfo = device_get_ivars(mcp_dev); dinfo->portal = mcp_dinfo->portal; - /* Allocate a command to send to MC hardware. */ - error = dpaa2_mcp_init_command(&sc->cmd, DPAA2_CMD_DEF); - if (error) { - device_printf(dev, "Failed to allocate dpaa2_cmd: error=%d\n", - error); - goto err_exit; - } + DPAA2_CMD_INIT(&cmd); - /* Open resource container and DPCON object. */ - error = DPAA2_CMD_RC_OPEN(dev, child, sc->cmd, rcinfo->id, - &sc->rc_token); + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); if (error) { - device_printf(dev, "Failed to open DPRC: error=%d\n", error); - goto err_free_cmd; + device_printf(dev, "%s: failed to open DPRC: error=%d\n", + __func__, error); + goto free_res; } - error = DPAA2_CMD_CON_OPEN(dev, child, sc->cmd, dinfo->id, - &sc->con_token); + error = DPAA2_CMD_CON_OPEN(dev, child, &cmd, dinfo->id, &con_token); if (error) { - device_printf(dev, "Failed to open DPCON: id=%d, error=%d\n", - dinfo->id, error); - goto err_close_rc; + device_printf(dev, "%s: failed to open DPCON: id=%d, error=%d\n", + __func__, dinfo->id, error); + goto close_rc; } - - /* Prepare DPCON object. */ - error = DPAA2_CMD_CON_RESET(dev, child, sc->cmd); + error = DPAA2_CMD_CON_RESET(dev, child, &cmd); if (error) { - device_printf(dev, "Failed to reset DPCON: id=%d, error=%d\n", - dinfo->id, error); - goto err_close_con; + device_printf(dev, "%s: failed to reset DPCON: id=%d, error=%d\n", + __func__, dinfo->id, error); + goto close_con; } - error = DPAA2_CMD_CON_GET_ATTRIBUTES(dev, child, sc->cmd, &sc->attr); + error = DPAA2_CMD_CON_GET_ATTRIBUTES(dev, child, &cmd, &sc->attr); if (error) { - device_printf(dev, "Failed to get DPCON attributes: id=%d, " - "error=%d\n", dinfo->id, error); - goto err_close_con; + device_printf(dev, "%s: failed to get DPCON attributes: id=%d, " + "error=%d\n", __func__, dinfo->id, error); + goto close_con; } - /* TODO: Enable debug output via sysctl (to reduce output). */ - if (bootverbose) + if (bootverbose) { device_printf(dev, "chan_id=%d, priorities=%d\n", sc->attr.chan_id, sc->attr.prior_num); + } + + DPAA2_CMD_CON_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, con_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); return (0); - err_close_con: - DPAA2_CMD_CON_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->con_token)); - err_close_rc: - DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->rc_token)); - err_free_cmd: - dpaa2_mcp_free_command(sc->cmd); - err_exit: +close_con: + DPAA2_CMD_CON_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, con_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +free_res: + dinfo->portal = NULL; + bus_release_resources(sc->dev, dpaa2_con_spec, sc->res); +err_exit: return (ENXIO); } diff --git a/sys/dev/dpaa2/dpaa2_con.h b/sys/dev/dpaa2/dpaa2_con.h index 82fd50f4eaed80..85a492935d468b 100644 --- a/sys/dev/dpaa2/dpaa2_con.h +++ b/sys/dev/dpaa2/dpaa2_con.h @@ -58,11 +58,6 @@ struct dpaa2_con_softc { device_t dev; struct resource *res[DPAA2_CON_MAX_RESOURCES]; struct dpaa2_con_attr attr; - - /* Help to send commands to MC. */ - struct dpaa2_cmd *cmd; - uint16_t rc_token; - uint16_t con_token; }; extern struct resource_spec dpaa2_con_spec[]; diff --git a/sys/dev/dpaa2/dpaa2_io.c b/sys/dev/dpaa2/dpaa2_io.c index e2b7992bfdb6ba..c27cd8d0f221e2 100644 --- a/sys/dev/dpaa2/dpaa2_io.c +++ b/sys/dev/dpaa2/dpaa2_io.c @@ -119,7 +119,7 @@ static void dpaa2_io_intr(void *arg); static int dpaa2_io_probe(device_t dev) { - /* DPIO device will be added by a parent resource container itself. */ + /* DPIO device will be added by the parent resource container itself. */ device_set_desc(dev, "DPAA2 I/O"); return (BUS_PROBE_DEFAULT); } @@ -127,35 +127,44 @@ dpaa2_io_probe(device_t dev) static int dpaa2_io_detach(device_t dev) { + device_t pdev = device_get_parent(dev); device_t child = dev; struct dpaa2_io_softc *sc = device_get_softc(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_cmd cmd; + uint16_t rc_token; + uint16_t io_token __unused; int error; - /* Tear down interrupt handler and release IRQ resources. */ - dpaa2_io_release_irqs(dev); + DPAA2_CMD_INIT(&cmd); - /* Free software portal helper object. */ + dpaa2_io_release_irqs(dev); dpaa2_swp_free_portal(sc->swp); - /* Disable DPIO object. */ - error = DPAA2_CMD_IO_DISABLE(dev, child, dpaa2_mcp_tk(sc->cmd, - sc->io_token)); - if (error && bootverbose) + /* Disable DPIO object */ + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: error=%d\n", + __func__, error); + goto unmap_res; + } + error = DPAA2_CMD_IO_OPEN(dev, child, &cmd, dinfo->id, &io_token); + if (error) { + device_printf(dev, "%s: failed to open DPIO: id=%d, error=%d\n", + __func__, dinfo->id, error); + goto unmap_res; + } + error = DPAA2_CMD_IO_DISABLE(dev, child, &cmd); + if (error && bootverbose) { device_printf(dev, "%s: failed to disable DPIO: id=%d, " "error=%d\n", __func__, dinfo->id, error); + } + DPAA2_CMD_IO_CLOSE(dev, child, &cmd); + DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(&cmd, rc_token)); - /* Close control sessions with the DPAA2 objects. */ - DPAA2_CMD_IO_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->io_token)); - DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->rc_token)); - - /* Free pre-allocated MC command. */ - dpaa2_mcp_free_command(sc->cmd); - sc->cmd = NULL; - sc->io_token = 0; - sc->rc_token = 0; - - /* Unmap memory resources of the portal. */ +unmap_res: for (int i = 0; i < MEM_RES_NUM; i++) { if (sc->res[MEM_RID(i)] == NULL) continue; @@ -166,8 +175,6 @@ dpaa2_io_detach(device_t dev) "resource: rid=%d, error=%d\n", __func__, MEM_RID(i), error); } - - /* Release allocated resources. */ bus_release_resources(dev, dpaa2_io_spec, sc->res); return (0); @@ -183,41 +190,44 @@ dpaa2_io_attach(device_t dev) struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); struct dpaa2_devinfo *dinfo = device_get_ivars(dev); struct dpaa2_devinfo *mcp_dinfo; + struct dpaa2_cmd cmd; struct resource_map_request req; struct { vm_memattr_t memattr; char *label; + bool mapped; } map_args[MEM_RES_NUM] = { - { VM_MEMATTR_WRITE_BACK, "cache-enabled part" }, - { VM_MEMATTR_DEVICE, "cache-inhibited part" }, - { VM_MEMATTR_DEVICE, "control registers" } + { VM_MEMATTR_WRITE_BACK, "cache-enabled part", false }, + { VM_MEMATTR_DEVICE, "cache-inhibited part", false }, + { VM_MEMATTR_DEVICE, "control registers", false } }; + uint16_t rc_token, io_token; int error; + DPAA2_CMD_INIT(&cmd); + sc->dev = dev; sc->swp = NULL; - sc->cmd = NULL; sc->intr = NULL; sc->irq_resource = NULL; + for (int i = 0; i < MEM_RES_NUM; i++) + sc->res[MEM_RID(i)] = NULL; - /* Allocate resources. */ error = bus_alloc_resources(sc->dev, dpaa2_io_spec, sc->res); if (error) { device_printf(dev, "%s: failed to allocate resources: " "error=%d\n", __func__, error); - return (ENXIO); + goto err_exit; } - /* Set allocated MC portal up. */ + /* Setup allocated MC portal */ mcp_dev = (device_t) rman_get_start(sc->res[MCP_RID(0)]); mcp_dinfo = device_get_ivars(mcp_dev); dinfo->portal = mcp_dinfo->portal; - /* Map memory resources of the portal. */ for (int i = 0; i < MEM_RES_NUM; i++) { if (sc->res[MEM_RID(i)] == NULL) continue; - resource_init_map_request(&req); req.memattr = map_args[i].memattr; error = bus_map_resource(sc->dev, SYS_RES_MEMORY, @@ -225,49 +235,43 @@ dpaa2_io_attach(device_t dev) if (error) { device_printf(dev, "%s: failed to map %s: error=%d\n", __func__, map_args[i].label, error); - goto err_exit; + goto unmap_res; + } else { + map_args[i].mapped = true; } } - /* Allocate a command to send to the MC hardware. */ - error = dpaa2_mcp_init_command(&sc->cmd, DPAA2_CMD_DEF); - if (error) { - device_printf(dev, "%s: failed to allocate dpaa2_cmd: " - "error=%d\n", __func__, error); - goto err_exit; - } + /* Enable DPIO object */ - /* Prepare DPIO object. */ - error = DPAA2_CMD_RC_OPEN(dev, child, sc->cmd, rcinfo->id, - &sc->rc_token); + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); if (error) { device_printf(dev, "%s: failed to open DPRC: error=%d\n", __func__, error); - goto err_exit; + goto unmap_res; } - error = DPAA2_CMD_IO_OPEN(dev, child, sc->cmd, dinfo->id, &sc->io_token); + error = DPAA2_CMD_IO_OPEN(dev, child, &cmd, dinfo->id, &io_token); if (error) { device_printf(dev, "%s: failed to open DPIO: id=%d, error=%d\n", __func__, dinfo->id, error); - goto err_exit; + goto close_rc; } - error = DPAA2_CMD_IO_RESET(dev, child, sc->cmd); + error = DPAA2_CMD_IO_RESET(dev, child, &cmd); if (error) { device_printf(dev, "%s: failed to reset DPIO: id=%d, error=%d\n", __func__, dinfo->id, error); - goto err_exit; + goto close_io; } - error = DPAA2_CMD_IO_GET_ATTRIBUTES(dev, child, sc->cmd, &sc->attr); + error = DPAA2_CMD_IO_GET_ATTRIBUTES(dev, child, &cmd, &sc->attr); if (error) { device_printf(dev, "%s: failed to get DPIO attributes: id=%d, " "error=%d\n", __func__, dinfo->id, error); - goto err_exit; + goto close_io; } - error = DPAA2_CMD_IO_ENABLE(dev, child, sc->cmd); + error = DPAA2_CMD_IO_ENABLE(dev, child, &cmd); if (error) { device_printf(dev, "%s: failed to enable DPIO: id=%d, " "error=%d\n", __func__, dinfo->id, error); - goto err_exit; + goto close_io; } /* Prepare descriptor of the QBMan software portal. */ @@ -291,23 +295,23 @@ dpaa2_io_attach(device_t dev) sc->swp_desc.swp_cycles_ratio = 256000 / (sc->swp_desc.swp_clk / 1000000); - /* Initialize QBMan software portal. */ error = dpaa2_swp_init_portal(&sc->swp, &sc->swp_desc, DPAA2_SWP_DEF); if (error) { device_printf(dev, "%s: failed to initialize dpaa2_swp: " "error=%d\n", __func__, error); - goto err_exit; + goto disable_io; } error = dpaa2_io_setup_irqs(dev); if (error) { device_printf(dev, "%s: failed to setup IRQs: error=%d\n", __func__, error); - goto err_exit; + goto free_portal; } -#if 0 - /* TODO: Enable debug output via sysctl (to reduce output). */ + DPAA2_CMD_IO_CLOSE(dev, child, dpaa2_mcp_tk(&cmd, io_token)); + DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(&cmd, rc_token)); + if (bootverbose) device_printf(dev, "dpio_id=%d, swp_id=%d, chan_mode=%s, " "notif_priors=%d, swp_version=0x%x\n", @@ -315,11 +319,33 @@ dpaa2_io_attach(device_t dev) sc->attr.chan_mode == DPAA2_IO_LOCAL_CHANNEL ? "local_channel" : "no_channel", sc->attr.priors_num, sc->attr.swp_version); -#endif + return (0); +free_portal: + dpaa2_swp_free_portal(sc->swp); +disable_io: + DPAA2_CMD_IO_DISABLE(dev, child, DPAA2_CMD_TK(&cmd, io_token)); +close_io: + DPAA2_CMD_IO_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, io_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +unmap_res: + dinfo->portal = NULL; + for (int i = 0; i < MEM_RES_NUM; i++) { + if (sc->res[MEM_RID(i)] == NULL || !map_args[i].mapped) { + continue; + } + error = bus_unmap_resource(sc->dev, SYS_RES_MEMORY, + sc->res[MEM_RID(i)], &sc->map[MEM_RID(i)]); + if (error && bootverbose) { + device_printf(dev, "%s: failed to unmap memory " + "resource: rid=%d, error=%d\n", __func__, MEM_RID(i), + error); + } + } + bus_release_resources(dev, dpaa2_io_spec, sc->res); err_exit: - dpaa2_io_detach(dev); return (ENXIO); } @@ -385,6 +411,18 @@ dpaa2_io_release_bufs(device_t iodev, uint16_t bpid, bus_addr_t *buf, return (dpaa2_swp_release_bufs(sc->swp, bpid, buf, buf_num)); } +/** + * @brief Acquire one or more buffers from the QBMan buffer pool. + */ +static int +dpaa2_io_acquire_bufs(device_t iodev, uint16_t bpid, bus_addr_t *buf[], + uint32_t *buf_num) +{ + struct dpaa2_io_softc *sc = device_get_softc(iodev); + + return (dpaa2_swp_acquire_bufs(sc->swp, bpid, buf, buf_num)); +} + /** * @brief Configure DPNI object to generate interrupts. */ @@ -557,6 +595,7 @@ static device_method_t dpaa2_io_methods[] = { DEVMETHOD(dpaa2_swp_conf_wq_channel, dpaa2_io_conf_wq_channel), DEVMETHOD(dpaa2_swp_query_bp, dpaa2_io_query_bp), DEVMETHOD(dpaa2_swp_release_bufs, dpaa2_io_release_bufs), + DEVMETHOD(dpaa2_swp_acquire_bufs, dpaa2_io_acquire_bufs), DEVMETHOD_END }; diff --git a/sys/dev/dpaa2/dpaa2_io.h b/sys/dev/dpaa2/dpaa2_io.h index d02dab8144df86..13def050fffb7f 100644 --- a/sys/dev/dpaa2/dpaa2_io.h +++ b/sys/dev/dpaa2/dpaa2_io.h @@ -92,11 +92,6 @@ struct dpaa2_io_softc { struct dpaa2_swp *swp; struct dpaa2_io_attr attr; - /* Help to send commands to MC. */ - struct dpaa2_cmd *cmd; - uint16_t rc_token; - uint16_t io_token; - struct resource *res[DPAA2_IO_MAX_RESOURCES]; struct resource_map map[DPAA2_IO_MAX_RESOURCES]; diff --git a/sys/dev/dpaa2/dpaa2_mac.c b/sys/dev/dpaa2/dpaa2_mac.c index d6e381c0dd1530..797803a3c2f6d6 100644 --- a/sys/dev/dpaa2/dpaa2_mac.c +++ b/sys/dev/dpaa2/dpaa2_mac.c @@ -103,7 +103,7 @@ static void dpaa2_mac_intr(void *arg); static int dpaa2_mac_probe(device_t dev) { - /* DPIO device will be added by a parent resource container itself. */ + /* DPIO device will be added by the parent resource container itself. */ device_set_desc(dev, "DPAA2 MAC"); return (BUS_PROBE_DEFAULT); } @@ -118,60 +118,51 @@ dpaa2_mac_attach(device_t dev) struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); struct dpaa2_devinfo *dinfo = device_get_ivars(dev); struct dpaa2_devinfo *mcp_dinfo; + struct dpaa2_cmd cmd; + uint16_t rc_token, mac_token; int error; sc->dev = dev; - memset(sc->addr, 0, ETHER_ADDR_LEN); error = bus_alloc_resources(sc->dev, dpaa2_mac_spec, sc->res); if (error) { device_printf(dev, "%s: failed to allocate resources: " "error=%d\n", __func__, error); - return (ENXIO); + goto err_exit; } - /* Obtain MC portal. */ + /* Setup allocated MC portal */ mcp_dev = (device_t) rman_get_start(sc->res[MCP_RID(0)]); mcp_dinfo = device_get_ivars(mcp_dev); dinfo->portal = mcp_dinfo->portal; - /* Allocate a command to send to MC hardware. */ - error = dpaa2_mcp_init_command(&sc->cmd, DPAA2_CMD_DEF); - if (error) { - device_printf(dev, "Failed to allocate dpaa2_cmd: error=%d\n", - error); - goto err_exit; - } + DPAA2_CMD_INIT(&cmd); - /* Open resource container and DPMAC object. */ - error = DPAA2_CMD_RC_OPEN(dev, child, sc->cmd, rcinfo->id, - &sc->rc_token); + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); if (error) { - device_printf(dev, "Failed to open DPRC: error=%d\n", error); - goto err_free_cmd; + device_printf(dev, "%s: failed to open DPRC: error=%d\n", + __func__, error); + goto free_res; } - error = DPAA2_CMD_MAC_OPEN(dev, child, sc->cmd, dinfo->id, - &sc->mac_token); + error = DPAA2_CMD_MAC_OPEN(dev, child, &cmd, dinfo->id, &mac_token); if (error) { - device_printf(dev, "Failed to open DPMAC: id=%d, error=%d\n", - dinfo->id, error); - goto err_close_rc; + device_printf(dev, "%s: failed to open DPMAC: id=%d, error=%d\n", + __func__, dinfo->id, error); + goto close_rc; } - error = DPAA2_CMD_MAC_GET_ATTRIBUTES(dev, child, sc->cmd, &sc->attr); + error = DPAA2_CMD_MAC_GET_ATTRIBUTES(dev, child, &cmd, &sc->attr); if (error) { - device_printf(dev, "Failed to get DPMAC attributes: id=%d, " - "error=%d\n", dinfo->id, error); - goto err_close_mac; + device_printf(dev, "%s: failed to get DPMAC attributes: id=%d, " + "error=%d\n", __func__, dinfo->id, error); + goto close_mac; + } + error = DPAA2_CMD_MAC_GET_ADDR(dev, child, &cmd, sc->addr); + if (error) { + device_printf(dev, "%s: failed to get physical address: " + "error=%d\n", __func__, error); } - error = DPAA2_CMD_MAC_GET_ADDR(dev, child, sc->cmd, sc->addr); - if (error) - device_printf(dev, "Failed to get physical address: error=%d\n", - error); - /* - * TODO: Enable debug output via sysctl. - */ if (bootverbose) { device_printf(dev, "ether %6D\n", sc->addr, ":"); device_printf(dev, "max_rate=%d, eth_if=%s, link_type=%s\n", @@ -182,18 +173,19 @@ dpaa2_mac_attach(device_t dev) error = dpaa2_mac_setup_irq(dev); if (error) { - device_printf(dev, "Failed to setup IRQs: error=%d\n", error); - goto err_close_mac; + device_printf(dev, "%s: failed to setup IRQs: error=%d\n", + __func__, error); + goto close_mac; } return (0); -err_close_mac: - DPAA2_CMD_MAC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->mac_token)); -err_close_rc: - DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->rc_token)); -err_free_cmd: - dpaa2_mcp_free_command(sc->cmd); +close_mac: + DPAA2_CMD_MAC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, mac_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +free_res: + bus_release_resources(sc->dev, dpaa2_mac_spec, sc->res); err_exit: return (ENXIO); } @@ -201,17 +193,6 @@ dpaa2_mac_attach(device_t dev) static int dpaa2_mac_detach(device_t dev) { - device_t child = dev; - struct dpaa2_mac_softc *sc = device_get_softc(dev); - - DPAA2_CMD_MAC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->mac_token)); - DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->rc_token)); - dpaa2_mcp_free_command(sc->cmd); - - sc->cmd = NULL; - sc->rc_token = 0; - sc->mac_token = 0; - return (0); } @@ -223,51 +204,68 @@ dpaa2_mac_setup_irq(device_t dev) { device_t child = dev; struct dpaa2_mac_softc *sc = device_get_softc(dev); - struct dpaa2_cmd *cmd = sc->cmd; - uint16_t mac_token = sc->mac_token; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_cmd cmd; + uint16_t rc_token, mac_token; uint32_t irq_mask; int error; - /* Configure IRQs. */ error = dpaa2_mac_setup_msi(sc); if (error) { - device_printf(dev, "Failed to allocate MSI\n"); - return (error); + device_printf(dev, "%s: failed to allocate MSI\n", __func__); + goto err_exit; } + error = ENXIO; if ((sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid[0], RF_ACTIVE | RF_SHAREABLE)) == NULL) { - device_printf(dev, "Failed to allocate IRQ resource\n"); - return (ENXIO); + device_printf(dev, "%s: failed to allocate IRQ resource\n", + __func__); + goto err_exit; } if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE, NULL, dpaa2_mac_intr, sc, &sc->intr)) { - device_printf(dev, "Failed to setup IRQ resource\n"); - return (ENXIO); + device_printf(dev, "%s: failed to setup IRQ resource\n", + __func__); + goto err_exit; } - /* Configure DPNI to generate interrupts. */ - irq_mask = - DPMAC_IRQ_LINK_CFG_REQ | - DPMAC_IRQ_LINK_CHANGED | - DPMAC_IRQ_LINK_UP_REQ | - DPMAC_IRQ_LINK_DOWN_REQ | + /* Configure DPNI to generate interrupts */ + + DPAA2_CMD_INIT(&cmd); + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + goto err_exit; + } + error = DPAA2_CMD_MAC_OPEN(dev, child, &cmd, dinfo->id, &mac_token); + if (error) { + goto close_rc; + } + irq_mask = DPMAC_IRQ_LINK_CFG_REQ | DPMAC_IRQ_LINK_CHANGED | + DPMAC_IRQ_LINK_UP_REQ | DPMAC_IRQ_LINK_DOWN_REQ | DPMAC_IRQ_EP_CHANGED; - error = DPAA2_CMD_MAC_SET_IRQ_MASK(dev, child, dpaa2_mcp_tk(cmd, - mac_token), DPMAC_IRQ_INDEX, irq_mask); + error = DPAA2_CMD_MAC_SET_IRQ_MASK(dev, child, &cmd, DPMAC_IRQ_INDEX, + irq_mask); if (error) { - device_printf(dev, "Failed to set IRQ mask\n"); - return (error); + device_printf(dev, "%s: failed to set IRQ mask\n", __func__); + goto close_mac; } - - /* Enable IRQ. */ - error = DPAA2_CMD_MAC_SET_IRQ_ENABLE(dev, child, cmd, DPMAC_IRQ_INDEX, + error = DPAA2_CMD_MAC_SET_IRQ_ENABLE(dev, child, &cmd, DPMAC_IRQ_INDEX, true); if (error) { - device_printf(dev, "Failed to enable IRQ\n"); - return (error); + device_printf(dev, "%s: failed to enable IRQ\n", __func__); + goto close_mac; } return (0); + +close_mac: + DPAA2_CMD_MAC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, mac_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +err_exit: + return (error); } /** @@ -296,16 +294,31 @@ dpaa2_mac_setup_msi(struct dpaa2_mac_softc *sc) static void dpaa2_mac_intr(void *arg) { - struct dpaa2_mac_softc *sc = (struct dpaa2_mac_softc *) arg; - device_t child = sc->dev; + device_t dev = ((struct dpaa2_mac_softc *) arg)->dev; + device_t child = dev; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_cmd cmd; uint32_t status = ~0u; /* clear all IRQ status bits */ + uint16_t rc_token, mac_token; int error; - error = DPAA2_CMD_MAC_GET_IRQ_STATUS(sc->dev, child, - dpaa2_mcp_tk(sc->cmd, sc->mac_token), DPMAC_IRQ_INDEX, &status); - if (error) - device_printf(sc->dev, "%s: failed to obtain IRQ status: " - "error=%d\n", __func__, error); + DPAA2_CMD_INIT(&cmd); + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + goto exit; + } + error = DPAA2_CMD_MAC_OPEN(dev, child, &cmd, dinfo->id, &mac_token); + if (error) { + goto close_rc; + } + DPAA2_CMD_MAC_GET_IRQ_STATUS(dev, child, &cmd, DPMAC_IRQ_INDEX, &status); + DPAA2_CMD_MAC_CLOSE(dev, child, &cmd); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +exit: + return; } static const char * diff --git a/sys/dev/dpaa2/dpaa2_mac.h b/sys/dev/dpaa2/dpaa2_mac.h index cbdf2d824045a2..d65095fedb58b7 100644 --- a/sys/dev/dpaa2/dpaa2_mac.h +++ b/sys/dev/dpaa2/dpaa2_mac.h @@ -108,12 +108,7 @@ struct dpaa2_mac_softc { struct resource *res[DPAA2_MAC_MAX_RESOURCES]; struct dpaa2_mac_attr attr; - /* Help to send commands to MC. */ - struct dpaa2_cmd *cmd; - uint16_t rc_token; - uint16_t mac_token; - - /* Interrupts. */ + /* Interrupts */ int irq_rid[DPAA2_MAC_MSI_COUNT]; struct resource *irq_res; void *intr; /* interrupt handle */ diff --git a/sys/dev/dpaa2/dpaa2_mcp.c b/sys/dev/dpaa2/dpaa2_mcp.c index f41d9a7d21b026..5e020ed9136736 100644 --- a/sys/dev/dpaa2/dpaa2_mcp.c +++ b/sys/dev/dpaa2/dpaa2_mcp.c @@ -108,46 +108,6 @@ dpaa2_mcp_free_portal(struct dpaa2_mcp *mcp) free(mcp, M_DPAA2_MCP); } -int -dpaa2_mcp_init_command(struct dpaa2_cmd **cmd, uint16_t flags) -{ - const int mflags = flags & DPAA2_CMD_NOWAIT_ALLOC - ? (M_NOWAIT | M_ZERO) : (M_WAITOK | M_ZERO); - struct dpaa2_cmd *c; - struct dpaa2_cmd_header *hdr; - - if (!cmd) - return (DPAA2_CMD_STAT_EINVAL); - - c = malloc(sizeof(struct dpaa2_cmd), M_DPAA2_MCP, mflags); - if (!c) - return (DPAA2_CMD_STAT_NO_MEMORY); - - hdr = (struct dpaa2_cmd_header *) &c->header; - hdr->srcid = 0; - hdr->status = DPAA2_CMD_STAT_OK; - hdr->token = 0; - hdr->cmdid = 0; - hdr->flags_hw = DPAA2_CMD_DEF; - hdr->flags_sw = DPAA2_CMD_DEF; - if (flags & DPAA2_CMD_HIGH_PRIO) - hdr->flags_hw |= DPAA2_HW_FLAG_HIGH_PRIO; - if (flags & DPAA2_CMD_INTR_DIS) - hdr->flags_sw |= DPAA2_SW_FLAG_INTR_DIS; - for (uint32_t i = 0; i < DPAA2_CMD_PARAMS_N; i++) - c->params[i] = 0; - *cmd = c; - - return (0); -} - -void -dpaa2_mcp_free_command(struct dpaa2_cmd *cmd) -{ - if (cmd != NULL) - free(cmd, M_DPAA2_MCP); -} - struct dpaa2_cmd * dpaa2_mcp_tk(struct dpaa2_cmd *cmd, uint16_t token) { @@ -198,7 +158,7 @@ dpaa2_mcp_attach(device_t dev) struct dpaa2_mcp_softc *sc = device_get_softc(dev); struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); struct dpaa2_devinfo *dinfo = device_get_ivars(dev); - struct dpaa2_cmd *cmd; + struct dpaa2_cmd cmd; struct dpaa2_mcp *portal; struct resource_map_request req; uint16_t rc_token, mcp_token; @@ -240,61 +200,34 @@ dpaa2_mcp_attach(device_t dev) goto err_exit; } - /* Allocate a command to send to MC hardware. */ - error = dpaa2_mcp_init_command(&cmd, DPAA2_CMD_DEF); - if (error) { - device_printf(dev, "%s: failed to allocate dpaa2_cmd: " - "error=%d\n", __func__, error); - goto err_exit; - } + DPAA2_CMD_INIT(&cmd); - /* Open resource container and DPMCP object. */ - error = DPAA2_CMD_RC_OPEN(dev, child, cmd, rcinfo->id, &rc_token); + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); if (error) { device_printf(dev, "%s: failed to open DPRC: error=%d\n", __func__, error); - goto err_free_cmd; + goto err_exit; } - error = DPAA2_CMD_MCP_OPEN(dev, child, cmd, dinfo->id, &mcp_token); + error = DPAA2_CMD_MCP_OPEN(dev, child, &cmd, dinfo->id, &mcp_token); if (error) { device_printf(dev, "%s: failed to open DPMCP: id=%d, error=%d\n", __func__, dinfo->id, error); goto err_close_rc; } - /* Prepare DPMCP object. */ - error = DPAA2_CMD_MCP_RESET(dev, child, cmd); - if (error) { + error = DPAA2_CMD_MCP_RESET(dev, child, &cmd); + if (error && bootverbose) { device_printf(dev, "%s: failed to reset DPMCP: id=%d, " "error=%d\n", __func__, dinfo->id, error); - goto err_close_mcp; - } - - /* Close the DPMCP object and the resource container. */ - error = DPAA2_CMD_MCP_CLOSE(dev, child, cmd); - if (error) { - device_printf(dev, "%s: failed to close DPMCP: id=%d, " - "error=%d\n", __func__, dinfo->id, error); - goto err_close_rc; } - error = DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(cmd, rc_token)); - if (error) { - device_printf(dev, "%s: failed to close DPRC: error=%d\n", - __func__, error); - goto err_free_cmd; - } - - dpaa2_mcp_free_command(cmd); + (void)DPAA2_CMD_MCP_CLOSE(dev, child, &cmd); + (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); dinfo->portal = portal; return (0); -err_close_mcp: - DPAA2_CMD_MCP_CLOSE(dev, child, dpaa2_mcp_tk(cmd, mcp_token)); err_close_rc: - DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(cmd, rc_token)); -err_free_cmd: - dpaa2_mcp_free_command(cmd); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); err_exit: dpaa2_mcp_detach(dev); return (ENXIO); diff --git a/sys/dev/dpaa2/dpaa2_mcp.h b/sys/dev/dpaa2/dpaa2_mcp.h index 55052ca7afb21e..f0770d847055ae 100644 --- a/sys/dev/dpaa2/dpaa2_mcp.h +++ b/sys/dev/dpaa2/dpaa2_mcp.h @@ -437,13 +437,37 @@ struct dpaa2_mcp_softc { int dpaa2_mcp_init_portal(struct dpaa2_mcp **mcp, struct resource *res, struct resource_map *map, uint16_t flags); -int dpaa2_mcp_init_command(struct dpaa2_cmd **cmd, uint16_t flags); void dpaa2_mcp_free_portal(struct dpaa2_mcp *mcp); -void dpaa2_mcp_free_command(struct dpaa2_cmd *cmd); /* to quickly update command token */ -struct dpaa2_cmd *dpaa2_mcp_tk(struct dpaa2_cmd *cmd, uint16_t token); +struct dpaa2_cmd *dpaa2_mcp_tk(struct dpaa2_cmd *cmd, const uint16_t token); /* to quickly update command flags */ -struct dpaa2_cmd *dpaa2_mcp_f(struct dpaa2_cmd *cmd, uint16_t flags); +struct dpaa2_cmd *dpaa2_mcp_f(struct dpaa2_cmd *cmd, const uint16_t flags); + +#define DPAA2_CMD_INIT_FLAGS(cmd, flags) do { \ + struct dpaa2_cmd_header *__hdr; \ + KASSERT((cmd) != NULL, ("%s:%d: failed", __func__, __LINE__)); \ + \ + __hdr = (struct dpaa2_cmd_header *) &((cmd)->header); \ + __hdr->srcid = 0; \ + __hdr->status = DPAA2_CMD_STAT_OK; \ + __hdr->token = 0; \ + __hdr->cmdid = 0; \ + __hdr->flags_hw = DPAA2_CMD_DEF; \ + __hdr->flags_sw = DPAA2_CMD_DEF; \ + if ((flags) & DPAA2_CMD_HIGH_PRIO) { \ + __hdr->flags_hw |= DPAA2_HW_FLAG_HIGH_PRIO; \ + } \ + if ((flags) & DPAA2_CMD_INTR_DIS) { \ + __hdr->flags_sw |= DPAA2_SW_FLAG_INTR_DIS; \ + } \ + \ + for (uint32_t __dcpi = 0; __dcpi < DPAA2_CMD_PARAMS_N; __dcpi++) { \ + (cmd)->params[__dcpi] = 0; \ + } \ +} while (0) +#define DPAA2_CMD_INIT(cmd) DPAA2_CMD_INIT_FLAGS((cmd), DPAA2_CMD_DEF) +#define DPAA2_CMD_TK(cmd, token) dpaa2_mcp_tk((cmd), (token)) +#define DPAA2_CMD_F(cmd, flags) dpaa2_mcp_f((cmd), (flags)) #endif /* _DPAA2_MCP_H */ diff --git a/sys/dev/dpaa2/dpaa2_ni.c b/sys/dev/dpaa2/dpaa2_ni.c index f62d6c1b6f29bc..3b7935ea76dbef 100644 --- a/sys/dev/dpaa2/dpaa2_ni.c +++ b/sys/dev/dpaa2/dpaa2_ni.c @@ -402,6 +402,7 @@ static int dpaa2_ni_detach(device_t); /* DPAA2 network interface setup and configuration */ static int dpaa2_ni_setup(device_t); static int dpaa2_ni_setup_channels(device_t); +static int dpaa2_ni_setup_channel(device_t, const uint32_t); static int dpaa2_ni_setup_fq(device_t, struct dpaa2_ni_channel *, enum dpaa2_ni_queue_type); static int dpaa2_ni_bind(device_t); @@ -431,7 +432,7 @@ static int dpaa2_ni_set_hash(device_t, uint64_t); static int dpaa2_ni_set_dist_key(device_t, enum dpaa2_ni_dist_mode, uint64_t); /* Buffers and buffer pools */ -static int dpaa2_ni_seed_buf_pool(struct dpaa2_ni_softc *, uint32_t); +static int dpaa2_ni_seed_buf_pool(struct dpaa2_ni_softc *, uint32_t, device_t); static int dpaa2_ni_seed_rxbuf(struct dpaa2_ni_softc *, struct dpaa2_buf *, int); static int dpaa2_ni_seed_txbuf(struct dpaa2_ni_softc *, struct dpaa2_buf *, int); static int dpaa2_ni_seed_chan_storage(struct dpaa2_ni_softc *, @@ -440,15 +441,17 @@ static int dpaa2_ni_seed_chan_storage(struct dpaa2_ni_softc *, /* Frame descriptor routines */ static int dpaa2_ni_build_fd(struct dpaa2_ni_softc *, struct dpaa2_ni_tx_ring *, struct dpaa2_buf *, bus_dma_segment_t *, int, struct dpaa2_fd *); -static int dpaa2_ni_fd_err(struct dpaa2_fd *); static uint32_t dpaa2_ni_fd_data_len(struct dpaa2_fd *); static int dpaa2_ni_fd_chan_idx(struct dpaa2_fd *); static int dpaa2_ni_fd_buf_idx(struct dpaa2_fd *); static int dpaa2_ni_fd_tx_idx(struct dpaa2_fd *); static int dpaa2_ni_fd_txbuf_idx(struct dpaa2_fd *); -static int dpaa2_ni_fd_format(struct dpaa2_fd *); static bool dpaa2_ni_fd_short_len(struct dpaa2_fd *); static int dpaa2_ni_fd_offset(struct dpaa2_fd *); +#ifdef DPAA2_DEBUG +static int dpaa2_ni_fd_err(struct dpaa2_fd *); +static int dpaa2_ni_fd_format(struct dpaa2_fd *); +#endif /* Various subroutines */ static int dpaa2_ni_cmp_api_version(struct dpaa2_ni_softc *, uint16_t, uint16_t); @@ -500,7 +503,7 @@ static int dpaa2_ni_collect_buf_free(SYSCTL_HANDLER_ARGS); static int dpaa2_ni_probe(device_t dev) { - /* DPNI device will be added by a parent resource container itself. */ + /* DPNI device will be added by the parent container itself */ device_set_desc(dev, "DPAA2 Network Interface"); return (BUS_PROBE_DEFAULT); } @@ -515,7 +518,10 @@ dpaa2_ni_attach(device_t dev) struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); struct dpaa2_devinfo *dinfo = device_get_ivars(dev); struct dpaa2_devinfo *mcp_dinfo; + struct dpaa2_cmd cmd; + struct dpaa2_buf *buf; struct ifnet *ifp; + uint16_t rc_token, ni_token; char tq_name[32]; int error; @@ -526,9 +532,10 @@ dpaa2_ni_attach(device_t dev) sc->media_status = 0; sc->if_flags = 0; sc->link_state = LINK_STATE_UNKNOWN; + sc->link_options = 0; sc->buf_align = 0; - /* For debug purposes only! */ +#ifdef DPAA2_DEBUG sc->rx_anomaly_frames = 0; sc->rx_single_buf_frames = 0; sc->rx_sg_buf_frames = 0; @@ -536,14 +543,17 @@ dpaa2_ni_attach(device_t dev) sc->rx_ieoi_err_frames = 0; sc->tx_single_buf_frames = 0; sc->tx_sg_frames = 0; +#endif DPAA2_ATOMIC_XCHG(&sc->buf_num, 0); DPAA2_ATOMIC_XCHG(&sc->buf_free, 0); sc->bp_dmat = NULL; + sc->tx_dmat = NULL; sc->st_dmat = NULL; sc->rxd_dmat = NULL; sc->qos_dmat = NULL; + sc->sgt_dmat = NULL; sc->qos_kcfg.type = DPAA2_BUF_STORE; sc->qos_kcfg.store.dmap = NULL; @@ -563,22 +573,21 @@ dpaa2_ni_attach(device_t dev) if (error) { device_printf(dev, "%s: failed to allocate resources: " "error=%d\n", __func__, error); - return (ENXIO); + goto err_exit; } - /* Obtain MC portal. */ + /* Setup allocated MC portal */ mcp_dev = (device_t) rman_get_start(sc->res[MCP_RID(0)]); mcp_dinfo = device_get_ivars(mcp_dev); dinfo->portal = mcp_dinfo->portal; mtx_init(&sc->lock, device_get_nameunit(dev), "dpaa2_ni", MTX_DEF); - /* Allocate network interface */ ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(dev, "%s: failed to allocate network interface\n", __func__); - return (ENXIO); + goto free_res; } sc->ifp = ifp; if_initname(ifp, DPAA2_NI_IFNAME, device_get_unit(sc->dev)); @@ -589,45 +598,36 @@ dpaa2_ni_attach(device_t dev) ifp->if_ioctl = dpaa2_ni_ioctl; ifp->if_transmit = dpaa2_ni_transmit; ifp->if_qflush = dpaa2_ni_qflush; - ifp->if_capabilities = IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_JUMBO_MTU; ifp->if_capenable = ifp->if_capabilities; - /* Allocate a command to send to MC hardware. */ - error = dpaa2_mcp_init_command(&sc->cmd, DPAA2_CMD_DEF); - if (error) { - device_printf(dev, "%s: failed to allocate dpaa2_cmd: " - "error=%d\n", __func__, error); - goto err_exit; - } + DPAA2_CMD_INIT(&cmd); - /* Open resource container and network interface object. */ - error = DPAA2_CMD_RC_OPEN(dev, child, sc->cmd, rcinfo->id, - &sc->rc_token); + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); if (error) { device_printf(dev, "%s: failed to open resource container: " "id=%d, error=%d\n", __func__, rcinfo->id, error); - goto err_free_cmd; + goto free_if; } - error = DPAA2_CMD_NI_OPEN(dev, child, dpaa2_mcp_tk(sc->cmd, - sc->rc_token), dinfo->id, &sc->ni_token); + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); if (error) { device_printf(dev, "%s: failed to open network interface: " "id=%d, error=%d\n", __func__, dinfo->id, error); - goto err_close_rc; + goto close_rc; } - /* Create a taskqueue thread to release new buffers to the pool. */ TASK_INIT(&sc->bp_task, 0, dpaa2_ni_bp_task, sc); bzero(tq_name, sizeof (tq_name)); snprintf(tq_name, sizeof (tq_name), "%s_tqbp", device_get_nameunit(dev)); + + /* Create a taskqueue thread to release new buffers to the pool. */ sc->bp_taskq = taskqueue_create(tq_name, M_WAITOK, taskqueue_thread_enqueue, &sc->bp_taskq); if (sc->bp_taskq == NULL) { - device_printf(dev, "%s: failed to allocate task queue: %s\n", + device_printf(dev, "%s: failed to allocate taskqueue: %s\n", __func__, tq_name); - goto err_close_ni; + goto close_ni; } taskqueue_start_threads(&sc->bp_taskq, 1, PI_NET, "%s", tq_name); @@ -635,45 +635,87 @@ dpaa2_ni_attach(device_t dev) if (error) { device_printf(dev, "%s: failed to setup DPNI: error=%d\n", __func__, error); - goto err_close_ni; + goto free_bp_taskq; } error = dpaa2_ni_setup_channels(dev); if (error) { device_printf(dev, "%s: failed to setup QBMan channels: " "error=%d\n", __func__, error); - goto err_close_ni; + goto teardown_ni; } error = dpaa2_ni_bind(dev); if (error) { device_printf(dev, "%s: failed to bind DPNI: error=%d\n", __func__, error); - goto err_close_ni; + goto free_channels; } error = dpaa2_ni_setup_irqs(dev); if (error) { device_printf(dev, "%s: failed to setup IRQs: error=%d\n", __func__, error); - goto err_close_ni; + goto unbind_ni; } error = dpaa2_ni_setup_sysctls(sc); if (error) { device_printf(dev, "%s: failed to setup sysctls: error=%d\n", __func__, error); - goto err_close_ni; + goto teardown_irqs; } ether_ifattach(sc->ifp, sc->mac.addr); callout_init(&sc->mii_callout, 0); + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); return (0); -err_close_ni: - DPAA2_CMD_NI_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->ni_token)); -err_close_rc: - DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->rc_token)); -err_free_cmd: - dpaa2_mcp_free_command(sc->cmd); +teardown_irqs: + /* XXX-DSL: Tear IRQs down after dpaa2_ni_setup_irqs(). */ +unbind_ni: + /* XXX-DSL: Free resources after dpaa2_ni_bind(). */ +free_channels: + for (uint32_t i = 0; i < sc->chan_n; i++) { + if (!sc->channels[i]->ready) { + continue; + } + buf = &sc->channels[i]->store; + KASSERT(buf->type == DPAA2_BUF_STORE, ("%s:%d: failed", __func__, + __LINE__)); + bus_dmamap_unload(buf->store.dmat, buf->store.dmap); + bus_dmamem_free(buf->store.dmat, buf->store.vaddr, + buf->store.dmap); + buf->store.vaddr = NULL; + free(sc->channels[i], M_DPAA2_NI); + sc->channels[i] = NULL; + } +teardown_ni: + buf = &sc->qos_kcfg; + bus_dmamap_unload(buf->store.dmat, buf->store.dmap); + bus_dmamem_free(buf->store.dmat, buf->store.vaddr, buf->store.dmap); + buf->store.vaddr = NULL; + bus_dma_tag_destroy(sc->sgt_dmat); + bus_dma_tag_destroy(sc->qos_dmat); + bus_dma_tag_destroy(sc->rxd_dmat); + bus_dma_tag_destroy(sc->st_dmat); + bus_dma_tag_destroy(sc->tx_dmat); + bus_dma_tag_destroy(sc->bp_dmat); +free_bp_taskq: + taskqueue_drain(sc->bp_taskq, &sc->bp_task); + taskqueue_free(sc->bp_taskq); + sc->bp_taskq = NULL; +close_ni: + DPAA2_CMD_NI_RESET(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +free_if: + sc->ifp = NULL; + if_free(ifp); +free_res: + mtx_destroy(&sc->lock); + dinfo->portal = NULL; + bus_release_resources(sc->dev, dpaa2_ni_spec, sc->res); err_exit: return (ENXIO); } @@ -728,17 +770,6 @@ dpaa2_ni_setup_fixed_link(struct dpaa2_ni_softc *sc) static int dpaa2_ni_detach(device_t dev) { - device_t child = dev; - struct dpaa2_ni_softc *sc = device_get_softc(dev); - - DPAA2_CMD_NI_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->ni_token)); - DPAA2_CMD_RC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, sc->rc_token)); - dpaa2_mcp_free_command(sc->cmd); - - sc->cmd = NULL; - sc->ni_token = 0; - sc->rc_token = 0; - return (0); } @@ -750,48 +781,60 @@ dpaa2_ni_setup(device_t dev) { device_t child = dev; struct dpaa2_ni_softc *sc = device_get_softc(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(device_get_parent(dev)); struct dpaa2_devinfo *dinfo = device_get_ivars(dev); struct dpaa2_ep_desc ep1_desc, ep2_desc; /* endpoint descriptors */ - struct dpaa2_cmd *cmd = sc->cmd; - uint8_t eth_bca[ETHER_ADDR_LEN]; /* broadcast physical address */ - uint16_t rc_token = sc->rc_token; - uint16_t ni_token = sc->ni_token; - uint16_t mac_token; + struct dpaa2_cmd cmd; + struct dpaa2_buf *buf; struct dpaa2_mac_attr attr; enum dpaa2_mac_link_type link_type; + uint8_t eth_bca[ETHER_ADDR_LEN]; /* broadcast physical address */ + uint16_t rc_token, ni_token, mac_token; uint32_t link; int error; - /* Check if we can work with this DPNI object. */ - error = DPAA2_CMD_NI_GET_API_VERSION(dev, child, dpaa2_mcp_tk(cmd, - ni_token), &sc->api_major, &sc->api_minor); + DPAA2_CMD_INIT(&cmd); + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open resource container: " + "id=%d\n", __func__, rcinfo->id); + goto err_exit; + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); + if (error) { + device_printf(dev, "%s: failed to open network interface: " + "id=%d\n", __func__, dinfo->id); + goto close_rc; + } + + error = DPAA2_CMD_NI_GET_API_VERSION(dev, child, &cmd, &sc->api_major, + &sc->api_minor); if (error) { device_printf(dev, "%s: failed to get DPNI API version\n", __func__); - return (error); + goto close_ni; } if (dpaa2_ni_cmp_api_version(sc, DPNI_VER_MAJOR, DPNI_VER_MINOR) < 0) { device_printf(dev, "%s: DPNI API version %u.%u not supported, " "need >= %u.%u\n", __func__, sc->api_major, sc->api_minor, DPNI_VER_MAJOR, DPNI_VER_MINOR); error = ENODEV; - return (error); + goto close_ni; } - /* Reset the DPNI object. */ - error = DPAA2_CMD_NI_RESET(dev, child, cmd); + error = DPAA2_CMD_NI_RESET(dev, child, &cmd); if (error) { device_printf(dev, "%s: failed to reset DPNI: id=%d\n", __func__, dinfo->id); - return (error); + goto close_ni; } - /* Obtain attributes of the DPNI object. */ - error = DPAA2_CMD_NI_GET_ATTRIBUTES(dev, child, cmd, &sc->attr); + error = DPAA2_CMD_NI_GET_ATTRIBUTES(dev, child, &cmd, &sc->attr); if (error) { device_printf(dev, "%s: failed to obtain DPNI attributes: " "id=%d\n", __func__, dinfo->id); - return (error); + goto close_ni; } if (bootverbose) { device_printf(dev, "options=0x%#x queues=%d tx_channels=%d " @@ -808,18 +851,17 @@ dpaa2_ni_setup(device_t dev) } /* Configure buffer layouts of the DPNI queues. */ - error = dpaa2_ni_set_buf_layout(dev, cmd); + error = dpaa2_ni_set_buf_layout(dev, &cmd); if (error) { device_printf(dev, "%s: failed to configure buffer layout\n", __func__); - return (error); + goto close_ni; } - /* Configure DMA resources. */ error = dpaa2_ni_setup_dma(sc); if (error) { device_printf(dev, "%s: failed to setup DMA\n", __func__); - return (error); + goto close_ni; } /* Setup link between DPNI and an object it's connected to. */ @@ -827,19 +869,22 @@ dpaa2_ni_setup(device_t dev) ep1_desc.if_id = 0; /* DPNI has the only endpoint */ ep1_desc.type = dinfo->dtype; - error = DPAA2_CMD_RC_GET_CONN(dev, child, dpaa2_mcp_tk(cmd, rc_token), + error = DPAA2_CMD_RC_GET_CONN(dev, child, DPAA2_CMD_TK(&cmd, rc_token), &ep1_desc, &ep2_desc, &link); - if (error) + if (error) { device_printf(dev, "%s: failed to obtain an object DPNI is " - "connected to: error=%d\n", __func__, error); - else { + "connected to\n", __func__); + goto free_dma; + } else { device_printf(dev, "connected to %s (id=%d)\n", dpaa2_ttos(ep2_desc.type), ep2_desc.obj_id); - error = dpaa2_ni_set_mac_addr(dev, cmd, rc_token, ni_token); - if (error) - device_printf(dev, "%s: failed to set MAC " - "address: error=%d\n", __func__, error); + error = dpaa2_ni_set_mac_addr(dev, &cmd, rc_token, ni_token); + if (error) { + device_printf(dev, "%s: failed to set MAC address\n", + __func__); + goto free_dma; + } if (ep2_desc.type == DPAA2_DEV_MAC) { /* @@ -856,8 +901,8 @@ dpaa2_ni_setup(device_t dev) * link state managed by MC firmware). */ error = DPAA2_CMD_MAC_OPEN(sc->dev, child, - dpaa2_mcp_tk(sc->cmd, sc->rc_token), - sc->mac.dpmac_id, &mac_token); + DPAA2_CMD_TK(&cmd, rc_token), sc->mac.dpmac_id, + &mac_token); /* * Under VFIO, the DPMAC might be sitting in another * container (DPRC) we don't have access to. @@ -866,22 +911,24 @@ dpaa2_ni_setup(device_t dev) */ if (error) { device_printf(dev, "%s: failed to open " - "connected DPMAC: %d (assuming in other DPRC)\n", __func__, - sc->mac.dpmac_id); + "connected DPMAC: %d (assuming in other " + "DPRC)\n", __func__, sc->mac.dpmac_id); link_type = DPAA2_MAC_LINK_TYPE_FIXED; } else { error = DPAA2_CMD_MAC_GET_ATTRIBUTES(dev, child, - sc->cmd, &attr); - if (error) + &cmd, &attr); + if (error) { device_printf(dev, "%s: failed to get " "DPMAC attributes: id=%d, " "error=%d\n", __func__, dinfo->id, error); - else + /* Fallback to the fixed link. */ + link_type = DPAA2_MAC_LINK_TYPE_FIXED; + } else { link_type = attr.link_type; + } + DPAA2_CMD_MAC_CLOSE(dev, child, &cmd); } - DPAA2_CMD_MAC_CLOSE(dev, child, dpaa2_mcp_tk(sc->cmd, - mac_token)); if (link_type == DPAA2_MAC_LINK_TYPE_FIXED) { device_printf(dev, "connected DPMAC is in FIXED " @@ -895,25 +942,29 @@ dpaa2_ni_setup(device_t dev) if (error == 0) { error = MEMAC_MDIO_SET_NI_DEV( sc->mac.phy_dev, dev); - if (error != 0) + if (error != 0) { device_printf(dev, "%s: failed " "to set dpni dev on memac " - "mdio dev %s: error=%d\n", - __func__, + "mdio dev %s\n", __func__, device_get_nameunit( - sc->mac.phy_dev), error); + sc->mac.phy_dev)); + goto free_dma; + } } if (error == 0) { error = MEMAC_MDIO_GET_PHY_LOC( sc->mac.phy_dev, &sc->mac.phy_loc); - if (error == ENODEV) + if (error == ENODEV) { error = 0; - if (error != 0) + } + if (error != 0) { device_printf(dev, "%s: failed " "to get phy location from " - "memac mdio dev %s: error=%d\n", + "memac mdio dev %s\n", __func__, device_get_nameunit( - sc->mac.phy_dev), error); + sc->mac.phy_dev)); + goto free_dma; + } } if (error == 0) { error = mii_attach(sc->mac.phy_dev, @@ -922,17 +973,21 @@ dpaa2_ni_setup(device_t dev) dpaa2_ni_media_status, BMSR_DEFCAPMASK, sc->mac.phy_loc, MII_OFFSET_ANY, 0); - if (error != 0) + if (error != 0) { device_printf(dev, "%s: failed " - "to attach to miibus: " - "error=%d\n", - __func__, error); + "to attach to miibus\n", + __func__); + goto free_dma; + } } - if (error == 0) + if (error == 0) { sc->mii = device_get_softc(sc->miibus); + } } else { device_printf(dev, "%s: DPMAC link type is not " "supported\n", __func__); + error = ENXIO; + goto free_dma; } } else if (ep2_desc.type == DPAA2_DEV_NI || ep2_desc.type == DPAA2_DEV_MUX || @@ -951,37 +1006,61 @@ dpaa2_ni_setup(device_t dev) * in link configuration. It might be necessary to attach miibus * and PHY before this point. */ - error = dpaa2_ni_set_pause_frame(dev, dpaa2_mcp_tk(cmd, ni_token)); + error = dpaa2_ni_set_pause_frame(dev, DPAA2_CMD_TK(&cmd, ni_token)); if (error) { device_printf(dev, "%s: failed to configure Rx/Tx pause " "frames\n", __func__); - return (error); + goto free_dma; } /* Configure ingress traffic classification. */ - error = dpaa2_ni_set_qos_table(dev, dpaa2_mcp_tk(cmd, ni_token)); - if (error) - device_printf(dev, "%s: failed to configure QoS table: " - "error=%d\n", __func__, error); + error = dpaa2_ni_set_qos_table(dev, &cmd); + if (error) { + device_printf(dev, "%s: failed to configure QoS table\n", + __func__); + goto free_dma; + } /* Add broadcast physical address to the MAC filtering table. */ memset(eth_bca, 0xff, ETHER_ADDR_LEN); - error = DPAA2_CMD_NI_ADD_MAC_ADDR(dev, child, cmd, eth_bca); + error = DPAA2_CMD_NI_ADD_MAC_ADDR(dev, child, &cmd, eth_bca); if (error) { device_printf(dev, "%s: failed to add broadcast physical " "address to the MAC filtering table\n", __func__); - return (error); + goto free_qos_kcfg; } /* Set the maximum allowed length for received frames. */ - error = DPAA2_CMD_NI_SET_MFL(dev, child, cmd, DPAA2_ETH_MFL); + error = DPAA2_CMD_NI_SET_MFL(dev, child, &cmd, DPAA2_ETH_MFL); if (error) { device_printf(dev, "%s: failed to set maximum length for " "received frames\n", __func__); - return (error); + goto free_qos_kcfg; } + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); return (0); + +free_qos_kcfg: + buf = &sc->qos_kcfg; + bus_dmamap_unload(buf->store.dmat, buf->store.dmap); + bus_dmamem_free(buf->store.dmat, buf->store.vaddr, buf->store.dmap); + buf->store.vaddr = NULL; +free_dma: + bus_dma_tag_destroy(sc->sgt_dmat); + bus_dma_tag_destroy(sc->qos_dmat); + bus_dma_tag_destroy(sc->rxd_dmat); + bus_dma_tag_destroy(sc->st_dmat); + bus_dma_tag_destroy(sc->tx_dmat); + bus_dma_tag_destroy(sc->bp_dmat); +close_ni: + DPAA2_CMD_NI_RESET(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); + DPAA2_CMD_NI_CLOSE(dev, child, &cmd); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +err_exit: + return (error); } /** @@ -991,34 +1070,30 @@ static int dpaa2_ni_setup_channels(device_t dev) { struct dpaa2_ni_softc *sc = device_get_softc(dev); - struct dpaa2_con_softc *consc; - struct dpaa2_devinfo *io_info, *con_info; - device_t io_dev, con_dev, child = dev; - struct dpaa2_ni_channel *channel; - struct dpaa2_io_notif_ctx *ctx; - struct dpaa2_con_notif_cfg notif_cfg; struct dpaa2_buf *buf; - int error; struct sysctl_ctx_list *sysctl_ctx; struct sysctl_oid *node; struct sysctl_oid_list *parent; uint32_t i, num_chan; + int error; - /* Calculate number of the channels based on the allocated resources. */ - for (i = 0; i < IO_RES_NUM; i++) - if (!sc->res[IO_RID(i)]) + /* Calculate number of channels based on the allocated resources. */ + for (i = 0; i < IO_RES_NUM; i++) { + if (!sc->res[IO_RID(i)]) { break; + } + } num_chan = i; - for (i = 0; i < CON_RES_NUM; i++) - if (!sc->res[CON_RID(i)]) + for (i = 0; i < CON_RES_NUM; i++) { + if (!sc->res[CON_RID(i)]) { break; + } + } num_chan = i < num_chan ? i : num_chan; - /* Limit maximum channels. */ + /* Limit maximum channels */ sc->chan_n = num_chan > DPAA2_NI_MAX_CHANNELS ? DPAA2_NI_MAX_CHANNELS : num_chan; - - /* Limit channels by number of the queues. */ sc->chan_n = sc->chan_n > sc->attr.num.queues ? sc->attr.num.queues : sc->chan_n; @@ -1026,137 +1101,213 @@ dpaa2_ni_setup_channels(device_t dev) sysctl_ctx = device_get_sysctl_ctx(sc->dev); parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)); - node = SYSCTL_ADD_NODE(sysctl_ctx, parent, OID_AUTO, "channels", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "DPNI Channels"); parent = SYSCTL_CHILDREN(node); - /* Setup channels for the portal. */ for (uint32_t i = 0; i < sc->chan_n; i++) { - /* Select software portal. */ - io_dev = (device_t) rman_get_start(sc->res[IO_RID(i)]); - io_info = device_get_ivars(io_dev); - - /* Select DPCON (channel). */ - con_dev = (device_t) rman_get_start(sc->res[CON_RID(i)]); - consc = device_get_softc(con_dev); - con_info = device_get_ivars(con_dev); - - /* Enable selected channel. */ - error = DPAA2_CMD_CON_ENABLE(dev, child, dpaa2_mcp_tk(consc->cmd, - consc->con_token)); + error = dpaa2_ni_setup_channel(dev, i); if (error) { - device_printf(dev, "%s: failed to enable channel: " - "dpcon_id=%d, chan_id=%d\n", __func__, con_info->id, - consc->attr.chan_id); - return (error); - } - - channel = malloc(sizeof(struct dpaa2_ni_channel), M_DPAA2_NI, - M_WAITOK | M_ZERO); - if (!channel) { - device_printf(dev, "%s: failed to allocate a channel\n", - __func__); - return (ENOMEM); + device_printf(dev, "%s: failed to configure channel: " + "idx=%d\n", __func__, i); + goto free_channels; } + } - sc->channels[i] = channel; + /* There is exactly one Rx error queue per DPNI. */ + error = dpaa2_ni_setup_fq(dev, sc->channels[0], DPAA2_NI_QUEUE_RX_ERR); + if (error) { + device_printf(dev, "%s: failed to setup RxError queue\n", + __func__); + goto free_channels; + } - channel->id = consc->attr.chan_id; - channel->flowid = i; - channel->ni_dev = dev; - channel->io_dev = io_dev; - channel->con_dev = con_dev; - channel->recycled_n = 0; + return (0); - buf = &channel->store; - buf->type = DPAA2_BUF_STORE; - buf->store.dmat = NULL; - buf->store.dmap = NULL; - buf->store.paddr = 0; +free_channels: + for (uint32_t i = 0; i < sc->chan_n; i++) { + if (!sc->channels[i]->ready) { + continue; + } + buf = &sc->channels[i]->store; + bus_dmamap_unload(buf->store.dmat, buf->store.dmap); + bus_dmamem_free(buf->store.dmat, buf->store.vaddr, + buf->store.dmap); buf->store.vaddr = NULL; + free(sc->channels[i], M_DPAA2_NI); + sc->channels[i] = NULL; + } + return (error); +} - /* For debug purposes only! */ - channel->tx_frames = 0; - channel->tx_dropped = 0; +/** + * @brief Сonfigure specific QBMan channel. + */ +static int +dpaa2_ni_setup_channel(device_t dev, const uint32_t chidx) +{ + device_t io_dev, con_dev, child = dev; + struct dpaa2_ni_softc *sc = device_get_softc(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(device_get_parent(dev)); + struct dpaa2_devinfo *io_info, *con_info; + struct dpaa2_con_softc *consc; + struct dpaa2_con_notif_cfg notif_cfg; + struct dpaa2_ni_channel *channel = NULL; + struct dpaa2_io_notif_ctx *ctx; + struct dpaa2_buf *buf; + struct dpaa2_cmd cmd; + uint16_t rc_token, con_token; + int error; - /* None of the frame queues for this channel configured yet. */ - channel->rxq_n = 0; + DPAA2_CMD_INIT(&cmd); - /* Setup WQ channel notification context. */ - ctx = &channel->ctx; - ctx->qman_ctx = (uint64_t) ctx; - ctx->cdan_en = true; - ctx->fq_chan_id = channel->id; - ctx->io_dev = channel->io_dev; - ctx->channel = channel; - ctx->poll = dpaa2_ni_poll; + io_dev = (device_t) rman_get_start(sc->res[IO_RID(chidx)]); + io_info = device_get_ivars(io_dev); + con_dev = (device_t) rman_get_start(sc->res[CON_RID(chidx)]); + consc = device_get_softc(con_dev); + con_info = device_get_ivars(con_dev); - /* Register the new notification context. */ - error = DPAA2_SWP_CONF_WQ_CHANNEL(channel->io_dev, ctx); - if (error) { - device_printf(dev, "%s: failed to register notification " - "context\n", __func__); - return (error); - } + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC\n", __func__); + goto err_exit; + } + error = DPAA2_CMD_CON_OPEN(dev, child, &cmd, con_info->id, &con_token); + if (error) { + device_printf(dev, "%s: failed to open DPCON: id=%d\n", + __func__, con_info->id); + goto close_rc; + } + error = DPAA2_CMD_CON_ENABLE(dev, child, &cmd); + if (error) { + device_printf(dev, "%s: failed to enable channel: " + "dpcon_id=%d, chan_id=%d\n", __func__, con_info->id, + consc->attr.chan_id); + goto close_con; + } - /* Register DPCON notification with Management Complex. */ - notif_cfg.dpio_id = io_info->id; - notif_cfg.prior = 0; - notif_cfg.qman_ctx = ctx->qman_ctx; - error = DPAA2_CMD_CON_SET_NOTIF(dev, child, dpaa2_mcp_tk( - consc->cmd, consc->con_token), ¬if_cfg); - if (error) { - device_printf(dev, "%s: failed to set DPCON " - "notification: dpcon_id=%d, chan_id=%d\n", __func__, - con_info->id, consc->attr.chan_id); - return (error); - } + channel = malloc(sizeof(struct dpaa2_ni_channel), M_DPAA2_NI, + M_WAITOK | M_ZERO); + if (!channel) { + device_printf(dev, "%s: failed to allocate channel\n", __func__); + error = ENOMEM; + goto disable_con; + } + channel->id = consc->attr.chan_id; + channel->flowid = chidx; + channel->ni_dev = dev; + channel->io_dev = io_dev; + channel->con_dev = con_dev; + channel->recycled_n = 0; + channel->ready = false; + + buf = &channel->store; + buf->type = DPAA2_BUF_STORE; + buf->store.dmat = NULL; + buf->store.dmap = NULL; + buf->store.paddr = 0; + buf->store.vaddr = NULL; + +#ifdef DPAA2_DEBUG + channel->tx_frames = 0; + channel->tx_dropped = 0; +#endif - /* Allocate initial # of Rx buffers and a channel storage. */ - error = dpaa2_ni_seed_buf_pool(sc, DPAA2_NI_BUFS_INIT); - if (error) { - device_printf(dev, "%s: failed to seed buffer pool\n", - __func__); - return (error); - } - error = dpaa2_ni_seed_chan_storage(sc, channel); - if (error) { - device_printf(dev, "%s: failed to seed channel " - "storage\n", __func__); - return (error); - } + /* None of the frame queues for this channel configured yet. */ + channel->rxq_n = 0; - /* Prepare queues for this channel. */ - error = dpaa2_ni_setup_fq(dev, channel, DPAA2_NI_QUEUE_TX_CONF); - if (error) { - device_printf(dev, "%s: failed to prepare TxConf " - "queue: error=%d\n", __func__, error); - return (error); - } - error = dpaa2_ni_setup_fq(dev, channel, DPAA2_NI_QUEUE_RX); - if (error) { - device_printf(dev, "%s: failed to prepare Rx queue: " - "error=%d\n", __func__, error); - return (error); - } + /* Setup WQ channel notification context */ + ctx = &channel->ctx; + ctx->qman_ctx = (uint64_t) ctx; + ctx->cdan_en = true; + ctx->fq_chan_id = channel->id; + ctx->io_dev = channel->io_dev; + ctx->channel = channel; + ctx->poll = dpaa2_ni_poll; - if (bootverbose) - device_printf(dev, "channel: dpio_id=%d " - "dpcon_id=%d chan_id=%d, priorities=%d\n", - io_info->id, con_info->id, channel->id, - consc->attr.prior_num); + /* Register new notification context */ + error = DPAA2_SWP_CONF_WQ_CHANNEL(channel->io_dev, ctx); + if (error) { + device_printf(dev, "%s: failed to register notification " + "context\n", __func__); + goto free_chan; } - /* There is exactly one Rx error queue per DPNI. */ - error = dpaa2_ni_setup_fq(dev, sc->channels[0], DPAA2_NI_QUEUE_RX_ERR); + /* Register DPCON notification with MC */ + notif_cfg.dpio_id = io_info->id; + notif_cfg.prior = 0; + notif_cfg.qman_ctx = ctx->qman_ctx; + error = DPAA2_CMD_CON_SET_NOTIF(dev, child, &cmd, ¬if_cfg); + if (error) { + device_printf(dev, "%s: failed to set DPCON " + "notification: dpcon_id=%d, chan_id=%d\n", __func__, + con_info->id, consc->attr.chan_id); + goto free_chan; + } + + /* Allocate initial # of Rx buffers and a channel storage */ + error = dpaa2_ni_seed_buf_pool(sc, DPAA2_NI_BUFS_INIT, io_dev); + if (error) { + device_printf(dev, "%s: failed to seed buffer pool\n", + __func__); + goto drain_bp; + } + error = dpaa2_ni_seed_chan_storage(sc, channel); if (error) { - device_printf(dev, "%s: failed to prepare RxError queue: " + device_printf(dev, "%s: failed to seed channel " + "storage\n", __func__); + goto drain_bp; + } + + /* Prepare queues for this channel */ + error = dpaa2_ni_setup_fq(dev, channel, DPAA2_NI_QUEUE_TX_CONF); + if (error) { + device_printf(dev, "%s: failed to prepare TxConf " + "queue: error=%d\n", __func__, error); + goto free_storage; + } + error = dpaa2_ni_setup_fq(dev, channel, DPAA2_NI_QUEUE_RX); + if (error) { + device_printf(dev, "%s: failed to prepare Rx queue: " "error=%d\n", __func__, error); - return (error); + goto free_storage; } + if (bootverbose) { + device_printf(dev, "channel: dpio_id=%d " + "dpcon_id=%d chan_id=%d, priorities=%d\n", + io_info->id, con_info->id, channel->id, + consc->attr.prior_num); + } + + DPAA2_CMD_CON_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, con_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); + sc->channels[chidx] = channel; + sc->channels[chidx]->ready = true; return (0); + +free_storage: + buf = &channel->store; + KASSERT(buf->type == DPAA2_BUF_STORE, ("%s:%d: failed", __func__, + __LINE__)); + bus_dmamap_unload(buf->store.dmat, buf->store.dmap); + bus_dmamem_free(buf->store.dmat, buf->store.vaddr, buf->store.dmap); + buf->store.vaddr = NULL; +drain_bp: + /* + * XXX-DSL: Acquire all of released buffers from the pool. + */ +free_chan: + KASSERT(channel != NULL, ("%s:%d: failed", __func__, __LINE__)); + free(channel, M_DPAA2_NI); +disable_con: + DPAA2_CMD_CON_DISABLE(dev, child, DPAA2_CMD_TK(&cmd, con_token)); +close_con: + DPAA2_CMD_CON_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, con_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +err_exit: + return (error); } /** @@ -1226,59 +1377,77 @@ dpaa2_ni_bind(device_t dev) { device_t bp_dev, child = dev; struct dpaa2_ni_softc *sc = device_get_softc(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(device_get_parent(dev)); + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); struct dpaa2_devinfo *bp_info; - struct dpaa2_cmd *cmd = sc->cmd; + struct dpaa2_cmd cmd; + struct dpaa2_buf *buf; struct dpaa2_ni_pools_cfg pools_cfg; struct dpaa2_ni_err_cfg err_cfg; struct dpaa2_ni_channel *chan; - uint16_t ni_token = sc->ni_token; + uint16_t rc_token, ni_token; int error; - /* Select buffer pool (only one available at the moment). */ + DPAA2_CMD_INIT(&cmd); + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: id=%d\n", __func__, + rcinfo->id); + goto err_exit; + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); + if (error) { + device_printf(dev, "%s: failed to open DPNI: id=%d\n", __func__, + dinfo->id); + goto close_rc; + } + + /* Select buffer pool (only one available at the moment) */ bp_dev = (device_t) rman_get_start(sc->res[BP_RID(0)]); bp_info = device_get_ivars(bp_dev); - /* Configure buffers pool. */ pools_cfg.pools_num = 1; pools_cfg.pools[0].bp_obj_id = bp_info->id; pools_cfg.pools[0].backup_flag = 0; pools_cfg.pools[0].buf_sz = sc->buf_sz; - error = DPAA2_CMD_NI_SET_POOLS(dev, child, dpaa2_mcp_tk(cmd, ni_token), + error = DPAA2_CMD_NI_SET_POOLS(dev, child, DPAA2_CMD_TK(&cmd, ni_token), &pools_cfg); if (error) { - device_printf(dev, "%s: failed to set buffer pools\n", __func__); - return (error); + device_printf(dev, "%s: failed to set buffer pool\n", __func__); + goto close_ni; } - /* Setup ingress traffic distribution. */ + /* Setup ingress traffic distribution */ error = dpaa2_ni_setup_rx_dist(dev); if (error && error != EOPNOTSUPP) { device_printf(dev, "%s: failed to setup ingress traffic " "distribution\n", __func__); - return (error); + goto close_ni; } - if (bootverbose && error == EOPNOTSUPP) + if (bootverbose && error == EOPNOTSUPP) { device_printf(dev, "Ingress traffic distribution not " "supported\n"); + } - /* Configure handling of error frames. */ + /* Configure handling of error frames */ err_cfg.err_mask = DPAA2_NI_FAS_RX_ERR_MASK; err_cfg.set_err_fas = false; err_cfg.action = DPAA2_NI_ERR_DISCARD; - error = DPAA2_CMD_NI_SET_ERR_BEHAVIOR(dev, child, cmd, &err_cfg); + error = DPAA2_CMD_NI_SET_ERR_BEHAVIOR(dev, child, &cmd, &err_cfg); if (error) { device_printf(dev, "%s: failed to set errors behavior\n", __func__); - return (error); + goto teardown_rx_dist; } - /* Configure channel queues to generate CDANs. */ + /* Configure channel queues to generate CDANs */ for (uint32_t i = 0; i < sc->chan_n; i++) { chan = sc->channels[i]; - /* Setup Rx flows. */ + /* Setup Rx flows */ for (uint32_t j = 0; j < chan->rxq_n; j++) { - error = dpaa2_ni_setup_rx_flow(dev, cmd, + error = dpaa2_ni_setup_rx_flow(dev, &cmd, &chan->rx_queues[j]); if (error) { device_printf(dev, "%s: failed to setup Rx " @@ -1286,9 +1455,8 @@ dpaa2_ni_bind(device_t dev) return (error); } } - - /* Setup Tx flow. */ - error = dpaa2_ni_setup_tx_flow(dev, cmd, &chan->txc_queue); + /* Setup Tx flow */ + error = dpaa2_ni_setup_tx_flow(dev, &cmd, &chan->txc_queue); if (error) { device_printf(dev, "%s: failed to setup Tx " "flow: error=%d\n", __func__, error); @@ -1296,8 +1464,8 @@ dpaa2_ni_bind(device_t dev) } } - /* Configure RxError queue to generate CDAN. */ - error = dpaa2_ni_setup_rx_err_flow(dev, cmd, &sc->rxe_queue); + /* Configure RxError queue to generate CDAN */ + error = dpaa2_ni_setup_rx_err_flow(dev, &cmd, &sc->rxe_queue); if (error) { device_printf(dev, "%s: failed to setup RxError flow: " "error=%d\n", __func__, error); @@ -1308,7 +1476,7 @@ dpaa2_ni_bind(device_t dev) * Get the Queuing Destination ID (QDID) that should be used for frame * enqueue operations. */ - error = DPAA2_CMD_NI_GET_QDID(dev, child, cmd, DPAA2_NI_QUEUE_TX, + error = DPAA2_CMD_NI_GET_QDID(dev, child, &cmd, DPAA2_NI_QUEUE_TX, &sc->tx_qdid); if (error) { device_printf(dev, "%s: failed to get Tx queuing destination " @@ -1316,7 +1484,21 @@ dpaa2_ni_bind(device_t dev) return (error); } + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); return (0); + +teardown_rx_dist: + buf = &sc->rxd_kcfg; + bus_dmamap_unload(buf->store.dmat, buf->store.dmap); + bus_dmamem_free(buf->store.dmat, buf->store.vaddr, buf->store.dmap); + buf->store.vaddr = NULL; +close_ni: + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +err_exit: + return (error); } /** @@ -1547,48 +1729,71 @@ dpaa2_ni_setup_irqs(device_t dev) { device_t child = dev; struct dpaa2_ni_softc *sc = device_get_softc(dev); - struct dpaa2_cmd *cmd = sc->cmd; - uint16_t ni_token = sc->ni_token; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_cmd cmd; + uint16_t rc_token, ni_token; int error; - /* Configure IRQs. */ + DPAA2_CMD_INIT(&cmd); + error = dpaa2_ni_setup_msi(sc); if (error) { device_printf(dev, "%s: failed to allocate MSI\n", __func__); - return (error); + goto err_exit; } if ((sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid[0], RF_ACTIVE | RF_SHAREABLE)) == NULL) { device_printf(dev, "%s: failed to allocate IRQ resource\n", __func__); - return (ENXIO); + goto free_msi; } if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE, NULL, dpaa2_ni_intr, sc, &sc->intr)) { device_printf(dev, "%s: failed to setup IRQ resource\n", __func__); - return (ENXIO); + goto free_res; + } + + /* Configure DPNI to generate interrupts */ + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC\n", __func__); + goto teardown_intr; + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); + if (error) { + device_printf(dev, "%s: failed to open DPNI\n", __func__); + goto close_rc; } - /* Configure DPNI to generate interrupts. */ - error = DPAA2_CMD_NI_SET_IRQ_MASK(dev, child, dpaa2_mcp_tk(cmd, - ni_token), DPNI_IRQ_INDEX, + error = DPAA2_CMD_NI_SET_IRQ_MASK(dev, child, + DPAA2_CMD_TK(&cmd, ni_token), DPNI_IRQ_INDEX, DPNI_IRQ_LINK_CHANGED | DPNI_IRQ_EP_CHANGED); if (error) { device_printf(dev, "%s: failed to set DPNI IRQ mask\n", __func__); - return (error); + goto close_ni; } - - /* Enable IRQ. */ - error = DPAA2_CMD_NI_SET_IRQ_ENABLE(dev, child, cmd, DPNI_IRQ_INDEX, + error = DPAA2_CMD_NI_SET_IRQ_ENABLE(dev, child, &cmd, DPNI_IRQ_INDEX, true); if (error) { device_printf(dev, "%s: failed to enable DPNI IRQ\n", __func__); - return (error); + goto close_ni; } return (0); + +close_ni: + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +teardown_intr: +free_res: +free_msi: +err_exit: + return (error); } /** @@ -1620,45 +1825,76 @@ dpaa2_ni_setup_msi(struct dpaa2_ni_softc *sc) static int dpaa2_ni_setup_if_caps(struct dpaa2_ni_softc *sc) { - const bool en_rxcsum = sc->ifp->if_capenable & IFCAP_RXCSUM; - const bool en_txcsum = sc->ifp->if_capenable & IFCAP_TXCSUM; device_t dev = sc->dev; device_t child = dev; + const bool en_rxcsum = sc->ifp->if_capenable & IFCAP_RXCSUM; + const bool en_txcsum = sc->ifp->if_capenable & IFCAP_TXCSUM; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_cmd cmd; + uint16_t rc_token, ni_token; int error; - /* Setup checksums validation. */ - error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, dpaa2_mcp_tk(sc->cmd, - sc->ni_token), DPAA2_NI_OFL_RX_L3_CSUM, en_rxcsum); + DPAA2_CMD_INIT(&cmd); + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: id=%d\n", __func__, + rcinfo->id); + goto err_exit; + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); + if (error) { + device_printf(dev, "%s: failed to open DPNI: id=%d\n", __func__, + dinfo->id); + goto close_rc; + } + + + /* Setup checksums validation */ + + error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, DPAA2_CMD_TK(&cmd, + ni_token), DPAA2_NI_OFL_RX_L3_CSUM, en_rxcsum); if (error) { device_printf(dev, "%s: failed to %s L3 checksum validation\n", __func__, en_rxcsum ? "enable" : "disable"); - return (error); + goto close_ni; } - error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, sc->cmd, + error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, &cmd, DPAA2_NI_OFL_RX_L4_CSUM, en_rxcsum); if (error) { device_printf(dev, "%s: failed to %s L4 checksum validation\n", __func__, en_rxcsum ? "enable" : "disable"); - return (error); + goto close_ni; } - /* Setup checksums generation. */ - error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, sc->cmd, + /* Setup checksums generation */ + + error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, &cmd, DPAA2_NI_OFL_TX_L3_CSUM, en_txcsum); if (error) { device_printf(dev, "%s: failed to %s L3 checksum generation\n", __func__, en_txcsum ? "enable" : "disable"); - return (error); + goto close_ni; } - error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, sc->cmd, + error = DPAA2_CMD_NI_SET_OFFLOAD(dev, child, &cmd, DPAA2_NI_OFL_TX_L4_CSUM, en_txcsum); if (error) { device_printf(dev, "%s: failed to %s L4 checksum generation\n", __func__, en_txcsum ? "enable" : "disable"); - return (error); + goto close_ni; } + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); return (0); + +close_ni: + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +err_exit: + return (error); } /** @@ -1667,37 +1903,69 @@ dpaa2_ni_setup_if_caps(struct dpaa2_ni_softc *sc) static int dpaa2_ni_setup_if_flags(struct dpaa2_ni_softc *sc) { - const bool en_promisc = sc->ifp->if_flags & IFF_PROMISC; - const bool en_allmulti = sc->ifp->if_flags & IFF_ALLMULTI; device_t dev = sc->dev; device_t child = dev; + const bool en_promisc = sc->ifp->if_flags & IFF_PROMISC; + const bool en_allmulti = sc->ifp->if_flags & IFF_ALLMULTI; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_cmd cmd; + uint16_t rc_token, ni_token; int error; - error = DPAA2_CMD_NI_SET_MULTI_PROMISC(dev, child, dpaa2_mcp_tk(sc->cmd, - sc->ni_token), en_promisc ? true : en_allmulti); + DPAA2_CMD_INIT(&cmd); + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: id=%d\n", __func__, + rcinfo->id); + goto err_exit; + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); + if (error) { + device_printf(dev, "%s: failed to open DPNI: id=%d\n", __func__, + dinfo->id); + goto close_rc; + } + + error = DPAA2_CMD_NI_SET_MULTI_PROMISC(dev, child, DPAA2_CMD_TK(&cmd, + ni_token), en_promisc ? true : en_allmulti); if (error) { device_printf(dev, "%s: failed to %s multicast promiscuous " "mode\n", __func__, en_allmulti ? "enable" : "disable"); - return (error); + goto close_ni; } - error = DPAA2_CMD_NI_SET_UNI_PROMISC(dev, child, sc->cmd, en_promisc); + error = DPAA2_CMD_NI_SET_UNI_PROMISC(dev, child, &cmd, en_promisc); if (error) { device_printf(dev, "%s: failed to %s unicast promiscuous mode\n", __func__, en_promisc ? "enable" : "disable"); - return (error); + goto close_ni; } + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); return (0); + +close_ni: + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +err_exit: + return (error); } static int dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc) { struct sysctl_ctx_list *ctx; - struct sysctl_oid *node, *node2; - struct sysctl_oid_list *parent, *parent2; + struct sysctl_oid *node; + struct sysctl_oid_list *parent; +#ifdef DPAA2_DEBUG + struct sysctl_oid *node2; + struct sysctl_oid_list *parent2; char cbuf[128]; +#endif int i; ctx = device_get_sysctl_ctx(sc->dev); @@ -1712,6 +1980,8 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc) CTLTYPE_U64 | CTLFLAG_RD, sc, 0, dpaa2_ni_collect_stats, "IU", dpni_stat_sysctls[i].desc); } + +#ifdef DPAA2_DEBUG SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "rx_anomaly_frames", CTLFLAG_RD, &sc->rx_anomaly_frames, "Rx frames in the buffers outside of the buffer pools"); @@ -1733,6 +2003,7 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc) SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "tx_sg_frames", CTLFLAG_RD, &sc->tx_sg_frames, "Tx S/G frames"); +#endif /* DPAA2_DEBUG */ SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "buf_num", CTLTYPE_U32 | CTLFLAG_RD, sc, 0, dpaa2_ni_collect_buf_num, @@ -1743,7 +2014,9 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc) parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)); - /* Add channels statistics. */ + /* Add channels statistics */ + +#ifdef DPAA2_DEBUG node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "channels", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "DPNI Channels"); parent = SYSCTL_CHILDREN(node); @@ -1761,6 +2034,7 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc) CTLFLAG_RD, &sc->channels[i]->tx_dropped, "Tx dropped counter"); } +#endif return (0); } @@ -1793,7 +2067,7 @@ dpaa2_ni_setup_dma(struct dpaa2_ni_softc *sc) if (error) { device_printf(dev, "%s: failed to create DMA tag for buffer " "pool\n", __func__); - return (error); + goto err_exit; } /* DMA tag to map Tx mbufs. */ @@ -1811,7 +2085,7 @@ dpaa2_ni_setup_dma(struct dpaa2_ni_softc *sc) if (error) { device_printf(dev, "%s: failed to create DMA tag for Tx " "buffers\n", __func__); - return (error); + goto free_bp_tag; } /* DMA tag to allocate channel storage. */ @@ -1828,7 +2102,7 @@ dpaa2_ni_setup_dma(struct dpaa2_ni_softc *sc) if (error) { device_printf(dev, "%s: failed to create DMA tag for channel " "storage\n", __func__); - return (error); + goto free_tx_tag; } /* DMA tag for Rx distribution key. */ @@ -1845,7 +2119,7 @@ dpaa2_ni_setup_dma(struct dpaa2_ni_softc *sc) if (error) { device_printf(dev, "%s: failed to create DMA tag for Rx " "distribution key\n", __func__); - return (error); + goto free_st_tag; } error = bus_dma_tag_create( @@ -1861,7 +2135,7 @@ dpaa2_ni_setup_dma(struct dpaa2_ni_softc *sc) if (error) { device_printf(dev, "%s: failed to create DMA tag for QoS key\n", __func__); - return (error); + goto free_rxd_tag; } error = bus_dma_tag_create( @@ -1877,10 +2151,23 @@ dpaa2_ni_setup_dma(struct dpaa2_ni_softc *sc) if (error) { device_printf(dev, "%s: failed to create DMA tag for S/G " "tables\n", __func__); - return (error); + goto free_qos_tag; } return (0); + +free_qos_tag: + bus_dma_tag_destroy(sc->qos_dmat); +free_rxd_tag: + bus_dma_tag_destroy(sc->rxd_dmat); +free_st_tag: + bus_dma_tag_destroy(sc->st_dmat); +free_tx_tag: + bus_dma_tag_destroy(sc->tx_dmat); +free_bp_tag: + bus_dma_tag_destroy(sc->bp_dmat); +err_exit: + return (error); } /** @@ -2075,29 +2362,32 @@ dpaa2_ni_set_qos_table(device_t dev, struct dpaa2_cmd *cmd) struct dpaa2_buf *buf = &sc->qos_kcfg; int error; + KASSERT(buf->type == DPAA2_BUF_STORE, ("%s: not storage buffer", + __func__)); + if (sc->attr.num.rx_tcs == 1 || !(sc->attr.options & DPNI_OPT_HAS_KEY_MASKING)) { - if (bootverbose) - device_printf(dev, "Ingress traffic classification is " - "not supported\n"); - return (0); + if (bootverbose) { + device_printf(dev, "Rx traffic classification not " + "supported\n"); + } + goto exit; + } + if (__predict_true(buf->store.dmat == NULL)) { + buf->store.dmat = sc->qos_dmat; } /* * Allocate a buffer visible to the device to hold the QoS table key * configuration. */ - KASSERT(buf->type == DPAA2_BUF_STORE, ("%s: not storage buffer", - __func__)); - if (__predict_true(buf->store.dmat == NULL)) - buf->store.dmat = sc->qos_dmat; error = bus_dmamem_alloc(buf->store.dmat, &buf->store.vaddr, BUS_DMA_ZERO | BUS_DMA_COHERENT, &buf->store.dmap); if (error) { device_printf(dev, "%s: failed to allocate a buffer for QoS key " "configuration\n", __func__); - return (error); + goto err_exit; } error = bus_dmamap_load(buf->store.dmat, buf->store.dmap, @@ -2106,7 +2396,7 @@ dpaa2_ni_set_qos_table(device_t dev, struct dpaa2_cmd *cmd) if (error) { device_printf(dev, "%s: failed to map QoS key configuration " "buffer into bus space\n", __func__); - return (error); + goto free_buf; } tbl.default_tc = 0; @@ -2116,16 +2406,26 @@ dpaa2_ni_set_qos_table(device_t dev, struct dpaa2_cmd *cmd) error = DPAA2_CMD_NI_SET_QOS_TABLE(dev, child, cmd, &tbl); if (error) { device_printf(dev, "%s: failed to set QoS table\n", __func__); - return (error); + goto unload_buf; } + /* XXX-DSL: Shouldn't QoS table be cleared before setting? */ error = DPAA2_CMD_NI_CLEAR_QOS_TABLE(dev, child, cmd); if (error) { device_printf(dev, "%s: failed to clear QoS table\n", __func__); - return (error); + goto unload_buf; } +exit: return (0); + +unload_buf: + bus_dmamap_unload(buf->store.dmat, buf->store.dmap); +free_buf: + bus_dmamem_free(buf->store.dmat, buf->store.vaddr, buf->store.dmap); + buf->store.vaddr = NULL; +err_exit: + return (error); } static int @@ -2150,7 +2450,7 @@ dpaa2_ni_set_mac_addr(device_t dev, struct dpaa2_cmd *cmd, uint16_t rc_token, if (error) { device_printf(dev, "%s: failed to obtain the MAC address " "associated with the physical port\n", __func__); - return (error); + goto err_exit; } /* Get primary MAC address from the DPNI attributes. */ @@ -2158,7 +2458,7 @@ dpaa2_ni_set_mac_addr(device_t dev, struct dpaa2_cmd *cmd, uint16_t rc_token, if (error) { device_printf(dev, "%s: failed to obtain primary MAC address\n", __func__); - return (error); + goto err_exit; } if (!ETHER_IS_ZERO(mac_addr)) { @@ -2168,7 +2468,7 @@ dpaa2_ni_set_mac_addr(device_t dev, struct dpaa2_cmd *cmd, uint16_t rc_token, if (error) { device_printf(dev, "%s: failed to set primary MAC " "address\n", __func__); - return (error); + goto err_exit; } for (int i = 0; i < ETHER_ADDR_LEN; i++) sc->mac.addr[i] = mac_addr[i]; @@ -2183,7 +2483,7 @@ dpaa2_ni_set_mac_addr(device_t dev, struct dpaa2_cmd *cmd, uint16_t rc_token, if (error) { device_printf(dev, "%s: failed to set random primary " "MAC address\n", __func__); - return (error); + goto err_exit; } for (int i = 0; i < ETHER_ADDR_LEN; i++) sc->mac.addr[i] = mac_addr[i]; @@ -2193,50 +2493,65 @@ dpaa2_ni_set_mac_addr(device_t dev, struct dpaa2_cmd *cmd, uint16_t rc_token, } return (0); + +err_exit: + return (error); } static void dpaa2_ni_miibus_statchg(device_t dev) { - struct dpaa2_ni_softc *sc; - device_t child; + device_t child = dev; + struct dpaa2_ni_softc *sc = device_get_softc(dev); struct dpaa2_mac_link_state mac_link = { 0 }; - uint16_t mac_token; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_cmd cmd; + uint16_t rc_token, mac_token; int error, link_state; - sc = device_get_softc(dev); - if (sc->fixed_link || sc->mii == NULL) + if (sc->fixed_link || sc->mii == NULL) { return; + } /* * Note: ifp link state will only be changed AFTER we are called so we * cannot rely on ifp->if_linkstate here. */ if (sc->mii->mii_media_status & IFM_AVALID) { - if (sc->mii->mii_media_status & IFM_ACTIVE) + if (sc->mii->mii_media_status & IFM_ACTIVE) { link_state = LINK_STATE_UP; - else + } else { link_state = LINK_STATE_DOWN; - } else + } + } else { link_state = LINK_STATE_UNKNOWN; + } if (link_state != sc->link_state) { - sc->link_state = link_state; - - child = sc->dev; - error = DPAA2_CMD_MAC_OPEN(sc->dev, child, dpaa2_mcp_tk(sc->cmd, - sc->rc_token), sc->mac.dpmac_id, &mac_token); + DPAA2_CMD_INIT(&cmd); + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, + &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: id=%d, " + "error=%d\n", __func__, rcinfo->id, error); + return; + } + error = DPAA2_CMD_MAC_OPEN(dev, child, &cmd, sc->mac.dpmac_id, + &mac_token); if (error) { device_printf(sc->dev, "%s: failed to open DPMAC: " "id=%d, error=%d\n", __func__, sc->mac.dpmac_id, error); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, + rc_token)); return; } if (link_state == LINK_STATE_UP || link_state == LINK_STATE_DOWN) { - /* Update DPMAC link state. */ + /* Update DPMAC link state */ mac_link.supported = sc->mii->mii_media.ifm_media; mac_link.advert = sc->mii->mii_media.ifm_media; mac_link.rate = 1000; /* TODO: Where to get from? */ /* ifmedia_baudrate? */ @@ -2246,16 +2561,17 @@ dpaa2_ni_miibus_statchg(device_t dev) mac_link.up = (link_state == LINK_STATE_UP) ? true : false; mac_link.state_valid = true; - /* Inform DPMAC about link state. */ - error = DPAA2_CMD_MAC_SET_LINK_STATE(sc->dev, child, - sc->cmd, &mac_link); - if (error) + /* Inform DPMAC about link state */ + error = DPAA2_CMD_MAC_SET_LINK_STATE(dev, child, &cmd, + &mac_link); + if (error) { device_printf(sc->dev, "%s: failed to set DPMAC " "link state: id=%d, error=%d\n", __func__, sc->mac.dpmac_id, error); + } } - DPAA2_CMD_MAC_CLOSE(sc->dev, child, dpaa2_mcp_tk(sc->cmd, - mac_token)); + DPAA2_CMD_MAC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, mac_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); } } @@ -2322,12 +2638,18 @@ dpaa2_ni_media_tick(void *arg) static void dpaa2_ni_init(void *arg) { + device_t dev = ((struct dpaa2_ni_softc *) arg)->dev; + device_t child = dev; struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *) arg; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_cmd cmd; struct ifnet *ifp = sc->ifp; - device_t dev = sc->dev; - device_t child = dev; + uint16_t rc_token, ni_token; int error; + DPAA2_CMD_INIT(&cmd); + DPNI_LOCK(sc); if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) { DPNI_UNLOCK(sc); @@ -2335,25 +2657,39 @@ dpaa2_ni_init(void *arg) } DPNI_UNLOCK(sc); - error = DPAA2_CMD_NI_ENABLE(dev, child, dpaa2_mcp_tk(sc->cmd, - sc->ni_token)); - if (error) + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: error=%d\n", + __func__, error); + goto reset_callout; + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); + if (error) { + device_printf(dev, "%s: failed to open DPNI: error=%d\n", + __func__, error); + goto close_rc; + } + error = DPAA2_CMD_NI_ENABLE(dev, child, &cmd); + if (error) { device_printf(dev, "%s: failed to enable DPNI: error=%d\n", __func__, error); + } + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +reset_callout: DPNI_LOCK(sc); - if (sc->mii) + if (sc->mii) { mii_mediachg(sc->mii); + } callout_reset(&sc->mii_callout, hz, dpaa2_ni_media_tick, sc); - ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; DPNI_UNLOCK(sc); /* Force link-state update to initilize things. */ dpaa2_ni_miibus_statchg(dev); - - return; } static int @@ -2402,17 +2738,22 @@ dpaa2_ni_qflush(struct ifnet *ifp) } static int -dpaa2_ni_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +dpaa2_ni_ioctl(struct ifnet *ifp, u_long c, caddr_t data) { + device_t dev = ((struct dpaa2_ni_softc *) ifp->if_softc)->dev; + device_t child = dev; struct dpaa2_ni_softc *sc = ifp->if_softc; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_cmd cmd; struct ifreq *ifr = (struct ifreq *) data; - device_t dev, child; + uint16_t rc_token, ni_token; uint32_t changed = 0; int mtu, error, rc = 0; - dev = child = sc->dev; + DPAA2_CMD_INIT(&cmd); - switch (cmd) { + switch (c) { case SIOCSIFMTU: DPNI_LOCK(sc); mtu = ifr->ifr_mtu; @@ -2423,14 +2764,34 @@ dpaa2_ni_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) ifp->if_mtu = mtu; DPNI_UNLOCK(sc); - /* Update maximum frame length. */ - error = DPAA2_CMD_NI_SET_MFL(dev, child, dpaa2_mcp_tk(sc->cmd, - sc->ni_token), mtu + ETHER_HDR_LEN); + /* Update maximum frame length */ + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, + &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: id=%d, " + "error=%d\n", __func__, rcinfo->id, error); + return (error); + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, + &ni_token); + if (error) { + device_printf(dev, "%s: failed to open DPNI: id=%d, " + "error=%d\n", __func__, dinfo->id, error); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, + rc_token)); + return (error); + } + error = DPAA2_CMD_NI_SET_MFL(dev, child, DPAA2_CMD_TK(&cmd, + ni_token), mtu + ETHER_HDR_LEN); if (error) { device_printf(dev, "%s: failed to update maximum frame " "length: error=%d\n", __func__, error); - return (error); } + + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); + rc = error; break; case SIOCSIFCAP: changed = ifp->if_capenable ^ ifr->ifr_reqcap; @@ -2474,23 +2835,24 @@ dpaa2_ni_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) if (ifp->if_drv_flags & IFF_DRV_RUNNING) { DPNI_UNLOCK(sc); rc = dpaa2_ni_update_mac_filters(ifp); - if (rc) + if (rc) { device_printf(dev, "%s: failed to update MAC " "filters: error=%d\n", __func__, rc); + } DPNI_LOCK(sc); } DPNI_UNLOCK(sc); break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: - if (sc->mii) - rc = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, cmd); - else if(sc->fixed_link) { - rc = ifmedia_ioctl(ifp, ifr, &sc->fixed_ifmedia, cmd); + if (sc->mii) { + rc = ifmedia_ioctl(ifp, ifr, &sc->mii->mii_media, c); + } else if (sc->fixed_link) { + rc = ifmedia_ioctl(ifp, ifr, &sc->fixed_ifmedia, c); } break; default: - rc = ether_ioctl(ifp, cmd, data); + rc = ether_ioctl(ifp, c, data); } return (rc); @@ -2499,79 +2861,145 @@ dpaa2_ni_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) static int dpaa2_ni_update_mac_filters(struct ifnet *ifp) { - struct dpaa2_ni_softc *sc = ifp->if_softc; + device_t dev = ((struct dpaa2_ni_softc *) ifp->if_softc)->dev; + device_t child = dev; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); struct dpaa2_ni_mcaddr_ctx ctx; - device_t dev, child; + struct dpaa2_cmd cmd; + uint16_t rc_token, ni_token; int error; - dev = child = sc->dev; + DPAA2_CMD_INIT(&cmd); + + /* Remove all multicast MAC filters */ - /* Remove all multicast MAC filters. */ - error = DPAA2_CMD_NI_CLEAR_MAC_FILTERS(dev, child, dpaa2_mcp_tk(sc->cmd, - sc->ni_token), false, true); + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: id=%d\n", __func__, + rcinfo->id); + goto err_exit; + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); + if (error) { + device_printf(dev, "%s: failed to open DPNI: id=%d\n", __func__, + dinfo->id); + goto close_rc; + } + error = DPAA2_CMD_NI_CLEAR_MAC_FILTERS(dev, child, &cmd, false, true); if (error) { device_printf(dev, "%s: failed to clear multicast MAC filters: " "error=%d\n", __func__, error); - return (error); + goto close_ni; } + DPAA2_CMD_NI_CLOSE(dev, child, &cmd); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); + ctx.ifp = ifp; ctx.error = 0; ctx.nent = 0; - if_foreach_llmaddr(ifp, dpaa2_ni_add_maddr, &ctx); - return (ctx.error); + +close_ni: + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +err_exit: + return (error); } static u_int dpaa2_ni_add_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) { struct dpaa2_ni_mcaddr_ctx *ctx = arg; + device_t dev = ((struct dpaa2_ni_softc *) ctx->ifp->if_softc)->dev; + device_t child = dev; struct dpaa2_ni_softc *sc = ctx->ifp->if_softc; - device_t dev, child; - - dev = child = sc->dev; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_cmd cmd; + uint16_t rc_token, ni_token; + int error; - if (ctx->error != 0) + if (ctx->error != 0) { return (0); + } + + DPAA2_CMD_INIT(&cmd); + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: id=%d, error=%d\n", + __func__, rcinfo->id, error); + goto exit; + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); + if (error) { + device_printf(dev, "%s: failed to open DPNI: id=%d, error=%d\n", + __func__, dinfo->id, error); + goto close_rc; + } if (ETHER_IS_MULTICAST(LLADDR(sdl))) { - ctx->error = DPAA2_CMD_NI_ADD_MAC_ADDR(dev, child, dpaa2_mcp_tk( - sc->cmd, sc->ni_token), LLADDR(sdl)); + ctx->error = DPAA2_CMD_NI_ADD_MAC_ADDR(dev, child, &cmd, + LLADDR(sdl)); if (ctx->error != 0) { device_printf(dev, "%s: can't add more then %d MAC " "addresses, switching to the multicast promiscuous " "mode\n", __func__, ctx->nent); - - /* Enable multicast promiscuous mode. */ + /* Enable multicast promiscuous mode */ DPNI_LOCK(sc); ctx->ifp->if_flags |= IFF_ALLMULTI; sc->if_flags |= IFF_ALLMULTI; ctx->error = dpaa2_ni_setup_if_flags(sc); DPNI_UNLOCK(sc); - - return (0); + goto close_ni; } ctx->nent++; } + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); return (1); + +close_ni: + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +exit: + return (0); } static void dpaa2_ni_intr(void *arg) { - struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *) arg; - device_t child = sc->dev; + device_t dev = ((struct dpaa2_ni_softc *) arg)->dev; + device_t child = dev; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_cmd cmd; uint32_t status = ~0u; /* clear all IRQ status bits */ + uint16_t rc_token, ni_token; int error; - error = DPAA2_CMD_NI_GET_IRQ_STATUS(sc->dev, child, dpaa2_mcp_tk(sc->cmd, - sc->ni_token), DPNI_IRQ_INDEX, &status); - if (error) - device_printf(sc->dev, "%s: failed to obtain IRQ status: " - "error=%d\n", __func__, error); + DPAA2_CMD_INIT(&cmd); + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + goto exit; + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); + if (error) { + goto close_rc; + } + DPAA2_CMD_NI_GET_IRQ_STATUS(dev, child, &cmd, DPNI_IRQ_INDEX, &status); + DPAA2_CMD_NI_CLOSE(dev, child, &cmd); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +exit: + return; } /** @@ -2614,7 +3042,8 @@ dpaa2_ni_bp_task(void *arg, int count) /* Double allocated buffers number if free buffers < 25%. */ if (bp_conf.free_bufn < (buf_num >> 2)) { - (void)dpaa2_ni_seed_buf_pool(sc, buf_num); + (void)dpaa2_ni_seed_buf_pool(sc, buf_num, + sc->channels[0]->io_dev); DPAA2_ATOMIC_XCHG(&sc->buf_free, bp_conf.free_bufn); } } @@ -2709,7 +3138,9 @@ dpaa2_ni_tx_locked(struct dpaa2_ni_softc *sc, struct dpaa2_ni_tx_ring *tx, if (m_d == NULL) { device_printf(sc->dev, "%s: mbuf " "defragmentation failed\n", __func__); +#ifdef DPAA2_DEBUG fq->chan->tx_dropped++; +#endif goto err; } @@ -2719,7 +3150,9 @@ dpaa2_ni_tx_locked(struct dpaa2_ni_softc *sc, struct dpaa2_ni_tx_ring *tx, if (__predict_false(error != 0)) { device_printf(sc->dev, "%s: failed to load " "mbuf: error=%d\n", __func__, error); +#ifdef DPAA2_DEBUG fq->chan->tx_dropped++; +#endif goto err; } } @@ -2729,7 +3162,9 @@ dpaa2_ni_tx_locked(struct dpaa2_ni_softc *sc, struct dpaa2_ni_tx_ring *tx, if (__predict_false(error != 0)) { device_printf(sc->dev, "%s: failed to build frame " "descriptor: error=%d\n", __func__, error); +#ifdef DPAA2_DEBUG fq->chan->tx_dropped++; +#endif goto err_unload; } @@ -2749,10 +3184,14 @@ dpaa2_ni_tx_locked(struct dpaa2_ni_softc *sc, struct dpaa2_ni_tx_ring *tx, BUS_DMASYNC_PREWRITE); if (rc != 1) { +#ifdef DPAA2_DEBUG fq->chan->tx_dropped++; +#endif goto err_unload; } else { +#ifdef DPAA2_DEBUG fq->chan->tx_frames++; +#endif } return; @@ -2845,7 +3284,7 @@ dpaa2_ni_rx(struct dpaa2_ni_channel *chan, struct dpaa2_ni_fq *fq, __func__, paddr, buf->rx.paddr); } - /* Update statistics. */ +#ifdef DPAA2_DEBUG switch (dpaa2_ni_fd_err(fd)) { case 1: /* Enqueue rejected by QMan */ sc->rx_enq_rej_frames++; @@ -2866,6 +3305,7 @@ dpaa2_ni_rx(struct dpaa2_ni_channel *chan, struct dpaa2_ni_fq *fq, default: break; } +#endif m = buf->rx.m; buf->rx.m = NULL; @@ -3050,7 +3490,7 @@ dpaa2_ni_cmp_api_version(struct dpaa2_ni_softc *sc, uint16_t major, * @brief Allocate Rx buffers visible to QBMan and release them to the pool. */ static int -dpaa2_ni_seed_buf_pool(struct dpaa2_ni_softc *sc, uint32_t seedn) +dpaa2_ni_seed_buf_pool(struct dpaa2_ni_softc *sc, uint32_t seedn, device_t iodev) { device_t bp_dev; struct dpaa2_bp_softc *bpsc; @@ -3059,23 +3499,23 @@ dpaa2_ni_seed_buf_pool(struct dpaa2_ni_softc *sc, uint32_t seedn) const int allocated = DPAA2_ATOMIC_READ(&sc->buf_num); int i, error, bufn = 0; - KASSERT(sc->bp_dmat != NULL, ("%s: DMA tag for buffer pool not " - "created?", __func__)); + KASSERT(sc->bp_dmat != NULL, ("%s: no DMA tag for pool?", __func__)); /* There's only one buffer pool for now. */ bp_dev = (device_t) rman_get_start(sc->res[BP_RID(0)]); bpsc = device_get_softc(bp_dev); - /* Limit # of buffers released to the pool. */ - if (allocated + seedn > DPAA2_NI_BUFS_MAX) + /* Limit # of buffers released to the pool */ + if (allocated + seedn > DPAA2_NI_BUFS_MAX) { seedn = DPAA2_NI_BUFS_MAX - allocated; + } - /* Release "seedn" buffers to the pool. */ + /* Release "seedn" buffers to the pool */ for (i = allocated; i < (allocated + seedn); i++) { - /* Enough buffers were allocated for a single command. */ + /* Enough buffers were allocated for a single command */ if (bufn == DPAA2_SWP_BUFS_PER_CMD) { - error = DPAA2_SWP_RELEASE_BUFS(sc->channels[0]->io_dev, - bpsc->attr.bpid, paddr, bufn); + error = DPAA2_SWP_RELEASE_BUFS(iodev, bpsc->attr.bpid, + paddr, bufn); if (error) { device_printf(sc->dev, "%s: failed to release " "buffers to the pool (1)\n", __func__); @@ -3092,16 +3532,17 @@ dpaa2_ni_seed_buf_pool(struct dpaa2_ni_softc *sc, uint32_t seedn) buf->rx.paddr = 0; buf->rx.vaddr = NULL; error = dpaa2_ni_seed_rxbuf(sc, buf, i); - if (error) + if (error) { break; + } paddr[bufn] = buf->rx.paddr; bufn++; } - /* Release if there are buffers left. */ + /* Release if there are buffers left */ if (bufn > 0) { - error = DPAA2_SWP_RELEASE_BUFS(sc->channels[0]->io_dev, - bpsc->attr.bpid, paddr, bufn); + error = DPAA2_SWP_RELEASE_BUFS(iodev, bpsc->attr.bpid, paddr, + bufn); if (error) { device_printf(sc->dev, "%s: failed to release " "buffers to the pool (2)\n", __func__); @@ -3119,8 +3560,8 @@ dpaa2_ni_seed_buf_pool(struct dpaa2_ni_softc *sc, uint32_t seedn) static int dpaa2_ni_seed_rxbuf(struct dpaa2_ni_softc *sc, struct dpaa2_buf *buf, int idx) { - struct mbuf *m; - bus_dmamap_t dmap; + struct mbuf *m = NULL; + bus_dmamap_t dmap = NULL; bus_dma_segment_t segs; int error, nsegs; @@ -3128,9 +3569,10 @@ dpaa2_ni_seed_rxbuf(struct dpaa2_ni_softc *sc, struct dpaa2_buf *buf, int idx) "allocated?", __func__)); KASSERT(buf->type == DPAA2_BUF_RX, ("%s: not Rx buffer", __func__)); - /* Keep DMA tag for this buffer. */ - if (__predict_false(buf->rx.dmat == NULL)) + if (__predict_false(buf->rx.dmat == NULL)) { + /* Keep DMA tag for this buffer. */ buf->rx.dmat = sc->bp_dmat; + } /* Create a DMA map for the giving buffer if it doesn't exist yet. */ if (__predict_false(buf->rx.dmap == NULL)) { @@ -3139,7 +3581,7 @@ dpaa2_ni_seed_rxbuf(struct dpaa2_ni_softc *sc, struct dpaa2_buf *buf, int idx) device_printf(sc->dev, "%s: failed to create DMA map " "for buffer: buf_idx=%d, error=%d\n", __func__, idx, error); - return (error); + goto err_exit; } buf->rx.dmap = dmap; } @@ -3150,13 +3592,15 @@ dpaa2_ni_seed_rxbuf(struct dpaa2_ni_softc *sc, struct dpaa2_buf *buf, int idx) if (__predict_false(m == NULL)) { device_printf(sc->dev, "%s: failed to allocate mbuf for " "buffer\n", __func__); - return (ENOMEM); + error = ENOMEM; + goto free_dmamap; } m->m_len = m->m_ext.ext_size; m->m_pkthdr.len = m->m_ext.ext_size; buf->rx.m = m; - } else + } else { m = buf->rx.m; + } error = bus_dmamap_load_mbuf_sg(buf->rx.dmat, buf->rx.dmap, m, &segs, &nsegs, BUS_DMA_NOWAIT); @@ -3165,9 +3609,7 @@ dpaa2_ni_seed_rxbuf(struct dpaa2_ni_softc *sc, struct dpaa2_buf *buf, int idx) if (__predict_false(error != 0 || nsegs != 1)) { device_printf(sc->dev, "%s: failed to map mbuf: error=%d, " "nsegs=%d\n", __func__, error, nsegs); - bus_dmamap_unload(buf->rx.dmat, buf->rx.dmap); - m_freem(m); - return (error); + goto unload_dmamap; } buf->rx.paddr = segs.ds_addr; buf->rx.vaddr = m->m_data; @@ -3186,6 +3628,18 @@ dpaa2_ni_seed_rxbuf(struct dpaa2_ni_softc *sc, struct dpaa2_buf *buf, int idx) (buf->rx.paddr & DPAA2_NI_BUF_ADDR_MASK); return (0); + +unload_dmamap: + bus_dmamap_unload(buf->rx.dmat, buf->rx.dmap); + if (m != NULL) { + m_freem(m); + } +free_dmamap: + if (dmap != NULL) { + bus_dmamap_destroy(buf->rx.dmat, dmap); + } +err_exit: + return (error); } /** @@ -3243,14 +3697,13 @@ dpaa2_ni_seed_chan_storage(struct dpaa2_ni_softc *sc, struct dpaa2_ni_channel *chan) { struct dpaa2_buf *buf = &chan->store; + bool dmamem_alloc = false; int error; - KASSERT(sc->st_dmat != NULL, ("%s: channel storage DMA tag is not " - "allocated?", __func__)); - KASSERT(buf->type == DPAA2_BUF_STORE, ("%s: not channel storage buffer", - __func__)); + KASSERT(sc->st_dmat != NULL, ("%s: no DMA tag for storage?", __func__)); + KASSERT(buf->type == DPAA2_BUF_STORE, ("%s:%d: failed", __func__, + __LINE__)); - /* Keep DMA tag for this buffer. */ if (__predict_false(buf->store.dmat == NULL)) { buf->store.dmat = sc->st_dmat; } @@ -3261,8 +3714,9 @@ dpaa2_ni_seed_chan_storage(struct dpaa2_ni_softc *sc, if (error) { device_printf(sc->dev, "%s: failed to allocate channel " "storage\n", __func__); - return (error); + goto err_exit; } + dmamem_alloc = true; } if (__predict_false(buf->store.paddr == 0)) { @@ -3272,7 +3726,7 @@ dpaa2_ni_seed_chan_storage(struct dpaa2_ni_softc *sc, if (error) { device_printf(sc->dev, "%s: failed to map channel " "storage\n", __func__); - return (error); + goto unload_dmamap; } } @@ -3280,6 +3734,16 @@ dpaa2_ni_seed_chan_storage(struct dpaa2_ni_softc *sc, chan->store_idx = 0; return (0); + +unload_dmamap: + bus_dmamap_unload(buf->store.dmat, buf->store.dmap); + if (dmamem_alloc) { + bus_dmamem_free(buf->store.dmat, buf->store.vaddr, + buf->store.dmap); + buf->store.vaddr = NULL; + } +err_exit: + return (error); } /** @@ -3327,8 +3791,10 @@ dpaa2_ni_build_fd(struct dpaa2_ni_softc *sc, struct dpaa2_ni_tx_ring *tx, return (error); } buf->tx.paddr = buf->tx.sgt_paddr; - buf->tx.vaddr = buf->tx.sgt_vaddr; + buf->tx.vaddr = buf->tx.sgt_vaddr; +#ifdef DPAA2_DEBUG sc->tx_sg_frames++; /* for sysctl(9) */ +#endif } else { return (EINVAL); } @@ -3350,12 +3816,21 @@ dpaa2_ni_build_fd(struct dpaa2_ni_softc *sc, struct dpaa2_ni_tx_ring *tx, return (0); } +#ifdef DPAA2_DEBUG static int dpaa2_ni_fd_err(struct dpaa2_fd *fd) { return ((fd->ctrl >> DPAA2_NI_FD_ERR_SHIFT) & DPAA2_NI_FD_ERR_MASK); } +static int +dpaa2_ni_fd_format(struct dpaa2_fd *fd) +{ + return ((enum dpaa2_fd_format)((fd->offset_fmt_sl >> + DPAA2_NI_FD_FMT_SHIFT) & DPAA2_NI_FD_FMT_MASK)); +} +#endif + static uint32_t dpaa2_ni_fd_data_len(struct dpaa2_fd *fd) { @@ -3393,13 +3868,6 @@ dpaa2_ni_fd_txbuf_idx(struct dpaa2_fd *fd) DPAA2_NI_TXBUF_IDX_MASK); } -static int -dpaa2_ni_fd_format(struct dpaa2_fd *fd) -{ - return ((enum dpaa2_fd_format)((fd->offset_fmt_sl >> - DPAA2_NI_FD_FMT_SHIFT) & DPAA2_NI_FD_FMT_MASK)); -} - static bool dpaa2_ni_fd_short_len(struct dpaa2_fd *fd) { @@ -3419,18 +3887,40 @@ dpaa2_ni_fd_offset(struct dpaa2_fd *fd) static int dpaa2_ni_collect_stats(SYSCTL_HANDLER_ARGS) { - struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *) arg1; + device_t dev = ((struct dpaa2_ni_softc *) arg1)->dev; + device_t child = dev; + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); struct dpni_stat *stat = &dpni_stat_sysctls[oidp->oid_number]; - device_t child = sc->dev; + struct dpaa2_cmd cmd; uint64_t cnt[DPAA2_NI_STAT_COUNTERS]; uint64_t result = 0; + uint16_t rc_token, ni_token; int error; - error = DPAA2_CMD_NI_GET_STATISTICS(sc->dev, child, - dpaa2_mcp_tk(sc->cmd, sc->ni_token), stat->page, 0, cnt); - if (!error) + DPAA2_CMD_INIT(&cmd); + + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: id=%d, error=%d\n", + __func__, rcinfo->id, error); + goto exit; + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); + if (error) { + device_printf(dev, "%s: failed to open DPNI: id=%d, error=%d\n", + __func__, dinfo->id, error); + goto close_rc; + } + error = DPAA2_CMD_NI_GET_STATISTICS(dev, child, &cmd, stat->page, 0, cnt); + if (!error) { result = cnt[stat->cnt]; + } + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +exit: return (sysctl_handle_64(oidp, &result, 0, req)); } @@ -3481,29 +3971,42 @@ dpaa2_ni_set_dist_key(device_t dev, enum dpaa2_ni_dist_mode type, uint64_t flags { device_t child = dev; struct dpaa2_ni_softc *sc = device_get_softc(dev); + struct dpaa2_devinfo *dinfo = device_get_ivars(dev); + struct dpaa2_devinfo *rcinfo = device_get_ivars(dinfo->pdev); + struct dpaa2_buf *buf = &sc->rxd_kcfg; + struct dpaa2_cmd cmd; struct dpkg_profile_cfg cls_cfg; struct dpkg_extract *key; - struct dpaa2_buf *buf = &sc->rxd_kcfg; + uint16_t rc_token, ni_token; int i, error = 0; - KASSERT(buf->type == DPAA2_BUF_STORE, ("%s: not storage buffer", + KASSERT(type == DPAA2_NI_DIST_MODE_HASH, ("%s: unsupported Rx dist mode", __func__)); - if (__predict_true(buf->store.dmat == NULL)) + KASSERT(sc->rxd_dmat != NULL, ("%s: no DMA tag?", __func__)); + KASSERT(buf->type == DPAA2_BUF_STORE, ("%s:%d: failed", __func__, + __LINE__)); + + DPAA2_CMD_INIT(&cmd); + + if (__predict_true(buf->store.dmat == NULL)) { buf->store.dmat = sc->rxd_dmat; + } memset(&cls_cfg, 0, sizeof(cls_cfg)); - /* Configure extracts according to the given flags. */ + /* Configure extracts according to the given flags */ for (i = 0; i < ARRAY_SIZE(dist_fields); i++) { key = &cls_cfg.extracts[cls_cfg.num_extracts]; - if (!(flags & dist_fields[i].id)) + if (!(flags & dist_fields[i].id)) { continue; + } if (cls_cfg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) { device_printf(dev, "%s: failed to add key extraction " "rule\n", __func__); - return (E2BIG); + error = E2BIG; + goto err_exit; } key->type = DPKG_EXTRACT_FROM_HDR; @@ -3518,35 +4021,63 @@ dpaa2_ni_set_dist_key(device_t dev, enum dpaa2_ni_dist_mode type, uint64_t flags if (error != 0) { device_printf(dev, "%s: failed to allocate a buffer for Rx " "traffic distribution key configuration\n", __func__); - return (error); + goto err_exit; } error = dpaa2_ni_prepare_key_cfg(&cls_cfg, (uint8_t *) buf->store.vaddr); if (error != 0) { device_printf(dev, "%s: failed to prepare key configuration: " "error=%d\n", __func__, error); - return (error); + goto free_dmamem; } - /* Prepare for setting the Rx dist. */ + /* Prepare for setting the Rx dist */ error = bus_dmamap_load(buf->store.dmat, buf->store.dmap, buf->store.vaddr, DPAA2_CLASSIFIER_DMA_SIZE, dpaa2_ni_dmamap_cb, &buf->store.paddr, BUS_DMA_NOWAIT); if (error != 0) { device_printf(sc->dev, "%s: failed to map a buffer for Rx " "traffic distribution key configuration\n", __func__); - return (error); + goto free_dmamem; } - if (type == DPAA2_NI_DIST_MODE_HASH) { - error = DPAA2_CMD_NI_SET_RX_TC_DIST(dev, child, dpaa2_mcp_tk( - sc->cmd, sc->ni_token), sc->attr.num.queues, 0, - DPAA2_NI_DIST_MODE_HASH, buf->store.paddr); - if (error != 0) - device_printf(dev, "%s: failed to set distribution mode " - "and size for the traffic class\n", __func__); + error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); + if (error) { + device_printf(dev, "%s: failed to open DPRC: id=%d\n", __func__, + rcinfo->id); + goto unload_dmamem; + } + error = DPAA2_CMD_NI_OPEN(dev, child, &cmd, dinfo->id, &ni_token); + if (error) { + device_printf(dev, "%s: failed to open DPNI: id=%d\n", __func__, + dinfo->id); + goto close_rc; } + error = DPAA2_CMD_NI_SET_RX_TC_DIST(dev, child, &cmd, + sc->attr.num.queues, 0, DPAA2_NI_DIST_MODE_HASH, buf->store.paddr); + if (error != 0) { + device_printf(dev, "%s: failed to set distribution mode " + "and size for the traffic class\n", __func__); + goto close_ni; + } + + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); + return (0); + +close_ni: + DPAA2_CMD_NI_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, ni_token)); +close_rc: + DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); +unload_dmamem: + bus_dmamap_unload(buf->store.dmat, buf->store.dmap); +free_dmamem: + bus_dmamem_free(buf->store.dmat, buf->store.vaddr, buf->store.dmap); + buf->store.vaddr = NULL; +err_exit: + /* EOPNOTSUPP is a special case, shouldn't be returned here */ + KASSERT(error != EOPNOTSUPP, ("%s:%d: failed", __func__, __LINE__)); return (error); } diff --git a/sys/dev/dpaa2/dpaa2_ni.h b/sys/dev/dpaa2/dpaa2_ni.h index 929a4d0d4966f1..4572b18eac45f3 100644 --- a/sys/dev/dpaa2/dpaa2_ni.h +++ b/sys/dev/dpaa2/dpaa2_ni.h @@ -269,10 +269,12 @@ struct dpaa2_ni_channel { device_t con_dev; uint16_t id; uint16_t flowid; + bool ready; - /* For debug purposes only! */ +#ifdef DPAA2_DEBUG uint64_t tx_frames; uint64_t tx_dropped; +#endif /* DPAA2_DEBUG */ /* Context to configure CDAN. */ struct dpaa2_io_notif_ctx ctx; @@ -534,7 +536,7 @@ struct dpaa2_ni_softc { uint16_t buf_align; uint16_t buf_sz; - /* For debug purposes only! */ +#ifdef DPAA2_DEBUG uint64_t rx_anomaly_frames; uint64_t rx_single_buf_frames; uint64_t rx_sg_buf_frames; @@ -542,15 +544,11 @@ struct dpaa2_ni_softc { uint64_t rx_ieoi_err_frames; uint64_t tx_single_buf_frames; uint64_t tx_sg_frames; +#endif /* Attributes of the DPAA2 network interface. */ struct dpaa2_ni_attr attr; - /* Helps to send commands to MC. */ - struct dpaa2_cmd *cmd; - uint16_t rc_token; - uint16_t ni_token; - /* For network interface and miibus. */ struct ifnet *ifp; uint32_t if_flags; diff --git a/sys/dev/dpaa2/dpaa2_rc.c b/sys/dev/dpaa2/dpaa2_rc.c index f5d7bae92e0424..26348d3ad3af14 100644 --- a/sys/dev/dpaa2/dpaa2_rc.c +++ b/sys/dev/dpaa2/dpaa2_rc.c @@ -132,44 +132,40 @@ dpaa2_rc_attach(device_t dev) sc->dev = dev; sc->unit = device_get_unit(dev); - if (sc->unit == 0) { - /* Root DPRC should be attached directly to the MC bus. */ - pdev = device_get_parent(dev); - mcsc = device_get_softc(pdev); + /* Root DPRC should be attached directly to the MC bus. */ + pdev = device_get_parent(dev); + mcsc = device_get_softc(pdev); - KASSERT(strcmp(device_get_name(pdev), "dpaa2_mc") == 0, - ("root DPRC should be attached to the MC bus")); + KASSERT(strcmp(device_get_name(pdev), "dpaa2_mc") == 0, + ("%s: root DPRC should be attached to the MC bus", __func__)); + KASSERT(sc->unit == 0, ("%s: child DPRCs are not supported", __func__)); - /* - * Allocate devinfo to let the parent MC bus access ICID of the - * DPRC object. - */ - dinfo = malloc(sizeof(struct dpaa2_devinfo), M_DPAA2_RC, - M_WAITOK | M_ZERO); - if (!dinfo) { - device_printf(dev, "%s: failed to allocate " - "dpaa2_devinfo\n", __func__); - dpaa2_rc_detach(dev); - return (ENXIO); - } - device_set_ivars(dev, dinfo); + /* + * Allocate devinfo to let the parent MC bus access ICID of the + * DPRC object. + */ + dinfo = malloc(sizeof(struct dpaa2_devinfo), M_DPAA2_RC, + M_WAITOK | M_ZERO); + if (!dinfo) { + device_printf(dev, "%s: failed to allocate dpaa2_devinfo\n", + __func__); + dpaa2_rc_detach(dev); + return (ENXIO); + } + device_set_ivars(dev, dinfo); - dinfo->pdev = pdev; - dinfo->dev = dev; - dinfo->dtype = DPAA2_DEV_RC; - dinfo->portal = NULL; + dinfo->pdev = pdev; + dinfo->dev = dev; + dinfo->dtype = DPAA2_DEV_RC; + dinfo->portal = NULL; - /* Prepare helper portal object to send commands to MC. */ - error = dpaa2_mcp_init_portal(&dinfo->portal, mcsc->res[0], - &mcsc->map[0], DPAA2_PORTAL_DEF); - if (error) { - device_printf(dev, "%s: failed to initialize dpaa2_mcp: " - "error=%d\n", __func__, error); - dpaa2_rc_detach(dev); - return (ENXIO); - } - } else { - /* TODO: Child DPRCs aren't supported yet. */ + /* Prepare helper portal object to send commands to MC. */ + error = dpaa2_mcp_init_portal(&dinfo->portal, mcsc->res[0], + &mcsc->map[0], DPAA2_PORTAL_DEF); + if (error) { + device_printf(dev, "%s: failed to initialize dpaa2_mcp: " + "error=%d\n", __func__, error); + dpaa2_rc_detach(dev); return (ENXIO); } @@ -2746,108 +2742,82 @@ dpaa2_rc_discover(struct dpaa2_rc_softc *sc) device_t rcdev = sc->dev; device_t child = sc->dev; struct dpaa2_devinfo *rcinfo = device_get_ivars(rcdev); - struct dpaa2_cmd *cmd = NULL; + struct dpaa2_cmd cmd; struct dpaa2_rc_attr dprc_attr; struct dpaa2_obj obj; uint32_t major, minor, rev, obj_count; uint16_t rc_token; int rc; - /* Allocate a command to send to MC hardware. */ - rc = dpaa2_mcp_init_command(&cmd, DPAA2_CMD_DEF); - if (rc) { - device_printf(rcdev, "%s: failed to allocate dpaa2_cmd: " - "error=%d\n", __func__, rc); - return (ENXIO); - } + DPAA2_CMD_INIT(&cmd); - /* Print MC firmware version. */ - rc = DPAA2_CMD_MNG_GET_VERSION(rcdev, child, cmd, &major, &minor, &rev); + rc = DPAA2_CMD_MNG_GET_VERSION(rcdev, child, &cmd, &major, &minor, &rev); if (rc) { device_printf(rcdev, "%s: failed to get MC firmware version: " "error=%d\n", __func__, rc); - dpaa2_mcp_free_command(cmd); - return (ENXIO); + goto err_exit; } device_printf(rcdev, "MC firmware version: %u.%u.%u\n", major, minor, rev); - /* Obtain container ID associated with a given MC portal. */ - rc = DPAA2_CMD_MNG_GET_CONTAINER_ID(rcdev, child, cmd, &sc->cont_id); + rc = DPAA2_CMD_MNG_GET_CONTAINER_ID(rcdev, child, &cmd, &sc->cont_id); if (rc) { device_printf(rcdev, "%s: failed to get container id: " "error=%d\n", __func__, rc); - dpaa2_mcp_free_command(cmd); - return (ENXIO); + goto err_exit; } - if (bootverbose) - device_printf(rcdev, "Resource container ID: %u\n", sc->cont_id); + device_printf(rcdev, "Resource container ID: %u\n", sc->cont_id); - /* Open the resource container. */ - rc = DPAA2_CMD_RC_OPEN(rcdev, child, cmd, sc->cont_id, &rc_token); + rc = DPAA2_CMD_RC_OPEN(rcdev, child, &cmd, sc->cont_id, &rc_token); if (rc) { device_printf(rcdev, "%s: failed to open container: cont_id=%u, " "error=%d\n", __func__, sc->cont_id, rc); - dpaa2_mcp_free_command(cmd); - return (ENXIO); + goto err_exit; } - - /* Obtain a number of objects in this container. */ - rc = DPAA2_CMD_RC_GET_OBJ_COUNT(rcdev, child, cmd, &obj_count); + rc = DPAA2_CMD_RC_GET_OBJ_COUNT(rcdev, child, &cmd, &obj_count); if (rc) { device_printf(rcdev, "%s: failed to count objects in container: " "cont_id=%u, error=%d\n", __func__, sc->cont_id, rc); - DPAA2_CMD_RC_CLOSE(rcdev, child, cmd); - dpaa2_mcp_free_command(cmd); - return (ENXIO); + goto close_rc; } - if (bootverbose) - device_printf(rcdev, "Objects in container: %u\n", obj_count); + device_printf(rcdev, "Objects in container: %u\n", obj_count); - /* Obtain container attributes (including ICID). */ - rc = DPAA2_CMD_RC_GET_ATTRIBUTES(rcdev, child, cmd, &dprc_attr); + rc = DPAA2_CMD_RC_GET_ATTRIBUTES(rcdev, child, &cmd, &dprc_attr); if (rc) { - device_printf(rcdev, "%s: failed to get attributes of the " - "container: cont_id=%u, error=%d\n", __func__, sc->cont_id, - rc); - DPAA2_CMD_RC_CLOSE(rcdev, child, cmd); - dpaa2_mcp_free_command(cmd); - return (ENXIO); - } - if (bootverbose) - device_printf(rcdev, "Isolation context ID: %u\n", - dprc_attr.icid); - if (rcinfo) { - rcinfo->id = dprc_attr.cont_id; - rcinfo->portal_id = dprc_attr.portal_id; - rcinfo->icid = dprc_attr.icid; + device_printf(rcdev, "%s: failed to get container attributes: " + "cont_id=%u, error=%d\n", __func__, sc->cont_id, rc); + goto close_rc; } + device_printf(rcdev, "Isolation context ID: %u\n", dprc_attr.icid); + + rcinfo->id = dprc_attr.cont_id; + rcinfo->portal_id = dprc_attr.portal_id; + rcinfo->icid = dprc_attr.icid; /* * Add MC portals before everything else. * TODO: Discover DPAA2 objects on-demand. */ for (uint32_t i = 0; i < obj_count; i++) { - rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, cmd, i, &obj); + rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, &cmd, i, &obj); if (rc) continue; /* Skip silently for now. */ if (obj.type != DPAA2_DEV_MCP) continue; - dpaa2_rc_add_managed_child(sc, cmd, &obj); + dpaa2_rc_add_managed_child(sc, &cmd, &obj); } /* Probe and attach MC portals. */ bus_generic_probe(rcdev); rc = bus_generic_attach(rcdev); if (rc) { - DPAA2_CMD_RC_CLOSE(rcdev, child, cmd); - dpaa2_mcp_free_command(cmd); + DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd); return (rc); } /* Add managed devices (except DPMCPs) to the resource container. */ for (uint32_t i = 0; i < obj_count; i++) { - rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, cmd, i, &obj); + rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, &cmd, i, &obj); if (rc && bootverbose) { if (rc == DPAA2_CMD_STAT_UNKNOWN_OBJ) { device_printf(rcdev, "%s: skip unsupported " @@ -2863,20 +2833,19 @@ dpaa2_rc_discover(struct dpaa2_rc_softc *sc) if (obj.type == DPAA2_DEV_MCP) continue; /* Already added. */ - dpaa2_rc_add_managed_child(sc, cmd, &obj); + dpaa2_rc_add_managed_child(sc, &cmd, &obj); } /* Probe and attach managed devices properly. */ bus_generic_probe(rcdev); rc = bus_generic_attach(rcdev); if (rc) { - DPAA2_CMD_RC_CLOSE(rcdev, child, cmd); - dpaa2_mcp_free_command(cmd); + DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd); return (rc); } /* Add other devices to the resource container. */ for (uint32_t i = 0; i < obj_count; i++) { - rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, cmd, i, &obj); + rc = DPAA2_CMD_RC_GET_OBJ(rcdev, child, &cmd, i, &obj); if (rc == DPAA2_CMD_STAT_UNKNOWN_OBJ && bootverbose) { device_printf(rcdev, "%s: skip unsupported DPAA2 " "object: idx=%u\n", __func__, i); @@ -2886,15 +2855,19 @@ dpaa2_rc_discover(struct dpaa2_rc_softc *sc) "idx=%u, error=%d\n", __func__, i, rc); continue; } - dpaa2_rc_add_child(sc, cmd, &obj); + dpaa2_rc_add_child(sc, &cmd, &obj); } - DPAA2_CMD_RC_CLOSE(rcdev, child, cmd); - dpaa2_mcp_free_command(cmd); + DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd); /* Probe and attach the rest of devices. */ bus_generic_probe(rcdev); return (bus_generic_attach(rcdev)); + +close_rc: + DPAA2_CMD_RC_CLOSE(rcdev, child, DPAA2_CMD_TK(&cmd, rc_token)); +err_exit: + return (ENXIO); } /** @@ -3139,50 +3112,39 @@ dpaa2_rc_configure_irq(device_t rcdev, device_t child, int rid, uint64_t addr, { struct dpaa2_devinfo *rcinfo; struct dpaa2_devinfo *dinfo; - struct dpaa2_cmd *cmd; - uint16_t rc_token; + struct dpaa2_cmd cmd; + uint16_t tok; int rc = EINVAL; + DPAA2_CMD_INIT(&cmd); + if (device_get_parent(child) == rcdev && rid >= 1) { rcinfo = device_get_ivars(rcdev); dinfo = device_get_ivars(child); - /* Allocate a command to send to MC hardware. */ - rc = dpaa2_mcp_init_command(&cmd, DPAA2_CMD_DEF); + rc = DPAA2_CMD_RC_OPEN(rcdev, child, &cmd, rcinfo->id, &tok); if (rc) { - device_printf(rcdev, "%s: failed to allocate dpaa2_cmd: " - "error=%d\n", __func__, rc); - return (ENODEV); - } - - /* Open resource container. */ - rc = DPAA2_CMD_RC_OPEN(rcdev, child, cmd, rcinfo->id, &rc_token); - if (rc) { - dpaa2_mcp_free_command(cmd); device_printf(rcdev, "%s: failed to open DPRC: " "error=%d\n", __func__, rc); return (ENODEV); } + /* Set MSI address and value. */ - rc = DPAA2_CMD_RC_SET_OBJ_IRQ(rcdev, child, cmd, rid - 1, addr, + rc = DPAA2_CMD_RC_SET_OBJ_IRQ(rcdev, child, &cmd, rid-1, addr, data, rid, dinfo->id, dinfo->dtype); if (rc) { - dpaa2_mcp_free_command(cmd); device_printf(rcdev, "%s: failed to setup IRQ: " "rid=%d, addr=%jx, data=%x, error=%d\n", __func__, rid, addr, data, rc); return (ENODEV); } - /* Close resource container. */ - rc = DPAA2_CMD_RC_CLOSE(rcdev, child, cmd); + + rc = DPAA2_CMD_RC_CLOSE(rcdev, child, &cmd); if (rc) { - dpaa2_mcp_free_command(cmd); device_printf(rcdev, "%s: failed to close DPRC: " "error=%d\n", __func__, rc); return (ENODEV); } - - dpaa2_mcp_free_command(cmd); rc = 0; } diff --git a/sys/dev/dpaa2/dpaa2_swp.c b/sys/dev/dpaa2/dpaa2_swp.c index 2ceed08159ef9e..3eddc19d5fe389 100644 --- a/sys/dev/dpaa2/dpaa2_swp.c +++ b/sys/dev/dpaa2/dpaa2_swp.c @@ -165,18 +165,16 @@ enum qbman_sdqcr_fc { }; /* Routines to execute software portal commands. */ -static int dpaa2_swp_exec_mgmt_command(struct dpaa2_swp *, - struct dpaa2_swp_cmd *, struct dpaa2_swp_rsp *, uint8_t); -static int dpaa2_swp_exec_br_command(struct dpaa2_swp *, struct dpaa2_swp_cmd *, +static int dpaa2_swp_exec_mgmt(struct dpaa2_swp *, struct dpaa2_swp_cmd *, + struct dpaa2_swp_rsp *, uint8_t); +static int dpaa2_swp_exec_br(struct dpaa2_swp *, struct dpaa2_swp_cmd *, uint32_t); -static int dpaa2_swp_exec_vdc_command_locked(struct dpaa2_swp *, - struct dpaa2_swp_cmd *); +static int dpaa2_swp_exec_vdc_locked(struct dpaa2_swp *, struct dpaa2_swp_cmd *); /* Management Commands helpers. */ -static int dpaa2_swp_send_mgmt_command(struct dpaa2_swp *, - struct dpaa2_swp_cmd *, uint8_t); -static int dpaa2_swp_wait_for_mgmt_response(struct dpaa2_swp *, - struct dpaa2_swp_rsp *); +static int dpaa2_swp_send_mgmt(struct dpaa2_swp *, struct dpaa2_swp_cmd *, + uint8_t); +static int dpaa2_swp_wait_for_mgmt(struct dpaa2_swp *, struct dpaa2_swp_rsp *); /* Helper subroutines. */ static int dpaa2_swp_cyc_diff(uint8_t, uint8_t, uint8_t); @@ -539,7 +537,7 @@ dpaa2_swp_conf_wq_channel(struct dpaa2_swp *swp, uint16_t chan_id, cmd.ctrl = cdan_en ? 1u : 0u; cmd.ctx = ctx; - error = dpaa2_swp_exec_mgmt_command(swp, (struct dpaa2_swp_cmd *) &cmd, + error = dpaa2_swp_exec_mgmt(swp, (struct dpaa2_swp_cmd *) &cmd, (struct dpaa2_swp_rsp *) &rsp, CMDID_SWP_WQCHAN_CONFIGURE); if (error) return (error); @@ -585,7 +583,7 @@ dpaa2_swp_query_bp(struct dpaa2_swp *swp, uint16_t bpid, cmd.bpid = bpid; - error = dpaa2_swp_exec_mgmt_command(swp, (struct dpaa2_swp_cmd *) &cmd, + error = dpaa2_swp_exec_mgmt(swp, (struct dpaa2_swp_cmd *) &cmd, (struct dpaa2_swp_rsp *) &rsp, CMDID_SWP_BP_QUERY); if (error) return (error); @@ -626,7 +624,7 @@ dpaa2_swp_release_bufs(struct dpaa2_swp *swp, uint16_t bpid, bus_addr_t *buf, cmd.bpid = bpid; cmd.verb |= 1 << 5; /* Switch release buffer command to valid. */ - error = dpaa2_swp_exec_br_command(swp, (struct dpaa2_swp_cmd *) &cmd, + error = dpaa2_swp_exec_br(swp, (struct dpaa2_swp_cmd *) &cmd, buf_num); if (error) { device_printf(swp->desc->dpio_dev, "buffers release command " @@ -637,6 +635,54 @@ dpaa2_swp_release_bufs(struct dpaa2_swp *swp, uint16_t bpid, bus_addr_t *buf, return (0); } +int +dpaa2_swp_acquire_bufs(struct dpaa2_swp *swp, uint16_t bpid, bus_addr_t *buf[], + uint32_t *buf_num) +{ + struct __packed { + uint8_t verb; + uint8_t _reserved1; + uint16_t bpid; + uint8_t buf_num; + uint8_t _reserved2[59]; + } cmd = {0}; + struct __packed { + uint8_t verb; + uint8_t result; + uint16_t _reserved1; + uint8_t buf_num; + uint8_t _reserved2[3]; + uint64_t buf[7]; + } rsp = {0}; + uint32_t bn; + int error; + + KASSERT(swp != NULL && buf != NULL && buf_num != NULL && + *buf_num > 0u && *buf_num <= DPAA2_SWP_BUFS_PER_CMD, + ("%s:%d: failed", __func__, __LINE__)); + + cmd.bpid = bpid; + cmd.buf_num = bn = *buf_num; + + error = dpaa2_swp_exec_mgmt(swp, (struct dpaa2_swp_cmd *) &cmd, + (struct dpaa2_swp_rsp *) &rsp, CMDID_SWP_MC_ACQUIRE); + if (error) { + return (error); + } else if (rsp.result != QBMAN_CMD_RC_OK) { + device_printf(swp->desc->dpio_dev, "%s: buffer acquire command " + "error: result=0x%02x\n", __func__, rsp.result); + return (EIO); + } + + bn = bn < rsp.buf_num ? bn : rsp.buf_num; + for (uint32_t i = 0; i < bn; i++) { + buf[i] = (bus_addr_t *) rsp.buf[i]; + } + *buf_num = bn; + + return (0); +} + int dpaa2_swp_dqrr_next_locked(struct dpaa2_swp *swp, struct dpaa2_dq *dq, uint32_t *idx) @@ -757,8 +803,7 @@ dpaa2_swp_pull(struct dpaa2_swp *swp, uint16_t chan_id, struct dpaa2_buf *buf, return (ENOENT); } - error = dpaa2_swp_exec_vdc_command_locked(swp, - (struct dpaa2_swp_cmd *) &cmd); + error = dpaa2_swp_exec_vdc_locked(swp, (struct dpaa2_swp_cmd *) &cmd); if (error != 0) { DPAA2_SWP_UNLOCK(swp); return (error); @@ -935,7 +980,7 @@ dpaa2_swp_cyc_diff(uint8_t ringsize, uint8_t first, uint8_t last) * @brief Execute Buffer Release Command (BRC). */ static int -dpaa2_swp_exec_br_command(struct dpaa2_swp *swp, struct dpaa2_swp_cmd *cmd, +dpaa2_swp_exec_br(struct dpaa2_swp *swp, struct dpaa2_swp_cmd *cmd, uint32_t buf_num) { struct __packed with_verb { @@ -1005,7 +1050,7 @@ dpaa2_swp_exec_br_command(struct dpaa2_swp *swp, struct dpaa2_swp_cmd *cmd, * command is present in the SDQCR register. */ static int -dpaa2_swp_exec_vdc_command_locked(struct dpaa2_swp *swp, +dpaa2_swp_exec_vdc_locked(struct dpaa2_swp *swp, struct dpaa2_swp_cmd *cmd) { struct __packed with_verb { @@ -1049,7 +1094,7 @@ dpaa2_swp_exec_vdc_command_locked(struct dpaa2_swp *swp, * @brief Execute a QBMan management command. */ static int -dpaa2_swp_exec_mgmt_command(struct dpaa2_swp *swp, struct dpaa2_swp_cmd *cmd, +dpaa2_swp_exec_mgmt(struct dpaa2_swp *swp, struct dpaa2_swp_cmd *cmd, struct dpaa2_swp_rsp *rsp, uint8_t cmdid) { #if (defined(_KERNEL) && defined(INVARIANTS)) @@ -1075,8 +1120,8 @@ dpaa2_swp_exec_mgmt_command(struct dpaa2_swp *swp, struct dpaa2_swp_cmd *cmd, * Send a command to QBMan using Management Command register and wait * for response from the Management Response registers. */ - dpaa2_swp_send_mgmt_command(swp, cmd, cmdid); - error = dpaa2_swp_wait_for_mgmt_response(swp, rsp); + dpaa2_swp_send_mgmt(swp, cmd, cmdid); + error = dpaa2_swp_wait_for_mgmt(swp, rsp); if (error) { DPAA2_SWP_UNLOCK(swp); return (error); @@ -1094,7 +1139,7 @@ dpaa2_swp_exec_mgmt_command(struct dpaa2_swp *swp, struct dpaa2_swp_cmd *cmd, } static int -dpaa2_swp_send_mgmt_command(struct dpaa2_swp *swp, struct dpaa2_swp_cmd *cmd, +dpaa2_swp_send_mgmt(struct dpaa2_swp *swp, struct dpaa2_swp_cmd *cmd, uint8_t cmdid) { const uint8_t *cmd_pdat8 = (const uint8_t *) cmd->params; @@ -1127,7 +1172,7 @@ dpaa2_swp_send_mgmt_command(struct dpaa2_swp *swp, struct dpaa2_swp_cmd *cmd, } static int -dpaa2_swp_wait_for_mgmt_response(struct dpaa2_swp *swp, struct dpaa2_swp_rsp *rsp) +dpaa2_swp_wait_for_mgmt(struct dpaa2_swp *swp, struct dpaa2_swp_rsp *rsp) { struct resource_map *map = swp->cfg.mem_backed ? swp->cena_map : swp->cinh_map; diff --git a/sys/dev/dpaa2/dpaa2_swp.h b/sys/dev/dpaa2/dpaa2_swp.h index 53a8b32ef185cb..232bb34715e36d 100644 --- a/sys/dev/dpaa2/dpaa2_swp.h +++ b/sys/dev/dpaa2/dpaa2_swp.h @@ -492,6 +492,8 @@ int dpaa2_swp_query_bp(struct dpaa2_swp *swp, uint16_t bpid, struct dpaa2_bp_conf *conf); int dpaa2_swp_release_bufs(struct dpaa2_swp *swp, uint16_t bpid, bus_addr_t *buf, uint32_t buf_num); +int dpaa2_swp_acquire_bufs(struct dpaa2_swp *swp, uint16_t bpid, + bus_addr_t *buf[], uint32_t *buf_num); int dpaa2_swp_dqrr_next_locked(struct dpaa2_swp *swp, struct dpaa2_dq *dq, uint32_t *idx); int dpaa2_swp_pull(struct dpaa2_swp *swp, uint16_t chan_id, diff --git a/sys/dev/dpaa2/dpaa2_swp_if.m b/sys/dev/dpaa2/dpaa2_swp_if.m index 09c658eb04d0a2..ad07c53ffe76e6 100644 --- a/sys/dev/dpaa2/dpaa2_swp_if.m +++ b/sys/dev/dpaa2/dpaa2_swp_if.m @@ -68,7 +68,7 @@ }; /** - * @brief Release one or more buffer pointers to a QBMan buffer pool. + * @brief Release one or more buffer pointers to the QBMan buffer pool. * * dev: DPIO device. * bpid: Buffer pool ID. @@ -82,6 +82,22 @@ uint32_t buf_num; }; +/** + * @brief Acquires one or more buffers from the QBMan buffer pool. + * + * dev: DPIO device. + * bpid: Buffer pool ID. + * buf: Array of buffer pointers to populate. + * buf_num: Number of the buffer pointers to acquire. Actual number of + * acquired buffers will be written after command execution. + */ +METHOD int acquire_bufs { + device_t dev; + uint16_t bpid; + bus_addr_t **buf; + uint32_t *buf_num; +}; + /** * @brief Query current configuration/state of the buffer pool. *