Lines Matching +full:high +full:- +full:dynamic +full:- +full:range

1 /*-
2 * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
39 * a BHND-compatible bus (e.g. bcma or siba).
172 (unsigned long long) sc->chipid.enum_addr); in bhndb_child_location()
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()
225 * priorities of per-core port resources.
239 * via dynamic register windows */ in bhndb_init_region_cfg()
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()
325 * always HIGH. 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()
362 /* Determine the number of dynamic windows required and 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()
385 /* Define a dynamic region for this port */ 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()
409 * register windows from our dynamic pool */ in bhndb_init_region_cfg()
411 if (prio_total <= br->dwa_count) { in bhndb_init_region_cfg()
412 /* low+default+high priority regions get windows */ 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()
416 /* default+high priority regions get windows */ in bhndb_init_region_cfg()
417 br->min_prio = BHNDB_PRIORITY_DEFAULT; in bhndb_init_region_cfg()
420 /* high priority regions get windows */ 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()
467 * @retval non-zero if an error occurs fetching device info for comparison.
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()
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()
537 device_printf(sc->dev, "unable to identify device, " 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()
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()
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()
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()
628 if ((error = bhnd_service_registry_fini(&sc->services))) in bhndb_generic_detach()
632 bhndb_free_resources(sc->bus_res); in bhndb_generic_detach()
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()
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()
709 /* Non-MMIO resources (e.g. IRQs) are handled solely by our parent */ in bhndb_suspend_resource()
714 dwa = bhndb_dw_find_resource(sc->bus_res, r); in bhndb_suspend_resource()
725 bhndb_dw_release(sc->bus_res, dwa, r); in bhndb_suspend_resource()
740 /* Non-MMIO resources (e.g. IRQs) are handled solely by our parent */ in bhndb_resume_resource()
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()
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()
882 return (&sc->chipid); in bhndb_get_chipid()
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
920 *core = sc->bridge_core; in bhndb_get_hostb_core()
932 return (&sc->services); in bhndb_get_service_registry()
959 return (BUS_ALLOC_RESOURCE(device_get_parent(sc->parent_dev), in bhndb_alloc_resource()
977 if (rle->res != NULL) { 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()
991 if (start > end || count > ((end - start) + 1)) 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()
1046 return (BUS_RELEASE_RESOURCE(device_get_parent(sc->parent_dev), in bhndb_release_resource()
1067 rle->res = NULL; in bhndb_release_resource()
1091 return (BUS_ADJUST_RESOURCE(device_get_parent(sc->parent_dev), 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()
1130 * copied from @p parent, adjusted to contain only the range defined by
1153 /* Configure child resource with window-adjusted real bus values */ in bhndb_init_child_resource()
1178 * @retval non-zero if @p r could not be activated.
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()
1199 bridge_res = bhndb_host_resource_for_regwin(sc->bus_res->res, win); 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()
1220 * Attempt to allocate/retain a dynamic register window for @p r, returning
1238 /* Look for an existing dynamic window we can reference */ 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()
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.
1287 * @retval non-zero activation failed.
1316 device_printf(sc->dev, "unsupported resource type %d\n", type); 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()
1343 r_start - rman_get_start(parent), r_size); 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()
1359 /* Prefer static mappings over consuming a dynamic windows. */ in bhndb_try_activate_resource()
1360 if (region && region->static_regwin) { 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()
1371 * priority to be reserved a dynamic window? */ in bhndb_try_activate_resource()
1372 if (dw_priority < sc->bus_res->min_prio) { 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()
1408 bhndb_dw_release(sc->bus_res, dwa, r); in bhndb_try_activate_resource()
1425 return (BUS_ACTIVATE_RESOURCE(device_get_parent(sc->parent_dev), in bhndb_activate_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()
1464 /* Free any dynamic window allocation. */ 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()
1488 return (&dinfo->resources); in bhndb_get_resource_list()
1501 * static register window, a dynamic register window, or it will configure @p r
1502 * as an indirect resource -- in that order.
1515 KASSERT(!r->direct, in bhndb_activate_bhnd_resource()
1518 KASSERT(!(rman_get_flags(r->res) & RF_ACTIVE), 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()
1544 region = bhndb_find_resource_region(sc->bus_res, in bhndb_activate_bhnd_resource()
1547 r_prio = region->priority; in bhndb_activate_bhnd_resource()
1551 /* If less than the minimum dynamic window priority, in bhndb_activate_bhnd_resource()
1553 if (r_prio < sc->bus_res->min_prio) 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()
1579 device_printf(child, "activated 0x%llx-0x%llx as %s " 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()
1606 error = BUS_DEACTIVATE_RESOURCE(dev, child, r->res); in bhndb_deactivate_bhnd_resource()
1608 r->direct = false; in bhndb_deactivate_bhnd_resource()
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.
1629 * fulfill this request; the borrowed record maps the target address range,
1648 br = sc->bus_res; in bhndb_io_resource_get_window()
1656 /* Search for an existing dynamic mapping of this address range. 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()
1668 /* Verify the range */ 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()
1736 * target range. */ 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()
1780 dwa = bhndb_io_resource(sc, rman_get_start(r->res) + \
1782 io_res = dwa->parent_res; \
1784 KASSERT(!r->direct, \
1792 bhndb_dw_return_stolen(sc->dev, sc->bus_res, \
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()
1943 bhndb_register_intr_handler(sc->bus_res, ih); in bhndb_setup_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()
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()
1985 bhndb_register_intr_handler(sc->bus_res, ih); in bhndb_teardown_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()
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()
2047 ih = bhndb_find_intr_handler(sc->bus_res, cookie); in bhndb_describe_intr()
2053 isrc = ih->ih_isrc; 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()
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()
2133 * range */ 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()
2177 return (bus_get_dma_tag(sc->parent_dev)); in bhndb_get_dma_tag()