Lines Matching +full:sc +full:- +full:resource

1 /*-
2 * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
39 * a BHND-compatible bus (e.g. bcma or siba).
51 #include <machine/resource.h>
79 static bool bhndb_hw_matches(struct bhndb_softc *sc,
83 static int bhndb_init_region_cfg(struct bhndb_softc *sc,
89 static int bhndb_find_hwspec(struct bhndb_softc *sc,
93 bhndb_addrspace bhndb_get_addrspace(struct bhndb_softc *sc,
96 static struct rman *bhndb_get_rman(struct bhndb_softc *sc,
99 static int bhndb_init_child_resource(struct resource *r,
100 struct resource *parent,
105 struct bhndb_softc *sc,
107 device_t child, struct resource *r);
110 struct bhndb_softc *sc, device_t child,
111 struct resource *r, bool *indirect);
113 static inline struct bhndb_dw_alloc *bhndb_io_resource(struct bhndb_softc *sc,
167 struct bhndb_softc *sc; in bhndb_child_location() local
169 sc = device_get_softc(dev); in bhndb_child_location()
172 (unsigned long long) sc->chipid.enum_addr); in bhndb_child_location()
179 * @param sc BHNDB device state.
185 bhndb_hw_matches(struct bhndb_softc *sc, struct bhnd_core_info *cores, in bhndb_hw_matches() argument
188 for (u_int i = 0; i < hw->num_hw_reqs; i++) { in bhndb_hw_matches()
192 match = &hw->hw_reqs[i]; in bhndb_hw_matches()
198 if (BHNDB_IS_CORE_DISABLED(sc->dev, sc->bus_dev, core)) in bhndb_hw_matches()
219 * @param sc The bhndb device state.
220 * @param br The resource state to be configured.
225 * priorities of per-core port resources.
228 bhndb_init_region_cfg(struct bhndb_softc *sc, bhnd_erom_t *erom, in bhndb_init_region_cfg() argument
255 for (regw = br->cfg->register_windows; in bhndb_init_region_cfg()
256 regw->win_type != BHNDB_REGWIN_T_INVALID; regw++) in bhndb_init_region_cfg()
262 if (regw->win_type != BHNDB_REGWIN_T_CORE) in bhndb_init_region_cfg()
265 /* Skip non-matching cores. */ in bhndb_init_region_cfg()
271 regw->d.core.port_type, in bhndb_init_region_cfg()
272 regw->d.core.port, in bhndb_init_region_cfg()
273 regw->d.core.region, in bhndb_init_region_cfg()
278 /* Skip non-applicable register windows */ in bhndb_init_region_cfg()
288 if (regw->d.core.offset > size) { in bhndb_init_region_cfg()
289 device_printf(sc->dev, "invalid register " in bhndb_init_region_cfg()
291 regw->d.core.offset, addr, size); in bhndb_init_region_cfg()
295 addr += regw->d.core.offset; in bhndb_init_region_cfg()
306 * within the region to a too-small window. in bhndb_init_region_cfg()
308 size = regw->win_size; in bhndb_init_region_cfg()
313 regw->d.core.port_type, regw->d.core.port, in bhndb_init_region_cfg()
314 regw->d.core.region); in bhndb_init_region_cfg()
316 alloc_flags = pp->alloc_flags; in bhndb_init_region_cfg()
350 if (BHNDB_IS_CORE_DISABLED(sc->dev, sc->bus_dev, core)) in bhndb_init_region_cfg()
359 if (hp->priority == BHNDB_PRIORITY_NONE) in bhndb_init_region_cfg()
364 for (u_int i = 0; i < hp->num_ports; i++) { in bhndb_init_region_cfg()
367 pp = &hp->ports[i]; in bhndb_init_region_cfg()
371 pp->type, pp->port, pp->region, in bhndb_init_region_cfg()
387 pp->priority, pp->alloc_flags, NULL); in bhndb_init_region_cfg()
392 switch (pp->priority) { in bhndb_init_region_cfg()
411 if (prio_total <= br->dwa_count) { in bhndb_init_region_cfg()
413 br->min_prio = BHNDB_PRIORITY_LOW; in bhndb_init_region_cfg()
415 } else if (prio_default + prio_high <= br->dwa_count) { in bhndb_init_region_cfg()
417 br->min_prio = BHNDB_PRIORITY_DEFAULT; in bhndb_init_region_cfg()
421 br->min_prio = BHNDB_PRIORITY_HIGH; in bhndb_init_region_cfg()
430 prio_min = br->min_prio; in bhndb_init_region_cfg()
431 device_printf(sc->dev, "min_prio: %d\n", prio_min); in bhndb_init_region_cfg()
433 STAILQ_FOREACH(region, &br->bus_regions, link) { in bhndb_init_region_cfg()
434 prio = region->priority; in bhndb_init_region_cfg()
435 flags = region->alloc_flags; in bhndb_init_region_cfg()
438 type_msg = region->static_regwin ? "static" : "dynamic"; in bhndb_init_region_cfg()
440 device_printf(sc->dev, "region 0x%llx+0x%llx priority " in bhndb_init_region_cfg()
442 (unsigned long long) region->addr, in bhndb_init_region_cfg()
443 (unsigned long long) region->size, in bhndb_init_region_cfg()
444 region->priority, in bhndb_init_region_cfg()
460 * @param sc The bhndb device state.
467 * @retval non-zero if an error occurs fetching device info for comparison.
470 bhndb_find_hwspec(struct bhndb_softc *sc, struct bhnd_core_info *cores, in bhndb_find_hwspec() argument
476 hw_table = BHNDB_BUS_GET_HARDWARE_TABLE(sc->parent_dev, sc->dev); in bhndb_find_hwspec()
477 for (next = hw_table; next->hw_reqs != NULL; next++) { in bhndb_find_hwspec()
478 if (!bhndb_hw_matches(sc, cores, ncores, next)) in bhndb_find_hwspec()
514 struct bhndb_softc *sc; in bhndb_attach() local
522 sc = device_get_softc(dev); in bhndb_attach()
523 sc->dev = dev; in bhndb_attach()
524 sc->parent_dev = device_get_parent(dev); in bhndb_attach()
525 sc->bridge_core = *bridge_core; in bhndb_attach()
526 sc->chipid = *cid; in bhndb_attach()
528 if ((error = bhnd_service_registry_init(&sc->services))) in bhndb_attach()
531 BHNDB_LOCK_INIT(sc); in bhndb_attach()
536 if ((error = bhndb_find_hwspec(sc, cores, ncores, &hw))) { in bhndb_attach()
537 device_printf(sc->dev, "unable to identify device, " in bhndb_attach()
538 " using generic bridge resource definitions\n"); in bhndb_attach()
540 hwcfg = BHNDB_BUS_GET_GENERIC_HWCFG(sc->parent_dev, dev); in bhndb_attach()
543 hwcfg = hw->cfg; in bhndb_attach()
547 device_printf(sc->dev, "%s resource configuration\n", hw->name); in bhndb_attach()
550 /* Allocate bridge resource state using the discovered hardware in bhndb_attach()
552 sc->bus_res = bhndb_alloc_resources(sc->dev, sc->parent_dev, hwcfg); in bhndb_attach()
553 if (sc->bus_res == NULL) { in bhndb_attach()
554 device_printf(sc->dev, "failed to allocate bridge resource " in bhndb_attach()
561 sc->bus_dev = BUS_ADD_CHILD(dev, BHND_PROBE_BUS, "bhnd", DEVICE_UNIT_ANY); in bhndb_attach()
562 if (sc->bus_dev == NULL) { in bhndb_attach()
567 dinfo = device_get_ivars(sc->bus_dev); in bhndb_attach()
568 dinfo->addrspace = BHNDB_ADDRSPACE_BRIDGED; in bhndb_attach()
572 eio = bhnd_erom_iores_new(sc->bus_dev, 0); in bhndb_attach()
579 /* Populate our resource priority configuration */ in bhndb_attach()
580 hwprio = BHNDB_BUS_GET_HARDWARE_PRIO(sc->parent_dev, sc->dev); in bhndb_attach()
581 error = bhndb_init_region_cfg(sc, erom, sc->bus_res, cores, ncores, in bhndb_attach()
584 device_printf(sc->dev, "failed to initialize resource " in bhndb_attach()
596 BHNDB_LOCK_DESTROY(sc); in bhndb_attach()
598 if (sc->bus_res != NULL) in bhndb_attach()
599 bhndb_free_resources(sc->bus_res); in bhndb_attach()
604 bhnd_service_registry_fini(&sc->services); in bhndb_attach()
618 struct bhndb_softc *sc; in bhndb_generic_detach() local
621 sc = device_get_softc(dev); in bhndb_generic_detach()
628 if ((error = bhnd_service_registry_fini(&sc->services))) in bhndb_generic_detach()
632 bhndb_free_resources(sc->bus_res); in bhndb_generic_detach()
634 BHNDB_LOCK_DESTROY(sc); in bhndb_generic_detach()
660 struct bhndb_softc *sc; in bhndb_generic_resume() local
665 sc = device_get_softc(dev); in bhndb_generic_resume()
666 bus_res = sc->bus_res; in bhndb_generic_resume()
668 /* Guarantee that all in-use dynamic register windows are mapped to in bhndb_generic_resume()
670 BHNDB_LOCK(sc); in bhndb_generic_resume()
672 for (size_t i = 0; i < bus_res->dwa_count; i++) { in bhndb_generic_resume()
673 dwa = &bus_res->dw_alloc[i]; in bhndb_generic_resume()
676 if (bhndb_dw_is_free(bus_res, dwa) && dwa->target == 0x0) in bhndb_generic_resume()
681 error = BHNDB_SET_WINDOW_ADDR(dev, dwa->win, dwa->target); in bhndb_generic_resume()
685 BHNDB_UNLOCK(sc); in bhndb_generic_resume()
702 struct resource *r) in bhndb_suspend_resource()
704 struct bhndb_softc *sc; in bhndb_suspend_resource() local
707 sc = device_get_softc(dev); in bhndb_suspend_resource()
709 /* Non-MMIO resources (e.g. IRQs) are handled solely by our parent */ in bhndb_suspend_resource()
713 BHNDB_LOCK(sc); in bhndb_suspend_resource()
714 dwa = bhndb_dw_find_resource(sc->bus_res, r); in bhndb_suspend_resource()
716 BHNDB_UNLOCK(sc); in bhndb_suspend_resource()
721 device_printf(child, "suspend resource type=%d 0x%jx+0x%jx\n", in bhndb_suspend_resource()
724 /* Release the resource's window reference */ in bhndb_suspend_resource()
725 bhndb_dw_release(sc->bus_res, dwa, r); in bhndb_suspend_resource()
726 BHNDB_UNLOCK(sc); in bhndb_suspend_resource()
734 struct resource *r) in bhndb_resume_resource()
736 struct bhndb_softc *sc; in bhndb_resume_resource() local
738 sc = device_get_softc(dev); in bhndb_resume_resource()
740 /* Non-MMIO resources (e.g. IRQs) are handled solely by our parent */ in bhndb_resume_resource()
749 device_printf(child, "resume resource type=%d 0x%jx+0x%jx\n", in bhndb_resume_resource()
752 return (bhndb_try_activate_resource(sc, rman_get_device(r), r, NULL)); in bhndb_resume_resource()
779 bhndb_get_addrspace(struct bhndb_softc *sc, device_t child) in bhndb_get_addrspace() argument
786 while (imd_dev != NULL && device_get_parent(imd_dev) != sc->dev) in bhndb_get_addrspace()
790 panic("bhndb address space request for non-child device %s\n", in bhndb_get_addrspace()
794 return (dinfo->addrspace); in bhndb_get_addrspace()
798 * Return the rman instance for a given resource @p type, if any.
800 * @param sc The bhndb device state.
802 * @param type The resource type (e.g. SYS_RES_MEMORY, SYS_RES_IRQ, ...)
805 bhndb_get_rman(struct bhndb_softc *sc, device_t child, int type) in bhndb_get_rman() argument
807 switch (bhndb_get_addrspace(sc, child)) { in bhndb_get_rman()
811 return (&sc->bus_res->ht_mem_rman); in bhndb_get_rman()
821 return (&sc->bus_res->br_mem_rman); in bhndb_get_rman()
823 return (&sc->bus_res->br_irq_rman); in bhndb_get_rman()
852 dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE; in bhndb_add_child()
853 resource_list_init(&dinfo->resources); in bhndb_add_child()
868 resource_list_free(&dinfo->resources); in bhndb_child_deleted()
881 struct bhndb_softc *sc = device_get_softc(dev); in bhndb_get_chipid() local
882 return (&sc->chipid); in bhndb_get_chipid()
892 struct bhndb_softc *sc; in bhndb_is_core_disabled() local
894 sc = device_get_softc(dev); in bhndb_is_core_disabled()
897 if (BHNDB_BUS_IS_CORE_DISABLED(sc->parent_dev, dev, core)) in bhndb_is_core_disabled()
900 /* Otherwise, we treat bridge-capable cores as unpopulated if they're in bhndb_is_core_disabled()
903 return (!bhnd_cores_equal(core, &sc->bridge_core)); in bhndb_is_core_disabled()
912 * This function uses a heuristic valid on all known PCI/PCIe/PCMCIA-bridged
918 struct bhndb_softc *sc = device_get_softc(dev); in bhndb_get_hostb_core() local
920 *core = sc->bridge_core; in bhndb_get_hostb_core()
930 struct bhndb_softc *sc = device_get_softc(dev); in bhndb_get_service_registry() local
932 return (&sc->services); in bhndb_get_service_registry()
938 static struct resource *
942 struct bhndb_softc *sc; in bhndb_alloc_resource() local
944 struct resource *rv; in bhndb_alloc_resource()
949 sc = device_get_softc(dev); in bhndb_alloc_resource()
954 /* Fetch the resource manager */ in bhndb_alloc_resource()
955 rm = bhndb_get_rman(sc, child, type); in bhndb_alloc_resource()
958 * resource type isn't handled locally. */ in bhndb_alloc_resource()
959 return (BUS_ALLOC_RESOURCE(device_get_parent(sc->parent_dev), in bhndb_alloc_resource()
965 /* Fetch the resource list entry. */ in bhndb_alloc_resource()
970 "default resource %#x type %d for child %s " in bhndb_alloc_resource()
977 if (rle->res != NULL) { in bhndb_alloc_resource()
979 "resource entry %#x type %d for child %s is busy\n", in bhndb_alloc_resource()
985 start = rle->start; in bhndb_alloc_resource()
986 end = rle->end; in bhndb_alloc_resource()
987 count = ulmax(count, rle->count); in bhndb_alloc_resource()
990 /* Validate resource addresses */ in bhndb_alloc_resource()
991 if (start > end || count > ((end - start) + 1)) in bhndb_alloc_resource()
1018 /* Update child's resource list entry */ in bhndb_alloc_resource()
1020 rle->res = rv; in bhndb_alloc_resource()
1021 rle->start = rman_get_start(rv); in bhndb_alloc_resource()
1022 rle->end = rman_get_end(rv); in bhndb_alloc_resource()
1023 rle->count = rman_get_size(rv); in bhndb_alloc_resource()
1033 bhndb_release_resource(device_t dev, device_t child, struct resource *r) in bhndb_release_resource()
1035 struct bhndb_softc *sc; in bhndb_release_resource() local
1040 sc = device_get_softc(dev); in bhndb_release_resource()
1043 /* Delegate to our parent device's bus if the requested resource type in bhndb_release_resource()
1045 if (bhndb_get_rman(sc, child, rman_get_type(r)) == NULL) { in bhndb_release_resource()
1046 return (BUS_RELEASE_RESOURCE(device_get_parent(sc->parent_dev), in bhndb_release_resource()
1057 /* Check for resource list entry */ in bhndb_release_resource()
1065 /* Clean resource list entry */ in bhndb_release_resource()
1067 rle->res = NULL; in bhndb_release_resource()
1077 struct resource *r, rman_res_t start, rman_res_t end) in bhndb_adjust_resource()
1079 struct bhndb_softc *sc; in bhndb_adjust_resource() local
1084 sc = device_get_softc(dev); in bhndb_adjust_resource()
1087 /* Delegate to our parent device's bus if the requested resource type in bhndb_adjust_resource()
1089 rm = bhndb_get_rman(sc, child, rman_get_type(r)); in bhndb_adjust_resource()
1091 return (BUS_ADJUST_RESOURCE(device_get_parent(sc->parent_dev), in bhndb_adjust_resource()
1102 BHNDB_LOCK(sc); in bhndb_adjust_resource()
1104 /* If not active, allow any range permitted by the resource manager */ in bhndb_adjust_resource()
1108 /* Otherwise, the range is limited by the bridged resource mapping */ in bhndb_adjust_resource()
1109 error = bhndb_find_resource_limits(sc->bus_res, r, &mstart, in bhndb_adjust_resource()
1124 BHNDB_UNLOCK(sc); in bhndb_adjust_resource()
1129 * Initialize child resource @p r with a virtual address, tag, and handle
1134 * @param parent The parent bus resource that fully contains the subregion.
1140 bhndb_init_child_resource(struct resource *r, in bhndb_init_child_resource()
1141 struct resource *parent, bhnd_size_t offset, bhnd_size_t size) in bhndb_init_child_resource()
1148 /* Fetch the parent resource's real bus values */ in bhndb_init_child_resource()
1153 /* Configure child resource with window-adjusted real bus values */ in bhndb_init_child_resource()
1169 * @param sc BHNDB device state.
1171 * @param child A child requesting resource activation.
1172 * @param type Resource type.
1173 * @param rid Resource identifier.
1174 * @param r Resource to be activated.
1178 * @retval non-zero if @p r could not be activated.
1181 bhndb_activate_static_region(struct bhndb_softc *sc, in bhndb_activate_static_region() argument
1182 struct bhndb_region *region, device_t child, struct resource *r) in bhndb_activate_static_region()
1184 struct resource *bridge_res; in bhndb_activate_static_region()
1190 win = region->static_regwin; in bhndb_activate_static_region()
1192 KASSERT(win != NULL && BHNDB_REGWIN_T_IS_STATIC(win->win_type), in bhndb_activate_static_region()
1193 ("can't activate non-static region")); in bhndb_activate_static_region()
1198 /* Find the corresponding bridge resource */ in bhndb_activate_static_region()
1199 bridge_res = bhndb_host_resource_for_regwin(sc->bus_res->res, win); in bhndb_activate_static_region()
1203 /* Calculate subregion offset within the parent resource */ in bhndb_activate_static_region()
1204 parent_offset = r_start - region->addr; in bhndb_activate_static_region()
1205 parent_offset += win->win_offset; in bhndb_activate_static_region()
1207 /* Configure resource with its real bus values. */ in bhndb_activate_static_region()
1223 * @param sc The bhndb driver state.
1224 * @param r The resource for which a window will be retained.
1227 bhndb_retain_dynamic_window(struct bhndb_softc *sc, struct resource *r) in bhndb_retain_dynamic_window() argument
1233 BHNDB_LOCK_ASSERT(sc, MA_OWNED); in bhndb_retain_dynamic_window()
1239 dwa = bhndb_dw_find_mapping(sc->bus_res, r_start, r_size); in bhndb_retain_dynamic_window()
1241 if (bhndb_dw_retain(sc->bus_res, dwa, r) == 0) in bhndb_retain_dynamic_window()
1248 dwa = bhndb_dw_next_free(sc->bus_res); in bhndb_retain_dynamic_window()
1254 /* Window must be large enough to map the entire resource */ in bhndb_retain_dynamic_window()
1255 if (dwa->win->win_size < rman_get_size(r)) in bhndb_retain_dynamic_window()
1259 error = bhndb_dw_set_addr(sc->dev, sc->bus_res, dwa, rman_get_start(r), in bhndb_retain_dynamic_window()
1262 device_printf(sc->dev, "dynamic window initialization " in bhndb_retain_dynamic_window()
1263 "for 0x%llx-0x%llx failed: %d\n", in bhndb_retain_dynamic_window()
1265 (unsigned long long) r_start + r_size - 1, in bhndb_retain_dynamic_window()
1271 if (bhndb_dw_retain(sc->bus_res, dwa, r)) in bhndb_retain_dynamic_window()
1278 * Activate a resource using any viable static or dynamic register window.
1280 * @param sc The bhndb driver state.
1282 * @param r The resource to be activated
1284 * the caller should instead use an indirect resource mapping.
1287 * @retval non-zero activation failed.
1290 bhndb_try_activate_resource(struct bhndb_softc *sc, device_t child, in bhndb_try_activate_resource() argument
1291 struct resource *r, bool *indirect) in bhndb_try_activate_resource()
1300 BHNDB_LOCK_ASSERT(sc, MA_NOTOWNED); in bhndb_try_activate_resource()
1316 device_printf(sc->dev, "unsupported resource type %d\n", type); in bhndb_try_activate_resource()
1327 if (bhndb_get_addrspace(sc, child) == BHNDB_ADDRSPACE_NATIVE) { in bhndb_try_activate_resource()
1328 struct resource *parent; in bhndb_try_activate_resource()
1330 /* Find the bridge resource referenced by the child */ in bhndb_try_activate_resource()
1331 parent = bhndb_host_resource_for_range(sc->bus_res->res, in bhndb_try_activate_resource()
1334 device_printf(sc->dev, "host resource not found " in bhndb_try_activate_resource()
1335 "for 0x%llx-0x%llx\n", in bhndb_try_activate_resource()
1337 (unsigned long long) r_start + r_size - 1); in bhndb_try_activate_resource()
1341 /* Initialize child resource with the real bus values */ in bhndb_try_activate_resource()
1343 r_start - rman_get_start(parent), r_size); in bhndb_try_activate_resource()
1347 /* Try to activate child resource */ in bhndb_try_activate_resource()
1354 /* Look for a bus region matching the resource's address range */ in bhndb_try_activate_resource()
1355 region = bhndb_find_resource_region(sc->bus_res, r_start, r_size); in bhndb_try_activate_resource()
1357 dw_priority = region->priority; in bhndb_try_activate_resource()
1360 if (region && region->static_regwin) { in bhndb_try_activate_resource()
1361 error = bhndb_activate_static_region(sc, region, child, r); in bhndb_try_activate_resource()
1363 device_printf(sc->dev, "static window allocation " in bhndb_try_activate_resource()
1364 "for 0x%llx-0x%llx failed\n", in bhndb_try_activate_resource()
1366 (unsigned long long) r_start + r_size - 1); in bhndb_try_activate_resource()
1370 /* A dynamic window will be required; is this resource high enough in bhndb_try_activate_resource()
1372 if (dw_priority < sc->bus_res->min_prio) { in bhndb_try_activate_resource()
1380 BHNDB_LOCK(sc); { in bhndb_try_activate_resource()
1381 dwa = bhndb_retain_dynamic_window(sc, r); in bhndb_try_activate_resource()
1382 } BHNDB_UNLOCK(sc); in bhndb_try_activate_resource()
1390 /* Configure resource with its real bus values. */ in bhndb_try_activate_resource()
1391 parent_offset = dwa->win->win_offset; in bhndb_try_activate_resource()
1392 parent_offset += r_start - dwa->target; in bhndb_try_activate_resource()
1394 error = bhndb_init_child_resource(r, dwa->parent_res, parent_offset, in bhndb_try_activate_resource()
1395 dwa->win->win_size); in bhndb_try_activate_resource()
1407 BHNDB_LOCK(sc); in bhndb_try_activate_resource()
1408 bhndb_dw_release(sc->bus_res, dwa, r); in bhndb_try_activate_resource()
1409 BHNDB_UNLOCK(sc); in bhndb_try_activate_resource()
1418 bhndb_activate_resource(device_t dev, device_t child, struct resource *r) in bhndb_activate_resource()
1420 struct bhndb_softc *sc = device_get_softc(dev); in bhndb_activate_resource() local
1423 * resource type isn't handled locally. */ in bhndb_activate_resource()
1424 if (bhndb_get_rman(sc, child, rman_get_type(r)) == NULL) { in bhndb_activate_resource()
1425 return (BUS_ACTIVATE_RESOURCE(device_get_parent(sc->parent_dev), in bhndb_activate_resource()
1429 return (bhndb_try_activate_resource(sc, child, r, NULL)); in bhndb_activate_resource()
1436 bhndb_deactivate_resource(device_t dev, device_t child, struct resource *r) in bhndb_deactivate_resource()
1439 struct bhndb_softc *sc; in bhndb_deactivate_resource() local
1443 sc = device_get_softc(dev); in bhndb_deactivate_resource()
1447 * resource type isn't handled locally. */ in bhndb_deactivate_resource()
1448 rm = bhndb_get_rman(sc, child, type); in bhndb_deactivate_resource()
1451 device_get_parent(sc->parent_dev), child, r)); in bhndb_deactivate_resource()
1460 /* No bridge-level state to be freed */ in bhndb_deactivate_resource()
1465 if (bhndb_get_addrspace(sc, child) == BHNDB_ADDRSPACE_BRIDGED) { in bhndb_deactivate_resource()
1466 BHNDB_LOCK(sc); in bhndb_deactivate_resource()
1467 dwa = bhndb_dw_find_resource(sc->bus_res, r); in bhndb_deactivate_resource()
1469 bhndb_dw_release(sc->bus_res, dwa, r); in bhndb_deactivate_resource()
1470 BHNDB_UNLOCK(sc); in bhndb_deactivate_resource()
1476 device_printf(dev, "unsupported resource type %d\n", type); in bhndb_deactivate_resource()
1488 return (&dinfo->resources); in bhndb_get_resource_list()
1497 * For BHNDB_ADDRSPACE_BRIDGED children, the resource priority is determined,
1498 * and if possible, the resource is activated as a direct resource. For example,
1499 * depending on resource priority and bridge resource availability, this
1502 * as an indirect resource -- in that order.
1508 struct bhndb_softc *sc; in bhndb_activate_bhnd_resource() local
1515 KASSERT(!r->direct, in bhndb_activate_bhnd_resource()
1516 ("direct flag set on inactive resource")); in bhndb_activate_bhnd_resource()
1518 KASSERT(!(rman_get_flags(r->res) & RF_ACTIVE), in bhndb_activate_bhnd_resource()
1519 ("RF_ACTIVE set on inactive resource")); in bhndb_activate_bhnd_resource()
1521 sc = device_get_softc(dev); in bhndb_activate_bhnd_resource()
1524 * resource type isn't handled locally. */ in bhndb_activate_bhnd_resource()
1525 if (bhndb_get_rman(sc, child, type) == NULL) { in bhndb_activate_bhnd_resource()
1526 error = BUS_ACTIVATE_RESOURCE(dev, child, r->res); in bhndb_activate_bhnd_resource()
1528 r->direct = true; in bhndb_activate_bhnd_resource()
1532 r_start = rman_get_start(r->res); in bhndb_activate_bhnd_resource()
1533 r_size = rman_get_size(r->res); in bhndb_activate_bhnd_resource()
1535 /* Determine the resource priority of bridged resources, and skip direct in bhndb_activate_bhnd_resource()
1537 if (bhndb_get_addrspace(sc, child) == BHNDB_ADDRSPACE_BRIDGED) { in bhndb_activate_bhnd_resource()
1544 region = bhndb_find_resource_region(sc->bus_res, in bhndb_activate_bhnd_resource()
1547 r_prio = region->priority; in bhndb_activate_bhnd_resource()
1552 * this resource should always be indirect. */ in bhndb_activate_bhnd_resource()
1553 if (r_prio < sc->bus_res->min_prio) in bhndb_activate_bhnd_resource()
1559 device_printf(dev, "unsupported resource type %d\n", in bhndb_activate_bhnd_resource()
1566 error = bhndb_try_activate_resource(sc, child, r->res, &indirect); in bhndb_activate_bhnd_resource()
1568 r->direct = true; in bhndb_activate_bhnd_resource()
1573 r->direct = false; in bhndb_activate_bhnd_resource()
1577 bhndb_get_addrspace(sc, child) == BHNDB_ADDRSPACE_BRIDGED) in bhndb_activate_bhnd_resource()
1579 device_printf(child, "activated 0x%llx-0x%llx as %s " in bhndb_activate_bhnd_resource()
1580 "resource\n", in bhndb_activate_bhnd_resource()
1582 (unsigned long long) r_start + r_size - 1, in bhndb_activate_bhnd_resource()
1583 r->direct ? "direct" : "indirect"); in bhndb_activate_bhnd_resource()
1599 if (!r->direct) in bhndb_deactivate_bhnd_resource()
1602 KASSERT(rman_get_flags(r->res) & RF_ACTIVE, in bhndb_deactivate_bhnd_resource()
1603 ("RF_ACTIVE not set on direct resource")); in bhndb_deactivate_bhnd_resource()
1606 error = BUS_DEACTIVATE_RESOURCE(dev, child, r->res); in bhndb_deactivate_bhnd_resource()
1608 r->direct = false; in bhndb_deactivate_bhnd_resource()
1614 * Find the best available bridge resource allocation record capable of handling
1619 * - Configure and return a free allocation record
1620 * - Return an existing allocation record mapping the requested space, or
1621 * - Steal, configure, and return an in-use allocation record.
1625 * @param sc Bridge driver state.
1639 bhndb_io_resource_get_window(struct bhndb_softc *sc, bus_addr_t addr, in bhndb_io_resource_get_window() argument
1646 BHNDB_LOCK_ASSERT(sc, MA_OWNED); in bhndb_io_resource_get_window()
1648 br = sc->bus_res; in bhndb_io_resource_get_window()
1658 * region would never be allocated as an indirect resource. */ in bhndb_io_resource_get_window()
1659 for (size_t i = 0; i < br->dwa_count; i++) { in bhndb_io_resource_get_window()
1662 dwa = &br->dw_alloc[i]; in bhndb_io_resource_get_window()
1663 win = dwa->win; in bhndb_io_resource_get_window()
1665 KASSERT(win->win_type == BHNDB_REGWIN_T_DYN, in bhndb_io_resource_get_window()
1669 if (addr < dwa->target) in bhndb_io_resource_get_window()
1672 if (addr + size > dwa->target + win->win_size) in bhndb_io_resource_get_window()
1681 * PCI_V0 (BCM4318, etc) Wi-Fi chipsets */ in bhndb_io_resource_get_window()
1686 if ((region->alloc_flags & BHNDB_ALLOC_FULFILL_ON_OVERCOMMIT) == 0) in bhndb_io_resource_get_window()
1697 panic("register windows exhausted attempting to map 0x%llx-0x%llx\n", in bhndb_io_resource_get_window()
1698 (unsigned long long) addr, (unsigned long long) addr+size-1); in bhndb_io_resource_get_window()
1702 * Return a borrowed reference to a bridge resource allocation record capable
1710 * @param sc Bridge driver state.
1713 * @param[out] offset The offset within the returned resource at which
1723 bhndb_io_resource(struct bhndb_softc *sc, bus_addr_t addr, bus_size_t size, in bhndb_io_resource() argument
1730 BHNDB_LOCK_ASSERT(sc, MA_OWNED); in bhndb_io_resource()
1732 dwa = bhndb_io_resource_get_window(sc, addr, size, &borrowed, stolen, in bhndb_io_resource()
1737 if (addr < dwa->target || in bhndb_io_resource()
1738 addr > dwa->target + dwa->win->win_size || in bhndb_io_resource()
1739 (dwa->target + dwa->win->win_size) - addr < size) in bhndb_io_resource()
1744 "range 0x%llx-0x%llx\n", in bhndb_io_resource()
1746 (unsigned long long) addr+size-1); in bhndb_io_resource()
1749 error = bhndb_dw_set_addr(sc->dev, sc->bus_res, dwa, addr, in bhndb_io_resource()
1753 "0x%llx-0x%llx\n", in bhndb_io_resource()
1755 (unsigned long long) addr+size-1); in bhndb_io_resource()
1760 *offset = (addr - dwa->target) + dwa->win->win_offset; in bhndb_io_resource()
1770 struct bhndb_softc *sc; \
1772 struct resource *io_res; \
1777 sc = device_get_softc(dev); \
1779 BHNDB_LOCK(sc); \
1780 dwa = bhndb_io_resource(sc, rman_get_start(r->res) + \
1782 io_res = dwa->parent_res; \
1784 KASSERT(!r->direct, \
1785 ("bhnd_bus slow path used for direct resource")); \
1788 ("i/o resource is not active"));
1792 bhndb_dw_return_stolen(sc->dev, sc->bus_res, \
1795 BHNDB_UNLOCK(sc);
1911 bhndb_setup_intr(device_t dev, device_t child, struct resource *r, in bhndb_setup_intr()
1915 struct bhndb_softc *sc; in bhndb_setup_intr() local
1920 sc = device_get_softc(dev); in bhndb_setup_intr()
1934 error = bus_setup_intr(isrc->is_owner, isrc->is_res, flags, filter, in bhndb_setup_intr()
1935 handler, arg, &ih->ih_cookiep); in bhndb_setup_intr()
1942 BHNDB_LOCK(sc); in bhndb_setup_intr()
1943 bhndb_register_intr_handler(sc->bus_res, ih); in bhndb_setup_intr()
1944 BHNDB_UNLOCK(sc); in bhndb_setup_intr()
1955 bhndb_teardown_intr(device_t dev, device_t child, struct resource *r, in bhndb_teardown_intr()
1958 struct bhndb_softc *sc; in bhndb_teardown_intr() local
1963 sc = device_get_softc(dev); in bhndb_teardown_intr()
1966 BHNDB_LOCK(sc); in bhndb_teardown_intr()
1968 ih = bhndb_find_intr_handler(sc->bus_res, cookiep); in bhndb_teardown_intr()
1974 bhndb_deregister_intr_handler(sc->bus_res, ih); in bhndb_teardown_intr()
1976 BHNDB_UNLOCK(sc); in bhndb_teardown_intr()
1979 isrc = ih->ih_isrc; in bhndb_teardown_intr()
1980 error = bus_teardown_intr(isrc->is_owner, isrc->is_res, ih->ih_cookiep); in bhndb_teardown_intr()
1984 BHNDB_LOCK(sc); in bhndb_teardown_intr()
1985 bhndb_register_intr_handler(sc->bus_res, ih); in bhndb_teardown_intr()
1986 BHNDB_UNLOCK(sc); in bhndb_teardown_intr()
2000 bhndb_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) in bhndb_bind_intr()
2002 struct bhndb_softc *sc; in bhndb_bind_intr() local
2006 sc = device_get_softc(dev); in bhndb_bind_intr()
2009 /* Fetch the isrc corresponding to the child IRQ resource */ in bhndb_bind_intr()
2010 BHNDB_LOCK(sc); in bhndb_bind_intr()
2011 STAILQ_FOREACH(ih, &sc->bus_res->bus_intrs, ih_link) { in bhndb_bind_intr()
2012 if (ih->ih_res == irq) { in bhndb_bind_intr()
2013 isrc = ih->ih_isrc; in bhndb_bind_intr()
2017 BHNDB_UNLOCK(sc); in bhndb_bind_intr()
2020 panic("%s requested bind of invalid irq %#jx-%#jx", in bhndb_bind_intr()
2026 return (bus_bind_intr(isrc->is_owner, isrc->is_res, cpu)); in bhndb_bind_intr()
2033 bhndb_describe_intr(device_t dev, device_t child, struct resource *irq, in bhndb_describe_intr()
2036 struct bhndb_softc *sc; in bhndb_describe_intr() local
2040 sc = device_get_softc(dev); in bhndb_describe_intr()
2045 BHNDB_LOCK(sc); in bhndb_describe_intr()
2047 ih = bhndb_find_intr_handler(sc->bus_res, cookie); in bhndb_describe_intr()
2053 isrc = ih->ih_isrc; in bhndb_describe_intr()
2055 BHNDB_UNLOCK(sc); in bhndb_describe_intr()
2058 return (BUS_DESCRIBE_INTR(device_get_parent(isrc->is_owner), in bhndb_describe_intr()
2059 isrc->is_owner, isrc->is_res, ih->ih_cookiep, descr)); in bhndb_describe_intr()
2091 struct bhndb_softc *sc; in bhndb_get_dma_translation() local
2097 sc = device_get_softc(dev); in bhndb_get_dma_translation()
2098 hwcfg = sc->bus_res->cfg; in bhndb_get_dma_translation()
2101 if (sc->bus_res->res->dma_tags == NULL) in bhndb_get_dma_translation()
2106 /* Backplane must support 64-bit addressing */ in bhndb_get_dma_translation()
2107 if (!(sc->chipid.chip_caps & BHND_CAP_BP64)) in bhndb_get_dma_translation()
2118 for (size_t i = 0; i < sc->bus_res->res->num_dma_tags; i++) { in bhndb_get_dma_translation()
2122 dwin = &hwcfg->dma_translations[i]; in bhndb_get_dma_translation()
2125 if ((dwin->base_addr & addr_mask) != dwin->base_addr) in bhndb_get_dma_translation()
2129 if ((dwin->flags & flags) != flags) in bhndb_get_dma_translation()
2134 masked = (dwin->addr_mask | dwin->addrext_mask) & addr_mask; in bhndb_get_dma_translation()
2142 match_dmat = sc->bus_res->res->dma_tags[i]; in bhndb_get_dma_translation()
2164 struct bhndb_softc *sc = device_get_softc(dev); in bhndb_get_dma_tag() local
2177 return (bus_get_dma_tag(sc->parent_dev)); in bhndb_get_dma_tag()