diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -126,11 +126,16 @@ static bus_read_ivar_t acpi_read_ivar; static bus_write_ivar_t acpi_write_ivar; static bus_get_resource_list_t acpi_get_rlist; +static bus_get_rman_t acpi_get_rman; static bus_set_resource_t acpi_set_resource; static bus_alloc_resource_t acpi_alloc_resource; static bus_adjust_resource_t acpi_adjust_resource; static bus_release_resource_t acpi_release_resource; static bus_delete_resource_t acpi_delete_resource; +static bus_activate_resource_t acpi_activate_resource; +static bus_deactivate_resource_t acpi_deactivate_resource; +static bus_map_resource_t acpi_map_resource; +static bus_unmap_resource_t acpi_unmap_resource; static bus_child_pnpinfo_t acpi_child_pnpinfo_method; static bus_child_location_t acpi_child_location_method; static bus_hint_device_unit_t acpi_hint_device_unit; @@ -196,16 +201,19 @@ DEVMETHOD(bus_read_ivar, acpi_read_ivar), DEVMETHOD(bus_write_ivar, acpi_write_ivar), DEVMETHOD(bus_get_resource_list, acpi_get_rlist), + DEVMETHOD(bus_get_rman, acpi_get_rman), DEVMETHOD(bus_set_resource, acpi_set_resource), DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), DEVMETHOD(bus_alloc_resource, acpi_alloc_resource), DEVMETHOD(bus_adjust_resource, acpi_adjust_resource), DEVMETHOD(bus_release_resource, acpi_release_resource), DEVMETHOD(bus_delete_resource, acpi_delete_resource), + DEVMETHOD(bus_activate_resource, acpi_activate_resource), + DEVMETHOD(bus_deactivate_resource, acpi_deactivate_resource), + DEVMETHOD(bus_map_resource, acpi_map_resource), + DEVMETHOD(bus_unmap_resource, acpi_unmap_resource), DEVMETHOD(bus_child_pnpinfo, acpi_child_pnpinfo_method), DEVMETHOD(bus_child_location, acpi_child_location_method), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_hint_device_unit, acpi_hint_device_unit), @@ -479,6 +487,8 @@ if (rman_init(&acpi_rman_mem) != 0) panic("acpi rman_init memory failed"); + resource_list_init(&sc->sysres_rl); + /* Initialise the ACPI mutex */ mtx_init(&acpi_mutex, "ACPI global lock", NULL, MTX_DEF); @@ -1294,6 +1304,20 @@ return (bus_generic_get_domain(dev, child, domain)); } +static struct rman * +acpi_get_rman(device_t bus, int type, u_int flags) +{ + /* Only memory and IO resources are managed. */ + switch (type) { + case SYS_RES_IOPORT: + return (&acpi_rman_io); + case SYS_RES_MEMORY: + return (&acpi_rman_mem); + default: + return (NULL); + } +} + /* * Pre-allocate/manage all memory and IO resources. Since rman can't handle * duplicates, we merge any in the sysresource attach routine. @@ -1301,8 +1325,8 @@ static int acpi_sysres_alloc(device_t dev) { + struct acpi_softc *sc = device_get_softc(dev); struct resource *res; - struct resource_list *rl; struct resource_list_entry *rle; struct rman *rm; device_t *children; @@ -1320,28 +1344,21 @@ } free(children, M_TEMP); - rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); - STAILQ_FOREACH(rle, rl, link) { + STAILQ_FOREACH(rle, &sc->sysres_rl, link) { if (rle->res != NULL) { device_printf(dev, "duplicate resource for %jx\n", rle->start); continue; } /* Only memory and IO resources are valid here. */ - switch (rle->type) { - case SYS_RES_IOPORT: - rm = &acpi_rman_io; - break; - case SYS_RES_MEMORY: - rm = &acpi_rman_mem; - break; - default: + rm = acpi_get_rman(dev, rle->type, 0); + if (rm == NULL) continue; - } /* Pre-allocate resource and add to our rman pool. */ - res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, rle->type, - &rle->rid, rle->start, rle->start + rle->count - 1, rle->count, 0); + res = bus_alloc_resource(dev, rle->type, + &rle->rid, rle->start, rle->start + rle->count - 1, rle->count, + RF_ACTIVE | RF_UNMAPPED); if (res != NULL) { rman_manage_region(rm, rman_get_start(res), rman_get_end(res)); rle->res = res; @@ -1542,63 +1559,39 @@ * from our system resource regions. */ if (res == NULL && start + count - 1 == end) - res = acpi_alloc_sysres(child, type, rid, start, end, count, flags); + res = bus_generic_rman_alloc_resource(bus, child, type, rid, start, end, + count, flags); return (res); } -/* - * Attempt to allocate a specific resource range from the system - * resource ranges. Note that we only handle memory and I/O port - * system resources. - */ -struct resource * -acpi_alloc_sysres(device_t child, int type, int *rid, rman_res_t start, - rman_res_t end, rman_res_t count, u_int flags) +static bool +acpi_is_resource_managed(device_t bus, int type, struct resource *r) { - struct rman *rm; - struct resource *res; - - switch (type) { - case SYS_RES_IOPORT: - rm = &acpi_rman_io; - break; - case SYS_RES_MEMORY: - rm = &acpi_rman_mem; - break; - default: - return (NULL); - } + struct rman *rm; - KASSERT(start + count - 1 == end, ("wildcard resource range")); - res = rman_reserve_resource(rm, start, end, count, flags & ~RF_ACTIVE, - child); - if (res == NULL) - return (NULL); - - rman_set_rid(res, *rid); - - /* If requested, activate the resource using the parent's method. */ - if (flags & RF_ACTIVE) - if (bus_activate_resource(child, type, *rid, res) != 0) { - rman_release_resource(res); - return (NULL); - } - - return (res); + rm = acpi_get_rman(bus, type, 0); + if (rm == NULL) + return (false); + return (rman_is_region_manager(r, rm)); } -static int -acpi_is_resource_managed(int type, struct resource *r) +static struct resource * +acpi_managed_resource(device_t bus, int type, struct resource *r) { + struct acpi_softc *sc = device_get_softc(bus); + struct resource_list_entry *rle; - /* We only handle memory and IO resources through rman. */ - switch (type) { - case SYS_RES_IOPORT: - return (rman_is_region_manager(r, &acpi_rman_io)); - case SYS_RES_MEMORY: - return (rman_is_region_manager(r, &acpi_rman_mem)); - } - return (0); + KASSERT(acpi_is_resource_managed(bus, type, r), + ("resource %p is not suballocated", r)); + + STAILQ_FOREACH(rle, &sc->sysres_rl, link) { + if (rle->type != type || rle->res == NULL) + continue; + if (rman_get_start(r) >= rman_get_start(rle->res) && + rman_get_end(r) <= rman_get_end(rle->res)) + return (rle->res); + } + return (NULL); } static int @@ -1606,7 +1599,7 @@ rman_res_t start, rman_res_t end) { - if (acpi_is_resource_managed(type, r)) + if (acpi_is_resource_managed(bus, type, r)) return (rman_adjust_resource(r, start, end)); return (bus_generic_adjust_resource(bus, child, type, r, start, end)); } @@ -1615,20 +1608,12 @@ acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { - int ret; - /* * If this resource belongs to one of our internal managers, * deactivate it and release it to the local pool. */ - if (acpi_is_resource_managed(type, r)) { - if (rman_get_flags(r) & RF_ACTIVE) { - ret = bus_deactivate_resource(child, type, rid, r); - if (ret != 0) - return (ret); - } - return (rman_release_resource(r)); - } + if (acpi_is_resource_managed(bus, type, r)) + return (bus_generic_rman_release_resource(bus, child, type, rid, r)); return (bus_generic_rl_release_resource(bus, child, type, rid, r)); } @@ -1648,6 +1633,69 @@ resource_list_delete(rl, type, rid); } +static int +acpi_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + if (acpi_is_resource_managed(bus, type, r)) + return (bus_generic_rman_activate_resource(bus, child, type, + rid, r)); + return (bus_generic_activate_resource(bus, child, type, rid, r)); +} + +static int +acpi_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + if (acpi_is_resource_managed(bus, type, r)) + return (bus_generic_rman_deactivate_resource(bus, child, type, + rid, r)); + return (bus_generic_deactivate_resource(bus, child, type, rid, r)); +} + +static int +acpi_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 args; + struct resource *sysres; + rman_res_t length, start; + int error; + + if (!acpi_is_resource_managed(bus, type, r)) + return (bus_generic_map_resource(bus, child, type, r, argsp, + map)); + + /* Resources must be active to be mapped. */ + if (!(rman_get_flags(r) & RF_ACTIVE)) + return (ENXIO); + + resource_init_map_request(&args); + error = resource_validate_map_request(r, argsp, &args, &start, &length); + if (error) + return (error); + + sysres = acpi_managed_resource(bus, type, r); + if (sysres == NULL) + return (ENOENT); + + args.offset = start - rman_get_start(sysres); + args.length = length; + return (bus_generic_map_resource(bus, child, type, sysres, &args, map)); +} + +static int +acpi_unmap_resource(device_t bus, device_t child, int type, struct resource *r, + struct resource_map *map) +{ + if (acpi_is_resource_managed(bus, type, r)) { + r = acpi_managed_resource(bus, type, r); + if (r == NULL) + return (ENOENT); + } + return (bus_generic_unmap_resource(bus, child, type, r, map)); +} + /* Allocate an IO port or memory resource, given its GAS. */ int acpi_bus_alloc_gas(device_t dev, int *type, int *rid, ACPI_GENERIC_ADDRESS *gas, diff --git a/sys/dev/acpica/acpi_resource.c b/sys/dev/acpica/acpi_resource.c --- a/sys/dev/acpica/acpi_resource.c +++ b/sys/dev/acpica/acpi_resource.c @@ -737,8 +737,6 @@ * private rman. */ -static int acpi_sysres_rid = 100; - static int acpi_sysres_probe(device_t dev); static int acpi_sysres_attach(device_t dev); @@ -780,6 +778,7 @@ acpi_sysres_attach(device_t dev) { device_t bus; + struct acpi_softc *bus_sc; struct resource_list_entry *bus_rle, *dev_rle; struct resource_list *bus_rl, *dev_rl; int done, type; @@ -794,7 +793,8 @@ */ bus = device_get_parent(dev); dev_rl = BUS_GET_RESOURCE_LIST(bus, dev); - bus_rl = BUS_GET_RESOURCE_LIST(device_get_parent(bus), bus); + bus_sc = acpi_device_get_parent_softc(dev); + bus_rl = &bus_sc->sysres_rl; STAILQ_FOREACH(dev_rle, dev_rl, link) { if (dev_rle->type != SYS_RES_IOPORT && dev_rle->type != SYS_RES_MEMORY) continue; @@ -834,7 +834,7 @@ /* If we didn't merge with anything, add this resource. */ if (bus_rle == NULL) - bus_set_resource(bus, type, acpi_sysres_rid++, start, count); + resource_list_add_next(bus_rl, type, start, end, count); } /* After merging/moving resources to the parent, free the list. */ diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -78,6 +78,9 @@ struct apm_clone_data *acpi_clone; /* Pseudo-dev for devd(8). */ STAILQ_HEAD(,apm_clone_data) apm_cdevs; /* All apm/apmctl/acpi cdevs. */ struct callout susp_force_to; /* Force suspend if no acks. */ + + /* System Resources */ + struct resource_list sysres_rl; }; struct acpi_device { @@ -438,9 +441,6 @@ struct resource *res, ACPI_RESOURCE *acpi_res); ACPI_STATUS acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set, void *arg); -struct resource *acpi_alloc_sysres(device_t child, int type, int *rid, - rman_res_t start, rman_res_t end, rman_res_t count, - u_int flags); /* ACPI event handling */ UINT32 acpi_event_power_button_sleep(void *context);