1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright © 2021-2022 Dmitry Salychev 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 /* 32 * The DPAA2 Buffer Pool (DPBP) driver. 33 * 34 * The DPBP configures a buffer pool that can be associated with DPAA2 network 35 * and accelerator interfaces. 36 */ 37 38 #include <sys/param.h> 39 #include <sys/kernel.h> 40 #include <sys/bus.h> 41 #include <sys/rman.h> 42 #include <sys/module.h> 43 #include <sys/malloc.h> 44 #include <sys/mutex.h> 45 46 #include <vm/vm.h> 47 48 #include <machine/bus.h> 49 #include <machine/resource.h> 50 51 #include <dev/pci/pcivar.h> 52 53 #include "pcib_if.h" 54 #include "pci_if.h" 55 56 #include "dpaa2_mc.h" 57 #include "dpaa2_mcp.h" 58 #include "dpaa2_swp.h" 59 #include "dpaa2_swp_if.h" 60 #include "dpaa2_cmd_if.h" 61 62 /* DPAA2 Buffer Pool resource specification. */ 63 struct resource_spec dpaa2_bp_spec[] = { 64 /* 65 * DPMCP resources. 66 * 67 * NOTE: MC command portals (MCPs) are used to send commands to, and 68 * receive responses from, the MC firmware. One portal per DPBP. 69 */ 70 #define MCP_RES_NUM (1u) 71 #define MCP_RID_OFF (0u) 72 #define MCP_RID(rid) ((rid) + MCP_RID_OFF) 73 /* --- */ 74 { DPAA2_DEV_MCP, MCP_RID(0), RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL }, 75 /* --- */ 76 RESOURCE_SPEC_END 77 }; 78 79 static int 80 dpaa2_bp_probe(device_t dev) 81 { 82 /* DPBP device will be added by the parent resource container. */ 83 device_set_desc(dev, "DPAA2 Buffer Pool"); 84 return (BUS_PROBE_DEFAULT); 85 } 86 87 static int 88 dpaa2_bp_detach(device_t dev) 89 { 90 device_t pdev = device_get_parent(dev); 91 device_t child = dev; 92 struct dpaa2_bp_softc *sc = device_get_softc(dev); 93 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); 94 struct dpaa2_devinfo *dinfo = device_get_ivars(dev); 95 struct dpaa2_cmd cmd; 96 uint16_t rc_token, bp_token; 97 int error; 98 99 DPAA2_CMD_INIT(&cmd); 100 101 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); 102 if (error) { 103 device_printf(dev, "%s: failed to open DPRC: error=%d\n", 104 __func__, error); 105 goto err_exit; 106 } 107 error = DPAA2_CMD_BP_OPEN(dev, child, &cmd, dinfo->id, &bp_token); 108 if (error) { 109 device_printf(dev, "%s: failed to open DPBP: id=%d, error=%d\n", 110 __func__, dinfo->id, error); 111 goto close_rc; 112 } 113 (void)DPAA2_CMD_BP_DISABLE(dev, child, &cmd); 114 (void)DPAA2_CMD_BP_CLOSE(dev, child, &cmd); 115 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); 116 117 dinfo->portal = NULL; 118 bus_release_resources(sc->dev, dpaa2_bp_spec, sc->res); 119 120 return (0); 121 122 close_rc: 123 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); 124 err_exit: 125 return (ENXIO); 126 } 127 128 static int 129 dpaa2_bp_attach(device_t dev) 130 { 131 device_t pdev = device_get_parent(dev); 132 device_t child = dev; 133 device_t mcp_dev; 134 struct dpaa2_bp_softc *sc = device_get_softc(dev); 135 struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); 136 struct dpaa2_devinfo *dinfo = device_get_ivars(dev); 137 struct dpaa2_devinfo *mcp_dinfo; 138 struct dpaa2_cmd cmd; 139 uint16_t rc_token, bp_token; 140 int error; 141 142 sc->dev = dev; 143 144 error = bus_alloc_resources(sc->dev, dpaa2_bp_spec, sc->res); 145 if (error) { 146 device_printf(dev, "%s: failed to allocate resources: " 147 "error=%d\n", __func__, error); 148 goto err_exit; 149 } 150 151 /* Send commands to MC via allocated portal. */ 152 mcp_dev = (device_t) rman_get_start(sc->res[MCP_RID(0)]); 153 mcp_dinfo = device_get_ivars(mcp_dev); 154 dinfo->portal = mcp_dinfo->portal; 155 156 DPAA2_CMD_INIT(&cmd); 157 158 error = DPAA2_CMD_RC_OPEN(dev, child, &cmd, rcinfo->id, &rc_token); 159 if (error) { 160 device_printf(dev, "%s: failed to open DPRC: error=%d\n", 161 __func__, error); 162 goto detach; 163 } 164 error = DPAA2_CMD_BP_OPEN(dev, child, &cmd, dinfo->id, &bp_token); 165 if (error) { 166 device_printf(dev, "%s: failed to open DPBP: id=%d, error=%d\n", 167 __func__, dinfo->id, error); 168 goto close_rc; 169 } 170 171 error = DPAA2_CMD_BP_RESET(dev, child, &cmd); 172 if (error) { 173 device_printf(dev, "%s: failed to reset DPBP: id=%d, error=%d\n", 174 __func__, dinfo->id, error); 175 goto close_bp; 176 } 177 error = DPAA2_CMD_BP_ENABLE(dev, child, &cmd); 178 if (error) { 179 device_printf(dev, "%s: failed to enable DPBP: id=%d, " 180 "error=%d\n", __func__, dinfo->id, error); 181 goto close_bp; 182 } 183 error = DPAA2_CMD_BP_GET_ATTRIBUTES(dev, child, &cmd, &sc->attr); 184 if (error) { 185 device_printf(dev, "%s: failed to get DPBP attributes: id=%d, " 186 "error=%d\n", __func__, dinfo->id, error); 187 goto close_bp; 188 } 189 190 (void)DPAA2_CMD_BP_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, bp_token)); 191 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); 192 return (0); 193 194 close_bp: 195 (void)DPAA2_CMD_BP_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, bp_token)); 196 close_rc: 197 (void)DPAA2_CMD_RC_CLOSE(dev, child, DPAA2_CMD_TK(&cmd, rc_token)); 198 detach: 199 dpaa2_bp_detach(dev); 200 err_exit: 201 return (ENXIO); 202 } 203 204 static device_method_t dpaa2_bp_methods[] = { 205 /* Device interface */ 206 DEVMETHOD(device_probe, dpaa2_bp_probe), 207 DEVMETHOD(device_attach, dpaa2_bp_attach), 208 DEVMETHOD(device_detach, dpaa2_bp_detach), 209 210 DEVMETHOD_END 211 }; 212 213 static driver_t dpaa2_bp_driver = { 214 "dpaa2_bp", 215 dpaa2_bp_methods, 216 sizeof(struct dpaa2_bp_softc), 217 }; 218 219 DRIVER_MODULE(dpaa2_bp, dpaa2_rc, dpaa2_bp_driver, 0, 0); 220