Date: Sun, 4 Sep 2016 00:58:19 +0000 (UTC) From: "Landon J. Fuller" <landonf@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r305371 - in head/sys: dev/bhnd dev/bhnd/bcma dev/bhnd/bhndb dev/bhnd/cores/chipc dev/bhnd/siba dev/bwn mips/broadcom modules/bhnd/bhndb Message-ID: <201609040058.u840wJVs030864@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: landonf Date: Sun Sep 4 00:58:19 2016 New Revision: 305371 URL: https://svnweb.freebsd.org/changeset/base/305371 Log: Migrate bhndb(4) to the new bhnd_erom API. Adds support for probing and initializing bhndb(4) bridge state using the bhnd_erom API, ensuring that full bridge configuration is available *prior* to actually attaching and enumerating the bhnd(4) child device, allowing us to safely allocate bus-level agent/device resources during bhnd(4) bus enumeration. - Add a bhnd_erom_probe() method usable by bhndb(4). This is an analogue to the existing bhnd_erom_probe_static() method, and allows the bhndb bridge to discover the best available erom parser class prior to newbus probing of its children. - Add support for supplying identification hints when probing erom devices. This is required on early EXTIF-only chipsets, where chip identification registers are not available. - Migrate bhndb over to the new bhnd_erom API, using bhnd_core_info records rather than bridged bhnd(4) device_t references to determine the bridged chipsets' capability/bridge configuration. - The bhndb parent (e.g. if_bwn) is now required to supply a hardware priority table to the bridge. The default table is currently sufficient for our supported devices. - Drop the two-pass attach approach we used for compatibility with bhndb(4) in the bhnd(4) bus drivers, and instead perform bus enumeration immediately, and allocate bridged per-child bus-level resources during that enumeration. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D7768 Modified: head/sys/dev/bhnd/bcma/bcma.c head/sys/dev/bhnd/bcma/bcma_bhndb.c head/sys/dev/bhnd/bcma/bcma_erom.c head/sys/dev/bhnd/bcma/bcma_eromvar.h head/sys/dev/bhnd/bcma/bcma_nexus.c head/sys/dev/bhnd/bcma/bcma_subr.c head/sys/dev/bhnd/bcma/bcmavar.h head/sys/dev/bhnd/bhnd.h head/sys/dev/bhnd/bhnd_bus_if.m head/sys/dev/bhnd/bhnd_erom.c head/sys/dev/bhnd/bhnd_erom.h head/sys/dev/bhnd/bhnd_erom_if.m head/sys/dev/bhnd/bhnd_match.h head/sys/dev/bhnd/bhnd_nexus.c head/sys/dev/bhnd/bhnd_subr.c head/sys/dev/bhnd/bhndb/bhnd_bhndb.c head/sys/dev/bhnd/bhndb/bhndb.c head/sys/dev/bhnd/bhndb/bhndb_bus_if.m head/sys/dev/bhnd/bhndb/bhndb_if.m head/sys/dev/bhnd/bhndb/bhndb_pci.c head/sys/dev/bhnd/bhndb/bhndb_private.h head/sys/dev/bhnd/bhndb/bhndb_subr.c head/sys/dev/bhnd/bhndb/bhndbvar.h head/sys/dev/bhnd/cores/chipc/chipcreg.h head/sys/dev/bhnd/siba/siba.c head/sys/dev/bhnd/siba/siba_bhndb.c head/sys/dev/bhnd/siba/siba_erom.c head/sys/dev/bhnd/siba/siba_nexus.c head/sys/dev/bhnd/siba/sibavar.h head/sys/dev/bwn/if_bwn_pci.c head/sys/dev/bwn/if_bwn_pcivar.h head/sys/mips/broadcom/bcm_machdep.c head/sys/modules/bhnd/bhndb/Makefile Modified: head/sys/dev/bhnd/bcma/bcma.c ============================================================================== --- head/sys/dev/bhnd/bcma/bcma.c Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bcma/bcma.c Sun Sep 4 00:58:19 2016 (r305371) @@ -48,6 +48,12 @@ __FBSDID("$FreeBSD$"); /* RID used when allocating EROM table */ #define BCMA_EROM_RID 0 +static bhnd_erom_class_t * +bcma_get_erom_class(driver_t *driver) +{ + return (&bcma_erom_parser); +} + int bcma_probe(device_t dev) { @@ -55,70 +61,25 @@ bcma_probe(device_t dev) return (BUS_PROBE_DEFAULT); } +/** + * Default bcma(4) bus driver implementation of DEVICE_ATTACH(). + * + * This implementation initializes internal bcma(4) state and performs + * bus enumeration, and must be called by subclassing drivers in + * DEVICE_ATTACH() before any other bus methods. + */ int bcma_attach(device_t dev) { - struct bcma_devinfo *dinfo; - device_t *devs, child; - int ndevs; - int error; + int error; - - if ((error = device_get_children(dev, &devs, &ndevs))) + /* Enumerate children */ + if ((error = bcma_add_children(dev))) { + device_delete_children(dev); return (error); - - /* - * Map our children's agent register block. - */ - for (int i = 0; i < ndevs; i++) { - bhnd_addr_t addr; - bhnd_size_t size; - rman_res_t r_start, r_count, r_end; - - child = devs[i]; - dinfo = device_get_ivars(child); - - KASSERT(!device_is_suspended(child), - ("bcma(4) stateful suspend handling requires that devices " - "not be suspended before bcma_attach()")); - - /* Verify that the agent register block exists and is - * mappable */ - if (bhnd_get_port_rid(child, BHND_PORT_AGENT, 0, 0) == -1) - continue; - - /* Fetch the address of the agent register block */ - error = bhnd_get_region_addr(child, BHND_PORT_AGENT, 0, 0, - &addr, &size); - if (error) { - device_printf(dev, "failed fetching agent register " - "block address for core %d\n", i); - goto cleanup; - } - - /* Allocate the resource */ - r_start = addr; - r_count = size; - r_end = r_start + r_count - 1; - - dinfo->rid_agent = i + 1; - dinfo->res_agent = BHND_BUS_ALLOC_RESOURCE(dev, dev, - SYS_RES_MEMORY, &dinfo->rid_agent, r_start, r_end, r_count, - RF_ACTIVE); - if (dinfo->res_agent == NULL) { - device_printf(dev, "failed allocating agent register " - "block for core %d\n", i); - error = ENXIO; - goto cleanup; - } } -cleanup: - free(devs, M_BHND); - if (error) - return (error); - - return (bhnd_generic_attach(dev)); + return (0); } int @@ -191,15 +152,6 @@ bcma_get_resource_list(device_t dev, dev return (&dinfo->resources); } -static device_t -bcma_find_hostb_device(device_t dev) -{ - struct bcma_softc *sc = device_get_softc(dev); - - /* This is set (or not) by the concrete bcma driver subclass. */ - return (sc->hostb_dev); -} - static int bcma_reset_core(device_t dev, device_t child, uint16_t flags) { @@ -516,8 +468,7 @@ bcma_add_children(device_t bus) corecfg = NULL; /* Allocate our EROM parser */ - erom = bhnd_erom_alloc(&bcma_erom_parser, bus, BCMA_EROM_RID, - cid->enum_addr); + erom = bhnd_erom_alloc(&bcma_erom_parser, cid, bus, BCMA_EROM_RID); if (erom == NULL) return (ENODEV); @@ -528,17 +479,21 @@ bcma_add_children(device_t bus) child = BUS_ADD_CHILD(bus, 0, NULL, -1); if (child == NULL) { error = ENXIO; - goto failed; + goto cleanup; } /* Initialize device ivars */ dinfo = device_get_ivars(child); if ((error = bcma_init_dinfo(bus, dinfo, corecfg))) - goto failed; + goto cleanup; /* The dinfo instance now owns the corecfg value */ corecfg = NULL; + /* Allocate device's agent registers, if any */ + if ((error = bcma_dinfo_alloc_agent(bus, child, dinfo))) + goto cleanup; + /* If pins are floating or the hardware is otherwise * unpopulated, the device shouldn't be used. */ if (bhnd_is_hw_disabled(child)) @@ -548,16 +503,19 @@ bcma_add_children(device_t bus) BHND_BUS_CHILD_ADDED(bus, child); } - /* Hit EOF parsing cores? */ + /* EOF while parsing cores is expected */ if (error == ENOENT) error = 0; -failed: +cleanup: bhnd_erom_free(erom); if (corecfg != NULL) bcma_free_corecfg(corecfg); + if (error) + device_delete_children(bus); + return (error); } @@ -574,7 +532,7 @@ static device_method_t bcma_methods[] = DEVMETHOD(bus_get_resource_list, bcma_get_resource_list), /* BHND interface */ - DEVMETHOD(bhnd_bus_find_hostb_device, bcma_find_hostb_device), + DEVMETHOD(bhnd_bus_get_erom_class, bcma_get_erom_class), DEVMETHOD(bhnd_bus_alloc_devinfo, bcma_alloc_bhnd_dinfo), DEVMETHOD(bhnd_bus_free_devinfo, bcma_free_bhnd_dinfo), DEVMETHOD(bhnd_bus_reset_core, bcma_reset_core), Modified: head/sys/dev/bhnd/bcma/bcma_bhndb.c ============================================================================== --- head/sys/dev/bhnd/bcma/bcma_bhndb.c Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bcma/bcma_bhndb.c Sun Sep 4 00:58:19 2016 (r305371) @@ -72,26 +72,21 @@ bcma_bhndb_probe(device_t dev) static int bcma_bhndb_attach(device_t dev) { - struct bcma_softc *sc; - int error; + int error; - sc = device_get_softc(dev); + /* Perform initial attach and enumerate our children. */ + if ((error = bcma_attach(dev))) + goto failed; + + /* Delegate remainder to standard bhnd method implementation */ + if ((error = bhnd_generic_attach(dev))) + goto failed; - /* Enumerate our children. */ - if ((error = bcma_add_children(dev))) - return (error); - - /* Initialize full bridge configuration */ - error = BHNDB_INIT_FULL_CONFIG(device_get_parent(dev), dev, - bhndb_bcma_priority_table); - if (error) - return (error); - - /* Ask our parent bridge to find the corresponding bridge core */ - sc->hostb_dev = BHNDB_FIND_HOSTB_DEVICE(device_get_parent(dev), dev); + return (0); - /* Call our superclass' implementation */ - return (bcma_attach(dev)); +failed: + device_delete_children(dev); + return (error); } static int Modified: head/sys/dev/bhnd/bcma/bcma_erom.c ============================================================================== --- head/sys/dev/bhnd/bcma/bcma_erom.c Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bcma/bcma_erom.c Sun Sep 4 00:58:19 2016 (r305371) @@ -58,7 +58,13 @@ __FBSDID("$FreeBSD$"); * marker. */ +struct bcma_erom_io; + static const char *bcma_erom_entry_type_name (uint8_t entry); + +static uint32_t bcma_eio_read4(struct bcma_erom_io *io, + bus_size_t offset); + static int bcma_erom_read32(struct bcma_erom *erom, uint32_t *entry); static int bcma_erom_skip32(struct bcma_erom *erom); @@ -72,8 +78,10 @@ static int bcma_erom_seek_next(struct static int bcma_erom_region_to_port_type(struct bcma_erom *erom, uint8_t region_type, bhnd_port_type *port_type); + static int bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry); + static bus_size_t bcma_erom_tell(struct bcma_erom *erom); static void bcma_erom_seek(struct bcma_erom *erom, bus_size_t offset); @@ -96,9 +104,33 @@ static void bcma_erom_to_core_info(con u_int core_idx, int core_unit, struct bhnd_core_info *info); +/** + * BCMA EROM generic I/O context + */ +struct bcma_erom_io { + struct bhnd_resource *res; /**< memory resource, or NULL if initialized + with bus space tag and handle */ + int rid; /**< memory resource id, or -1 */ + + bus_space_tag_t bst; /**< bus space tag, if any */ + bus_space_handle_t bsh; /**< bus space handle, if any */ + + bus_size_t start; /**< base read offset */ +}; + +/** + * BCMA EROM per-instance state. + */ +struct bcma_erom { + struct bhnd_erom obj; + device_t dev; /**< parent device, or NULL if none. */ + struct bcma_erom_io io; /**< I/O context */ + bus_size_t offset; /**< current read offset */ +}; + #define EROM_LOG(erom, fmt, ...) do { \ if (erom->dev != NULL) { \ - device_printf(erom->dev, "erom[0x%llx]: " fmt, \ + device_printf(erom->dev, "erom[0x%llx]: " fmt, \ (unsigned long long) (erom->offset), ##__VA_ARGS__);\ } else { \ printf("erom[0x%llx]: " fmt, \ @@ -106,7 +138,6 @@ static void bcma_erom_to_core_info(con } \ } while(0) - /** Return the type name for an EROM entry */ static const char * bcma_erom_entry_type_name (uint8_t entry) @@ -123,47 +154,112 @@ bcma_erom_entry_type_name (uint8_t entry } } + +/** + * Read a 32-bit value from an EROM I/O context. + * + * @param io EROM I/O context. + * @param offset Read offset. + */ +static uint32_t +bcma_eio_read4(struct bcma_erom_io *io, bus_size_t offset) +{ + bus_size_t read_off; + + read_off = io->start + offset; + if (io->res != NULL) + return (bhnd_bus_read_4(io->res, read_off)); + else + return (bus_space_read_4(io->bst, io->bsh, read_off)); +} + +/* Initialize bcma_erom resource I/O context */ +static void +bcma_eio_init(struct bcma_erom_io *io, struct bhnd_resource *res, int rid, + bus_size_t offset) +{ + io->res = res; + io->rid = rid; + io->start = offset; +} + +/* Initialize bcma_erom bus space I/O context */ +static void +bcma_eio_init_static(struct bcma_erom_io *io, bus_space_tag_t bst, + bus_space_handle_t bsh, bus_size_t offset) +{ + io->res = NULL; + io->rid = -1; + io->bst = bst; + io->bsh = bsh; + io->start = offset; +} + +/* BCMA implementation of BHND_EROM_INIT() */ static int -bcma_erom_init(bhnd_erom_t *erom, device_t parent, int rid, bus_addr_t enum_addr) +bcma_erom_init(bhnd_erom_t *erom, const struct bhnd_chipid *cid, + device_t parent, int rid) { - struct bcma_erom *sc = (struct bcma_erom *)erom; + struct bcma_erom *sc; + struct bhnd_resource *res; + sc = (struct bcma_erom *)erom; sc->dev = parent; + sc->offset = 0; + + res = bhnd_alloc_resource(parent, SYS_RES_MEMORY, &rid, cid->enum_addr, + cid->enum_addr + BCMA_EROM_TABLE_SIZE - 1, BCMA_EROM_TABLE_SIZE, + RF_ACTIVE|RF_SHAREABLE); - sc->rid = rid; - sc->res = bhnd_alloc_resource(parent, SYS_RES_MEMORY, &sc->rid, - enum_addr, enum_addr + BCMA_EROM_TABLE_SIZE - 1, - BCMA_EROM_TABLE_SIZE, RF_ACTIVE|RF_SHAREABLE); - if (sc->res == NULL) + if (res == NULL) return (ENOMEM); - - sc->start = BCMA_EROM_TABLE_START; + + bcma_eio_init(&sc->io, res, rid, BCMA_EROM_TABLE_START); + + return (0); +} + +/* BCMA implementation of BHND_EROM_INIT_STATIC() */ +static int +bcma_erom_init_static(bhnd_erom_t *erom, const struct bhnd_chipid *cid, + bus_space_tag_t bst, bus_space_handle_t bsh) +{ + struct bcma_erom *sc; + + sc = (struct bcma_erom *)erom; + sc->dev = NULL; sc->offset = 0; + bcma_eio_init_static(&sc->io, bst, bsh, BCMA_EROM_TABLE_START); + return (0); } +/* Common implementation of BHND_EROM_PROBE/BHND_EROM_PROBE_STATIC */ static int -bcma_erom_probe_static(bhnd_erom_class_t *cls, bus_space_tag_t bst, - bus_space_handle_t bsh, bus_addr_t paddr, struct bhnd_chipid *cid) +bcma_erom_probe_common(struct bcma_erom_io *io, const struct bhnd_chipid *hint, + struct bhnd_chipid *cid) { - uint32_t idreg, eaddr; - uint8_t chip_type; + uint32_t idreg, eromptr; - idreg = bus_space_read_4(bst, bsh, CHIPC_ID); - chip_type = CHIPC_GET_BITS(idreg, CHIPC_ID_BUS); + /* Hints aren't supported; all BCMA devices have a ChipCommon + * core */ + if (hint != NULL) + return (EINVAL); - /* Fetch EROM physical address */ - if (!BHND_CHIPTYPE_HAS_EROM(chip_type)) + /* Confirm CHIPC_EROMPTR availability */ + idreg = bcma_eio_read4(io, CHIPC_ID); + if (!BHND_CHIPTYPE_HAS_EROM(CHIPC_GET_BITS(idreg, CHIPC_ID_BUS))) return (ENXIO); - eaddr = bus_space_read_4(bst, bsh, CHIPC_EROMPTR); + /* Fetch EROM address */ + eromptr = bcma_eio_read4(io, CHIPC_EROMPTR); /* Parse chip identifier */ - *cid = bhnd_parse_chipid(idreg, eaddr); + *cid = bhnd_parse_chipid(idreg, eromptr); /* Verify chip type */ - switch (chip_type) { + switch (cid->chip_type) { case BHND_CHIPTYPE_BCMA: return (BUS_PROBE_DEFAULT); @@ -173,37 +269,44 @@ bcma_erom_probe_static(bhnd_erom_class_t default: return (ENXIO); - } + } } static int -bcma_erom_init_static(bhnd_erom_t *erom, bus_space_tag_t bst, - bus_space_handle_t bsh) +bcma_erom_probe(bhnd_erom_class_t *cls, struct bhnd_resource *res, + bus_size_t offset, const struct bhnd_chipid *hint, struct bhnd_chipid *cid) { - struct bcma_erom *sc = (struct bcma_erom *)erom; + struct bcma_erom_io io; - sc->dev = NULL; - sc->rid = -1; - sc->res = NULL; - sc->bst = bst; - sc->bsh = bsh; - sc->start = BCMA_EROM_TABLE_START; - sc->offset = 0; + bcma_eio_init(&io, res, rman_get_rid(res->res), + offset + BCMA_EROM_TABLE_START); - return (0); + return (bcma_erom_probe_common(&io, hint, cid)); } +static int +bcma_erom_probe_static(bhnd_erom_class_t *cls, bus_space_tag_t bst, + bus_space_handle_t bsh, bus_addr_t paddr, const struct bhnd_chipid *hint, + struct bhnd_chipid *cid) +{ + struct bcma_erom_io io; + + bcma_eio_init_static(&io, bst, bsh, BCMA_EROM_TABLE_START); + return (bcma_erom_probe_common(&io, hint, cid)); +} + + static void bcma_erom_fini(bhnd_erom_t *erom) { struct bcma_erom *sc = (struct bcma_erom *)erom; - if (sc->res != NULL) { - bhnd_release_resource(sc->dev, SYS_RES_MEMORY, sc->rid, - sc->res); + if (sc->io.res != NULL) { + bhnd_release_resource(sc->dev, SYS_RES_MEMORY, sc->io.rid, + sc->io.res); - sc->res = NULL; - sc->rid = -1; + sc->io.res = NULL; + sc->io.rid = -1; } } @@ -484,19 +587,12 @@ bcma_erom_seek(struct bcma_erom *erom, b static int bcma_erom_peek32(struct bcma_erom *erom, uint32_t *entry) { - bus_size_t off; - - if (erom->offset >= BCMA_EROM_TABLE_SIZE) { + if (erom->offset >= (BCMA_EROM_TABLE_SIZE - sizeof(uint32_t))) { EROM_LOG(erom, "BCMA EROM table missing terminating EOF\n"); return (EINVAL); } - - off = erom->start + erom->offset; - if (erom->res != NULL) - *entry = bhnd_bus_read_4(erom->res, off); - else - *entry = bus_space_read_4(erom->bst, erom->bsh, off); - + + *entry = bcma_eio_read4(&erom->io, erom->offset); return (0); } @@ -1259,6 +1355,7 @@ failed: } static kobj_method_t bcma_erom_methods[] = { + KOBJMETHOD(bhnd_erom_probe, bcma_erom_probe), KOBJMETHOD(bhnd_erom_probe_static, bcma_erom_probe_static), KOBJMETHOD(bhnd_erom_init, bcma_erom_init), KOBJMETHOD(bhnd_erom_init_static, bcma_erom_init_static), Modified: head/sys/dev/bhnd/bcma/bcma_eromvar.h ============================================================================== --- head/sys/dev/bhnd/bcma/bcma_eromvar.h Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bcma/bcma_eromvar.h Sun Sep 4 00:58:19 2016 (r305371) @@ -42,25 +42,6 @@ struct bcma_erom; int bcma_erom_next_corecfg(struct bcma_erom *sc, struct bcma_corecfg **result); -/** - * BCMA EROM per-instance state. - */ -struct bcma_erom { - struct bhnd_erom obj; - device_t dev; /**< EROM parent device, or NULL - if none. */ - struct bhnd_resource *res; /**< EROM table resource, or - NULL if initialized with - bus space tag and handle */ - int rid; /**< EROM table rid, or -1 */ - - bus_space_tag_t bst; /**< EROM table bus space */ - bus_space_handle_t bsh; /**< EROM table bus handle */ - - bus_size_t start; /**< EROM table offset */ - bus_size_t offset; /**< current read offset */ -}; - /** EROM core descriptor. */ struct bcma_erom_core { uint16_t vendor; /**< core's designer */ Modified: head/sys/dev/bhnd/bcma/bcma_nexus.c ============================================================================== --- head/sys/dev/bhnd/bcma/bcma_nexus.c Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bcma/bcma_nexus.c Sun Sep 4 00:58:19 2016 (r305371) @@ -93,10 +93,19 @@ bcma_nexus_attach(device_t dev) { int error; - if ((error = bcma_add_children(dev))) - return (error); - - return (bcma_attach(dev)); + /* Perform initial attach and enumerate our children. */ + if ((error = bcma_attach(dev))) + goto failed; + + /* Delegate remainder to standard bhnd method implementation */ + if ((error = bhnd_generic_attach(dev))) + goto failed; + + return (0); + +failed: + device_delete_children(dev); + return (error); } static const struct bhnd_chipid * Modified: head/sys/dev/bhnd/bcma/bcma_subr.c ============================================================================== --- head/sys/dev/bhnd/bcma/bcma_subr.c Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bcma/bcma_subr.c Sun Sep 4 00:58:19 2016 (r305371) @@ -43,6 +43,10 @@ __FBSDID("$FreeBSD$"); #include "bcmavar.h" +/* Return the resource ID for a device's agent register allocation */ +#define BCMA_AGENT_RID(_dinfo) \ + (BCMA_AGENT_RID_BASE + BCMA_DINFO_COREIDX(_dinfo)) + /** * Allocate and initialize new core config structure. * @@ -244,6 +248,63 @@ bcma_init_dinfo(device_t bus, struct bcm return (0); } + +/** + * Allocate the per-core agent register block for a device info structure + * previous initialized via bcma_init_dinfo(). + * + * If an agent0.0 region is not defined on @p dinfo, the device info + * agent resource is set to NULL and 0 is returned. + * + * @param bus The requesting bus device. + * @param child The bcma child device. + * @param dinfo The device info associated with @p child + * + * @retval 0 success + * @retval non-zero resource allocation failed. + */ +int +bcma_dinfo_alloc_agent(device_t bus, device_t child, struct bcma_devinfo *dinfo) +{ + bhnd_addr_t addr; + bhnd_size_t size; + rman_res_t r_start, r_count, r_end; + int error; + + KASSERT(dinfo->res_agent == NULL, ("double allocation of agent")); + + /* Verify that the agent register block exists and is + * mappable */ + if (bhnd_get_port_rid(child, BHND_PORT_AGENT, 0, 0) == -1) + return (0); /* nothing to do */ + + /* Fetch the address of the agent register block */ + error = bhnd_get_region_addr(child, BHND_PORT_AGENT, 0, 0, + &addr, &size); + if (error) { + device_printf(bus, "failed fetching agent register block " + "address for core %u\n", BCMA_DINFO_COREIDX(dinfo)); + return (error); + } + + /* Allocate the resource */ + r_start = addr; + r_count = size; + r_end = r_start + r_count - 1; + + dinfo->rid_agent = BCMA_AGENT_RID(dinfo); + dinfo->res_agent = BHND_BUS_ALLOC_RESOURCE(bus, bus, SYS_RES_MEMORY, + &dinfo->rid_agent, r_start, r_end, r_count, RF_ACTIVE); + if (dinfo->res_agent == NULL) { + device_printf(bus, "failed allocating agent register block for " + "core %u\n", BCMA_DINFO_COREIDX(dinfo)); + return (ENXIO); + } + + return (0); +} + + /** * Deallocate the given device info structure and any associated resources. * Modified: head/sys/dev/bhnd/bcma/bcmavar.h ============================================================================== --- head/sys/dev/bhnd/bcma/bcmavar.h Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bcma/bcmavar.h Sun Sep 4 00:58:19 2016 (r305371) @@ -45,6 +45,18 @@ * Internal definitions shared by bcma(4) driver implementations. */ +/** Base resource ID for per-core agent register allocations */ +#define BCMA_AGENT_RID_BASE 100 + +/** + * Return the device's core index. + * + * @param _dinfo The bcma_devinfo instance to query. + */ +#define BCMA_DINFO_COREIDX(_dinfo) \ + ((_dinfo)->corecfg->core_info.core_idx) + + /** BCMA port identifier. */ typedef u_int bcma_pid_t; #define BCMA_PID_MAX UINT_MAX /**< Maximum bcma_pid_t value */ @@ -72,6 +84,8 @@ struct bcma_devinfo *bcma_alloc_dinfo(de int bcma_init_dinfo(device_t bus, struct bcma_devinfo *dinfo, struct bcma_corecfg *corecfg); +int bcma_dinfo_alloc_agent(device_t bus, device_t child, + struct bcma_devinfo *dinfo); void bcma_free_dinfo(device_t bus, struct bcma_devinfo *dinfo); @@ -147,7 +161,6 @@ struct bcma_devinfo { /** BMCA per-instance state */ struct bcma_softc { struct bhnd_softc bhnd_sc; /**< bhnd state */ - device_t hostb_dev; /**< host bridge core, or NULL */ }; #endif /* _BCMA_BCMAVAR_H_ */ Modified: head/sys/dev/bhnd/bhnd.h ============================================================================== --- head/sys/dev/bhnd/bhnd.h Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bhnd.h Sun Sep 4 00:58:19 2016 (r305371) @@ -39,6 +39,7 @@ #include "bhnd_ids.h" #include "bhnd_types.h" +#include "bhnd_erom_types.h" #include "bhnd_debug.h" #include "bhnd_bus_if.h" #include "bhnd_match.h" @@ -188,6 +189,12 @@ struct bhnd_resource { * is MMIO accessible. */ }; +/** Wrap the active resource @p _r in a bhnd_resource structure */ +#define BHND_DIRECT_RESOURCE(_r) ((struct bhnd_resource) { \ + .res = (_r), \ + .direct = true, \ +}) + /** * Device quirk table descriptor. */ @@ -278,6 +285,13 @@ const struct bhnd_core_info *bhnd_find_c const struct bhnd_core_info *cores, u_int num_cores, bhnd_devclass_t class); +struct bhnd_core_match bhnd_core_get_match_desc( + const struct bhnd_core_info *core); + +bool bhnd_cores_equal( + const struct bhnd_core_info *lhs, + const struct bhnd_core_info *rhs); + bool bhnd_core_matches( const struct bhnd_core_info *core, const struct bhnd_core_match *desc); @@ -389,7 +403,16 @@ int bhnd_bus_generic_deactivate_reso bhnd_attach_type bhnd_bus_generic_get_attach_type(device_t dev, device_t child); - +/** + * Return the bhnd(4) bus driver's device enumeration parser class + * + * @param driver A bhnd bus driver instance. + */ +static inline bhnd_erom_class_t * +bhnd_driver_get_erom_class(driver_t *driver) +{ + return (BHND_BUS_GET_EROM_CLASS(driver)); +} /** * Return the active host bridge core for the bhnd bus, if any, or NULL if Modified: head/sys/dev/bhnd/bhnd_bus_if.m ============================================================================== --- head/sys/dev/bhnd/bhnd_bus_if.m Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bhnd_bus_if.m Sun Sep 4 00:58:19 2016 (r305371) @@ -29,6 +29,7 @@ #include <sys/rman.h> #include <dev/bhnd/bhnd_types.h> +#include <dev/bhnd/bhnd_erom_types.h> INTERFACE bhnd_bus; @@ -49,7 +50,13 @@ CODE { #include <sys/systm.h> #include <dev/bhnd/bhndvar.h> - + + static bhnd_erom_class_t * + bhnd_bus_null_get_erom_class(driver_t *driver) + { + return (NULL); + } + static struct bhnd_chipid * bhnd_bus_null_get_chipid(device_t dev, device_t child) { @@ -152,7 +159,7 @@ CODE { static device_t bhnd_bus_null_find_hostb_device(device_t dev) { - panic("bhnd_bus_find_hostb_device unimplemented"); + return (NULL); } static bool @@ -199,6 +206,15 @@ CODE { } /** + * Return the bhnd(4) bus driver's device enumeration parser class. + * + * @param driver The bhnd bus driver instance. + */ +STATICMETHOD bhnd_erom_class_t * get_erom_class { + driver_t *driver; +} DEFAULT bhnd_bus_null_get_erom_class; + +/** * Return the active host bridge core for the bhnd bus, if any. * * @param dev The bhnd bus device. Modified: head/sys/dev/bhnd/bhnd_erom.c ============================================================================== --- head/sys/dev/bhnd/bhnd_erom.c Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bhnd_erom.c Sun Sep 4 00:58:19 2016 (r305371) @@ -45,15 +45,15 @@ __FBSDID("$FreeBSD$"); * be allocated. * @param rid The resource ID to be used when allocating EROM * resources. - * @param enum_addr The base address of the device enumeration table. + * @param cid The device's chip identifier. * * @retval non-NULL success * @retval NULL if an error occured allocating or initializing the * EROM parser. */ bhnd_erom_t * -bhnd_erom_alloc(bhnd_erom_class_t *cls, device_t parent, int rid, - bus_addr_t enum_addr) +bhnd_erom_alloc(bhnd_erom_class_t *cls, const struct bhnd_chipid *cid, + device_t parent, int rid) { bhnd_erom_t *erom; int error; @@ -61,9 +61,9 @@ bhnd_erom_alloc(bhnd_erom_class_t *cls, erom = (bhnd_erom_t *)kobj_create((kobj_class_t)cls, M_BHND, M_WAITOK|M_ZERO); - if ((error = BHND_EROM_INIT(erom, parent, rid, enum_addr))) { + if ((error = BHND_EROM_INIT(erom, cid, parent, rid))) { printf("error initializing %s parser at %#jx with " - "rid %d: %d\n", cls->name, (uintmax_t)enum_addr, rid, + "rid %d: %d\n", cls->name, (uintmax_t)cid->enum_addr, rid, error); kobj_delete((kobj_t)erom, M_BHND); @@ -86,6 +86,7 @@ bhnd_erom_alloc(bhnd_erom_class_t *cls, * @param esize The total available number of bytes allocated for * @p erom. If this is less than is required by @p cls, * ENOMEM will be returned. + * @param cid The device's chip identifier. * @param bst Bus space tag. * @param bsh Bus space handle mapping the device enumeration * space. @@ -97,7 +98,7 @@ bhnd_erom_alloc(bhnd_erom_class_t *cls, */ int bhnd_erom_init_static(bhnd_erom_class_t *cls, bhnd_erom_t *erom, size_t esize, - bus_space_tag_t bst, bus_space_handle_t bsh) + const struct bhnd_chipid *cid, bus_space_tag_t bst, bus_space_handle_t bsh) { kobj_class_t kcls; @@ -109,7 +110,7 @@ bhnd_erom_init_static(bhnd_erom_class_t /* Perform instance initialization */ kobj_init_static((kobj_t)erom, kcls); - return (BHND_EROM_INIT_STATIC(erom, bst, bsh)); + return (BHND_EROM_INIT_STATIC(erom, cid, bst, bsh)); } /** Modified: head/sys/dev/bhnd/bhnd_erom.h ============================================================================== --- head/sys/dev/bhnd/bhnd_erom.h Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bhnd_erom.h Sun Sep 4 00:58:19 2016 (r305371) @@ -42,11 +42,12 @@ #include "bhnd_erom_if.h" bhnd_erom_t *bhnd_erom_alloc(bhnd_erom_class_t *cls, - device_t parent, int rid, - bus_addr_t enum_addr); + const struct bhnd_chipid *cid, + device_t parent, int rid); int bhnd_erom_init_static(bhnd_erom_class_t *cls, bhnd_erom_t *erom, size_t esize, + const struct bhnd_chipid *cid, bus_space_tag_t bst, bus_space_handle_t bsh); @@ -94,15 +95,48 @@ SET_DECLARE(bhnd_erom_class_set, bhnd_er /** * Probe to see if this device enumeration class supports the bhnd bus + * mapped by the given resource, returning a standard newbus device probe + * result (see BUS_PROBE_*) and the probed chip identification. + * + * @param cls The erom class to probe. + * @param res A resource mapping the first bus core (EXTIF or + * ChipCommon) + * @param offset Offset to the first bus core within @p res. + * @param hint Identification hint used to identify the device. If + * chipset supports standard chip identification registers + * within the first core, this parameter should be NULL. + * @param[out] cid On success, the probed chip identifier. + * + * @retval 0 if this is the only possible device enumeration + * parser for the probed bus. + * @retval negative if the probe succeeds, a negative value should be + * returned; the parser returning the highest negative + * value will be selected to handle device enumeration. + * @retval ENXIO If the bhnd bus type is not handled by this parser. + * @retval positive if an error occurs during probing, a regular unix error + * code should be returned. + */ +static inline int +bhnd_erom_probe(bhnd_erom_class_t *cls, struct bhnd_resource *res, + bus_size_t offset, const struct bhnd_chipid *hint, struct bhnd_chipid *cid) +{ + return (BHND_EROM_PROBE(cls, res, offset, hint, cid)); +} + +/** + * Probe to see if this device enumeration class supports the bhnd bus * mapped at the given bus space tag and handle, returning a standard * newbus device probe result (see BUS_PROBE_*) and the probed * chip identification. * - * @param cls The parser class to be probed. + * @param cls The erom class to probe. * @param bst Bus space tag. * @param bsh Bus space handle mapping the EXTIF or ChipCommon core. * @param paddr The physical address of the core mapped by @p bst and * @p bsh. + * @param hint Identification hint used to identify the device. If + * chipset supports standard chip identification registers + * within the first core, this parameter should be NULL. * @param[out] cid On success, the probed chip identifier. * * @retval 0 if this is the only possible device enumeration @@ -116,9 +150,10 @@ SET_DECLARE(bhnd_erom_class_set, bhnd_er */ static inline int bhnd_erom_probe_static(bhnd_erom_class_t *cls, bus_space_tag_t bst, - bus_space_handle_t bsh, bus_addr_t paddr, struct bhnd_chipid *cid) + bus_space_handle_t bsh, bus_addr_t paddr, const struct bhnd_chipid *hint, + struct bhnd_chipid *cid) { - return (BHND_EROM_PROBE_STATIC(cls, bst, bsh, paddr, cid)); + return (BHND_EROM_PROBE_STATIC(cls, bst, bsh, paddr, hint, cid)); } /** Modified: head/sys/dev/bhnd/bhnd_erom_if.m ============================================================================== --- head/sys/dev/bhnd/bhnd_erom_if.m Sun Sep 4 00:35:55 2016 (r305370) +++ head/sys/dev/bhnd/bhnd_erom_if.m Sun Sep 4 00:58:19 2016 (r305371) @@ -45,15 +45,48 @@ INTERFACE bhnd_erom; /** * Probe to see if this device enumeration class supports the bhnd bus + * mapped by the given resource, returning a standard newbus device probe + * result (see BUS_PROBE_*) and the probed chip identification. + * + * @param cls The erom class to probe. + * @param res A resource mapping the first bus core. + * @param offset Offset to the first bus core within @p res. + * @param hint Hint used to identify the device. If chipset supports + * standard chip identification registers within the first + * core, this parameter should be NULL. + * @param[out] cid On success, the probed chip identifier. + * + * @retval 0 if this is the only possible device enumeration + * parser for the probed bus. + * @retval negative if the probe succeeds, a negative value should be + * returned; the parser returning the highest negative + * value will be selected to handle device enumeration. + * @retval ENXIO If the bhnd bus type is not handled by this parser. + * @retval positive if an error occurs during probing, a regular unix error + * code should be returned. + */ +STATICMETHOD int probe { + bhnd_erom_class_t *cls; + struct bhnd_resource *res; + bus_size_t offset; + const struct bhnd_chipid *hint; + struct bhnd_chipid *cid; +}; + +/** + * Probe to see if this device enumeration class supports the bhnd bus * mapped at the given bus space tag and handle, returning a standard * newbus device probe result (see BUS_PROBE_*) and the probed * chip identification. * - * @param cls The erom parse class to probe. + * @param cls The erom class to probe. * @param bst Bus space tag. - * @param bsh Bus space handle mapping the EXTIF or ChipCommon core. + * @param bsh Bus space handle mapping the first bus core. * @param paddr The physical address of the core mapped by @p bst and * @p bsh. + * @param hint Hint used to identify the device. If chipset supports + * standard chip identification registers within the first + * core, this parameter should be NULL. * @param[out] cid On success, the probed chip identifier. * * @retval 0 if this is the only possible device enumeration @@ -66,51 +99,54 @@ INTERFACE bhnd_erom; * code should be returned. */ STATICMETHOD int probe_static { - bhnd_erom_class_t *cls; - bus_space_tag_t bst; - bus_space_handle_t bsh; - bus_addr_t paddr; - struct bhnd_chipid *cid; + bhnd_erom_class_t *cls; + bus_space_tag_t bst; + bus_space_handle_t bsh; + bus_addr_t paddr; + const struct bhnd_chipid *hint; + struct bhnd_chipid *cid; }; /** *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201609040058.u840wJVs030864>