Changeset View
Standalone View
sys/powerpc/powerpc/nexus.c
Show First 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
#include <machine/intr_machdep.h> | #include <machine/intr_machdep.h> | ||||
#include <machine/resource.h> | #include <machine/resource.h> | ||||
/* | /* | ||||
* The nexus handles root-level resource allocation requests and interrupt | * The nexus handles root-level resource allocation requests and interrupt | ||||
* mapping. All direct subdevices of nexus are attached by DEVICE_IDENTIFY(). | * mapping. All direct subdevices of nexus are attached by DEVICE_IDENTIFY(). | ||||
*/ | */ | ||||
static struct rman intr_rman; | |||||
static struct rman mem_rman; | |||||
static device_probe_t nexus_probe; | static device_probe_t nexus_probe; | ||||
static device_attach_t nexus_attach; | static device_attach_t nexus_attach; | ||||
static bus_setup_intr_t nexus_setup_intr; | static bus_setup_intr_t nexus_setup_intr; | ||||
static bus_teardown_intr_t nexus_teardown_intr; | static bus_teardown_intr_t nexus_teardown_intr; | ||||
static bus_alloc_resource_t nexus_alloc_resource; | |||||
static bus_activate_resource_t nexus_activate_resource; | static bus_activate_resource_t nexus_activate_resource; | ||||
static bus_deactivate_resource_t nexus_deactivate_resource; | static bus_deactivate_resource_t nexus_deactivate_resource; | ||||
static bus_adjust_resource_t nexus_adjust_resource; | |||||
static bus_release_resource_t nexus_release_resource; | |||||
static int nexus_map_resource(device_t bus, device_t child, int type, | static int nexus_map_resource(device_t bus, device_t child, int type, | ||||
struct resource *r, | struct resource *r, | ||||
struct resource_map_request *argsp, | struct resource_map_request *argsp, | ||||
struct resource_map *map); | struct resource_map *map); | ||||
static int nexus_unmap_resource(device_t bus, device_t child, int type, | static int nexus_unmap_resource(device_t bus, device_t child, int type, | ||||
struct resource *r, struct resource_map *map); | struct resource *r, struct resource_map *map); | ||||
static bus_space_tag_t nexus_get_bus_tag(device_t, device_t); | static bus_space_tag_t nexus_get_bus_tag(device_t, device_t); | ||||
static int nexus_get_cpus(device_t, device_t, enum cpu_sets, size_t, | static int nexus_get_cpus(device_t, device_t, enum cpu_sets, size_t, | ||||
cpuset_t *); | cpuset_t *); | ||||
#ifdef SMP | #ifdef SMP | ||||
static bus_bind_intr_t nexus_bind_intr; | static bus_bind_intr_t nexus_bind_intr; | ||||
#endif | #endif | ||||
static bus_config_intr_t nexus_config_intr; | static bus_config_intr_t nexus_config_intr; | ||||
static ofw_bus_map_intr_t nexus_ofw_map_intr; | static ofw_bus_map_intr_t nexus_ofw_map_intr; | ||||
static device_method_t nexus_methods[] = { | static device_method_t nexus_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, nexus_probe), | DEVMETHOD(device_probe, nexus_probe), | ||||
DEVMETHOD(device_attach, nexus_attach), | DEVMETHOD(device_attach, nexus_attach), | ||||
/* Bus interface */ | /* Bus interface */ | ||||
DEVMETHOD(bus_add_child, bus_generic_add_child), | DEVMETHOD(bus_add_child, bus_generic_add_child), | ||||
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), | |||||
DEVMETHOD(bus_activate_resource, nexus_activate_resource), | DEVMETHOD(bus_activate_resource, nexus_activate_resource), | ||||
DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), | DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), | ||||
DEVMETHOD(bus_adjust_resource, nexus_adjust_resource), | |||||
DEVMETHOD(bus_release_resource, nexus_release_resource), | |||||
DEVMETHOD(bus_map_resource, nexus_map_resource), | DEVMETHOD(bus_map_resource, nexus_map_resource), | ||||
DEVMETHOD(bus_unmap_resource, nexus_unmap_resource), | DEVMETHOD(bus_unmap_resource, nexus_unmap_resource), | ||||
DEVMETHOD(bus_setup_intr, nexus_setup_intr), | DEVMETHOD(bus_setup_intr, nexus_setup_intr), | ||||
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), | DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), | ||||
#ifdef SMP | #ifdef SMP | ||||
DEVMETHOD(bus_bind_intr, nexus_bind_intr), | DEVMETHOD(bus_bind_intr, nexus_bind_intr), | ||||
#endif | #endif | ||||
DEVMETHOD(bus_config_intr, nexus_config_intr), | DEVMETHOD(bus_config_intr, nexus_config_intr), | ||||
Show All 21 Lines | nexus_probe(device_t dev) | ||||
return (BUS_PROBE_DEFAULT); | return (BUS_PROBE_DEFAULT); | ||||
} | } | ||||
static int | static int | ||||
nexus_attach(device_t dev) | nexus_attach(device_t dev) | ||||
{ | { | ||||
intr_rman.rm_type = RMAN_ARRAY; | |||||
intr_rman.rm_descr = "Interrupts"; | |||||
mem_rman.rm_type = RMAN_ARRAY; | |||||
mem_rman.rm_descr = "Device Memory"; | |||||
if (rman_init(&intr_rman) != 0 || | |||||
rman_init(&mem_rman) != 0 || | |||||
rman_manage_region(&intr_rman, 0, 1UL << 16) != 0 || | |||||
rman_manage_region(&mem_rman, 0, ~0 >> 1) != 0) | |||||
mhorne: Please do not change the region boundaries, we want to maintain the same behaviour before and… | |||||
ehem_freebsd_m5p.comAuthorUnsubmitted Done Inline ActionsEach time I run across the default range I hear klaxons screaming "uninitialized! uninitialized! uninitialized!" (new form of Dalek?). I really dislike leaving this alone, even if that ends up being a separate diff. ehem_freebsd_m5p.com: Each time I run across the default range I hear klaxons screaming "uninitialized! | |||||
mhorneUnsubmitted Done Inline ActionsWell, they are not uninitialized, but initialized to the default/maximum values. Now that the overflow in rman_reserve_resource_bound() has been fixed we shouldn't fear using this range, it is meant to be supported. mhorne: Well, they are not uninitialized, but initialized to the default/maximum values. Now that the… | |||||
panic("%s: failed to set up rmans.", __func__); | |||||
bus_generic_probe(dev); | bus_generic_probe(dev); | ||||
bus_generic_attach(dev); | bus_generic_attach(dev); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
nexus_setup_intr(device_t bus __unused, device_t child, struct resource *r, | nexus_setup_intr(device_t bus __unused, device_t child, struct resource *r, | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, | ||||
pcell_t *irq) | pcell_t *irq) | ||||
{ | { | ||||
u_int intr = MAP_IRQ(iparent, irq[0]); | u_int intr = MAP_IRQ(iparent, irq[0]); | ||||
if (icells > 1) | if (icells > 1) | ||||
powerpc_fw_config_intr(intr, irq[1]); | powerpc_fw_config_intr(intr, irq[1]); | ||||
return (intr); | return (intr); | ||||
} | } | ||||
static struct resource * | |||||
nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, | |||||
rman_res_t start, rman_res_t end, rman_res_t count, u_int flags) | |||||
{ | |||||
struct rman *rm; | |||||
struct resource *rv; | |||||
struct resource_list_entry *rle; | |||||
int isdefault, passthrough; | |||||
isdefault = RMAN_IS_DEFAULT_RANGE(start, end); | |||||
passthrough = (device_get_parent(child) != bus); | |||||
rle = NULL; | |||||
if (!passthrough && isdefault) { | |||||
rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child), | |||||
type, *rid); | |||||
if (rle == NULL) { | |||||
if (bootverbose) | |||||
device_printf(bus, "no default resources for " | |||||
"rid = %d, type = %d\n", *rid, type); | |||||
return (NULL); | |||||
} | |||||
start = rle->start; | |||||
count = ummax(count, rle->count); | |||||
end = ummax(rle->end, start + count - 1); | |||||
} | |||||
switch (type) { | |||||
case SYS_RES_IRQ: | |||||
rm = &intr_rman; | |||||
break; | |||||
case SYS_RES_MEMORY: | |||||
rm = &mem_rman; | |||||
break; | |||||
default: | |||||
return (NULL); | |||||
} | |||||
rv = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, | |||||
child); | |||||
if (rv == NULL) | |||||
return (NULL); | |||||
rman_set_rid(rv, *rid); | |||||
if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(child, type, | |||||
*rid, rv) != 0) { | |||||
rman_release_resource(rv); | |||||
return (NULL); | |||||
} | |||||
if (!passthrough && rle != NULL) { | |||||
rle->res = rv; | |||||
rle->start = rman_get_start(rv); | |||||
rle->end = rman_get_end(rv); | |||||
rle->count = rle->end - rle->start + 1; | |||||
} | |||||
return (rv); | |||||
} | |||||
static int | static int | ||||
nexus_activate_resource(device_t bus __unused, device_t child __unused, | nexus_activate_resource(device_t bus __unused, device_t child __unused, | ||||
int type, int rid __unused, struct resource *r) | int type, int rid __unused, struct resource *r) | ||||
{ | { | ||||
if (type == SYS_RES_MEMORY) { | if (type == SYS_RES_MEMORY) { | ||||
vm_paddr_t start; | vm_paddr_t start; | ||||
void *p; | void *p; | ||||
Show All 26 Lines | if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { | ||||
psize = rman_get_size(r); | psize = rman_get_size(r); | ||||
pmap_unmapdev((vm_offset_t)rman_get_virtual(r), psize); | pmap_unmapdev((vm_offset_t)rman_get_virtual(r), psize); | ||||
} | } | ||||
return (rman_deactivate_resource(r)); | return (rman_deactivate_resource(r)); | ||||
} | } | ||||
static int | |||||
nexus_adjust_resource(device_t bus, device_t child __unused, int type, | |||||
mhorneUnsubmitted Not Done Inline ActionsMoving this out of ofwbus means that arm, arm64, mips, and riscv are now without a bus_adjust_resource method. I think this is okay, it is not used very widely and arm64 with ACPI has always been without it. Still, it will be worth noting in the final commit message, as this could be a regression. mhorne: Moving this out of ofwbus means that arm, arm64, mips, and riscv are now without a… | |||||
ehem_freebsd_m5p.comAuthorUnsubmitted Done Inline ActionsHuh. I hadn't noticed any issues, but that is certainly worthy of mention. ehem_freebsd_m5p.com: Huh. I hadn't noticed any issues, but that is certainly worthy of mention. | |||||
struct resource *r, rman_res_t start, rman_res_t end) | |||||
{ | |||||
struct rman *rm; | |||||
device_t ofwbus; | |||||
ofwbus = bus; | |||||
while (strcmp(device_get_name(device_get_parent(ofwbus)), "root") != 0) | |||||
ofwbus = device_get_parent(ofwbus); | |||||
switch (type) { | |||||
case SYS_RES_IRQ: | |||||
rm = &intr_rman; | |||||
break; | |||||
case SYS_RES_MEMORY: | |||||
rm = &mem_rman; | |||||
break; | |||||
default: | |||||
return (EINVAL); | |||||
} | |||||
if (rm == NULL) | |||||
return (ENXIO); | |||||
if (rman_is_region_manager(r, rm) == 0) | |||||
return (EINVAL); | |||||
return (rman_adjust_resource(r, start, end)); | |||||
} | |||||
static int | |||||
nexus_release_resource(device_t bus, device_t child, int type, | |||||
int rid, struct resource *r) | |||||
{ | |||||
struct resource_list_entry *rle; | |||||
int passthrough; | |||||
int error; | |||||
passthrough = (device_get_parent(child) != bus); | |||||
if (!passthrough) { | |||||
/* Clean resource list entry */ | |||||
rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child), | |||||
type, rid); | |||||
if (rle != NULL) | |||||
rle->res = NULL; | |||||
} | |||||
if ((rman_get_flags(r) & RF_ACTIVE) != 0) { | |||||
error = bus_deactivate_resource(child, type, rid, r); | |||||
if (error) | |||||
return (error); | |||||
} | |||||
return (rman_release_resource(r)); | |||||
} | |||||
static int | static int | ||||
nexus_map_resource(device_t bus, device_t child, int type, struct resource *r, | nexus_map_resource(device_t bus, device_t child, int type, struct resource *r, | ||||
struct resource_map_request *argsp, struct resource_map *map) | struct resource_map_request *argsp, struct resource_map *map) | ||||
{ | { | ||||
struct resource_map_request args; | struct resource_map_request args; | ||||
rman_res_t end, length, start; | rman_res_t end, length, start; | ||||
▲ Show 20 Lines • Show All 77 Lines • Show Last 20 Lines |
Please do not change the region boundaries, we want to maintain the same behaviour before and after moving the code around.