diff options
-rw-r--r-- | sys/dev/acpica/acpi_cpu.c | 116 | ||||
-rw-r--r-- | sys/i386/i386/legacy.c | 92 |
2 files changed, 166 insertions, 42 deletions
diff --git a/sys/dev/acpica/acpi_cpu.c b/sys/dev/acpica/acpi_cpu.c index 471638a..8015af9 100644 --- a/sys/dev/acpica/acpi_cpu.c +++ b/sys/dev/acpica/acpi_cpu.c @@ -1,5 +1,5 @@ /*- - * Copyright (c) 2003 Nate Lawson (SDG) + * Copyright (c) 2003-2005 Nate Lawson (SDG) * Copyright (c) 2001 Michael Smith * All rights reserved. * @@ -31,6 +31,7 @@ __FBSDID("$FreeBSD$"); #include "opt_acpi.h" #include <sys/param.h> #include <sys/bus.h> +#include <sys/cpu.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/module.h> @@ -71,7 +72,8 @@ struct acpi_cx { struct acpi_cpu_softc { device_t cpu_dev; ACPI_HANDLE cpu_handle; - uint32_t acpi_id; /* ACPI processor id */ + struct pcpu *cpu_pcpu; + uint32_t cpu_acpi_id; /* ACPI processor id */ uint32_t cpu_p_blk; /* ACPI P_BLK location */ uint32_t cpu_p_blk_len; /* P_BLK length (must be 6). */ struct resource *cpu_p_cnt; /* Throttling control register */ @@ -80,6 +82,10 @@ struct acpi_cpu_softc { int cpu_prev_sleep;/* Last idle sleep duration. */ }; +struct acpi_cpu_device { + struct resource_list ad_rl; +}; + #define CPU_GET_REG(reg, width) \ (bus_space_read_ ## width(rman_get_bustag((reg)), \ rman_get_bushandle((reg)), 0)) @@ -127,6 +133,8 @@ static int cpu_non_c3; /* Index of lowest non-C3 state. */ static u_int cpu_cx_stats[MAX_CX_STATES];/* Cx usage history. */ /* Values for sysctl. */ +static struct sysctl_ctx_list acpi_cpu_sysctl_ctx; +static struct sysctl_oid *acpi_cpu_sysctl_tree; static uint32_t cpu_throttle_state; static uint32_t cpu_throttle_max; static int cpu_cx_lowest; @@ -137,13 +145,15 @@ static int cpu_ndevices; static struct acpi_cpu_softc **cpu_softc; ACPI_SERIAL_DECL(cpu, "ACPI CPU"); -static struct sysctl_ctx_list acpi_cpu_sysctl_ctx; -static struct sysctl_oid *acpi_cpu_sysctl_tree; - static int acpi_cpu_probe(device_t dev); static int acpi_cpu_attach(device_t dev); static int acpi_pcpu_get_id(uint32_t idx, uint32_t *acpi_id, - uint32_t *cpu_id); + uint32_t *cpu_id); +static struct resource_list *acpi_cpu_get_rlist(device_t dev, device_t child); +static device_t acpi_cpu_add_child(device_t dev, int order, const char *name, + int unit); +static int acpi_cpu_read_ivar(device_t dev, device_t child, int index, + uintptr_t *result); static int acpi_cpu_shutdown(device_t dev); static int acpi_cpu_throttle_probe(struct acpi_cpu_softc *sc); static int acpi_cpu_cx_probe(struct acpi_cpu_softc *sc); @@ -163,7 +173,24 @@ static device_method_t acpi_cpu_methods[] = { /* Device interface */ DEVMETHOD(device_probe, acpi_cpu_probe), DEVMETHOD(device_attach, acpi_cpu_attach), + DEVMETHOD(device_detach, bus_generic_detach), DEVMETHOD(device_shutdown, acpi_cpu_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), + + /* Bus interface */ + DEVMETHOD(bus_add_child, acpi_cpu_add_child), + DEVMETHOD(bus_read_ivar, acpi_cpu_read_ivar), + DEVMETHOD(bus_get_resource_list, acpi_cpu_get_rlist), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), + DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), + DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + 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), {0, 0} }; @@ -174,8 +201,8 @@ static driver_t acpi_cpu_driver = { sizeof(struct acpi_cpu_softc), }; -static devclass_t acpi_cpu_devclass; -DRIVER_MODULE(cpu, acpi, acpi_cpu_driver, acpi_cpu_devclass, 0, 0); +extern devclass_t cpu_devclass; +DRIVER_MODULE(cpu, acpi, acpi_cpu_driver, cpu_devclass, 0, 0); MODULE_DEPEND(cpu, acpi, 1, 1, 1); static int @@ -265,17 +292,22 @@ acpi_cpu_attach(device_t dev) { ACPI_BUFFER buf; ACPI_OBJECT *obj; + struct pcpu *pcpu_data; struct acpi_cpu_softc *sc; struct acpi_softc *acpi_sc; ACPI_STATUS status; - int thr_ret, cx_ret; + int cx_ret, cpu_id, thr_ret; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); sc = device_get_softc(dev); sc->cpu_dev = dev; sc->cpu_handle = acpi_get_handle(dev); - cpu_softc[acpi_get_magic(dev)] = sc; + cpu_id = acpi_get_magic(dev); + cpu_softc[cpu_id] = sc; + pcpu_data = pcpu_find(cpu_id); + pcpu_data->pc_device = dev; + sc->cpu_pcpu = pcpu_data; buf.Pointer = NULL; buf.Length = ACPI_ALLOCATE_BUFFER; @@ -288,7 +320,7 @@ acpi_cpu_attach(device_t dev) obj = (ACPI_OBJECT *)buf.Pointer; sc->cpu_p_blk = obj->Processor.PblkAddress; sc->cpu_p_blk_len = obj->Processor.PblkLength; - sc->acpi_id = obj->Processor.ProcId; + sc->cpu_acpi_id = obj->Processor.ProcId; AcpiOsFree(obj); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: P_BLK at %#x/%d\n", device_get_unit(dev), sc->cpu_p_blk, sc->cpu_p_blk_len)); @@ -296,8 +328,8 @@ acpi_cpu_attach(device_t dev) acpi_sc = acpi_device_get_parent_softc(dev); sysctl_ctx_init(&acpi_cpu_sysctl_ctx); acpi_cpu_sysctl_tree = SYSCTL_ADD_NODE(&acpi_cpu_sysctl_ctx, - SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), - OID_AUTO, "cpu", CTLFLAG_RD, 0, ""); + SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "cpu", + CTLFLAG_RD, 0, ""); /* * Probe for throttling and Cx state support. @@ -314,7 +346,11 @@ acpi_cpu_attach(device_t dev) sysctl_ctx_free(&acpi_cpu_sysctl_ctx); } - return_VALUE (0); + /* Call identify and then probe/attach for cpu child drivers. */ + bus_generic_probe(dev); + bus_generic_attach(dev); + + return (0); } /* @@ -353,11 +389,61 @@ acpi_pcpu_get_id(uint32_t idx, uint32_t *acpi_id, uint32_t *cpu_id) return (ESRCH); } +static struct resource_list * +acpi_cpu_get_rlist(device_t dev, device_t child) +{ + struct acpi_cpu_device *ad; + + ad = device_get_ivars(child); + if (ad == NULL) + return (NULL); + return (&ad->ad_rl); +} + +static device_t +acpi_cpu_add_child(device_t dev, int order, const char *name, int unit) +{ + struct acpi_cpu_device *ad; + device_t child; + + if ((ad = malloc(sizeof(*ad), M_TEMP, M_NOWAIT | M_ZERO)) == NULL) + return (NULL); + + resource_list_init(&ad->ad_rl); + + child = device_add_child_ordered(dev, order, name, unit); + if (child != NULL) + device_set_ivars(child, ad); + return (child); +} + +static int +acpi_cpu_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) +{ + struct acpi_cpu_softc *sc; + + sc = device_get_softc(dev); + switch (index) { + case ACPI_IVAR_HANDLE: + *result = (uintptr_t)sc->cpu_handle; + break; + case CPU_IVAR_PCPU: + *result = (uintptr_t)sc->cpu_pcpu; + break; + default: + return (ENOENT); + } + return (0); +} + static int acpi_cpu_shutdown(device_t dev) { ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + /* Allow children to shutdown first. */ + bus_generic_shutdown(dev); + /* Disable any entry to the idle function. */ cpu_cx_count = 0; @@ -668,7 +754,7 @@ acpi_cpu_startup(void *arg) int count, i; /* Get set of CPU devices */ - devclass_get_devices(acpi_cpu_devclass, &cpu_devices, &cpu_ndevices); + devclass_get_devices(cpu_devclass, &cpu_devices, &cpu_ndevices); /* Check for quirks via the first CPU device. */ sc = device_get_softc(cpu_devices[0]); diff --git a/sys/i386/i386/legacy.c b/sys/i386/i386/legacy.c index af7f157..2112d77 100644 --- a/sys/i386/i386/legacy.c +++ b/sys/i386/i386/legacy.c @@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> +#include <sys/cpu.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/module.h> @@ -137,32 +138,25 @@ legacy_attach(device_t dev) { device_t child; int i; - struct pcpu *pc; + /* First, attach the CPU pseudo-driver. */ + for (i = 0; i <= mp_maxid; i++) + if (!CPU_ABSENT(i)) { + child = BUS_ADD_CHILD(dev, 0, "cpu", i); + if (child == NULL) + panic("legacy_attach cpu"); + device_probe_and_attach(child); + } + +#ifndef PC98 /* - * First, let our child driver's identify any child devices that + * Second, let our child driver's identify any child devices that * they can find. Once that is done attach any devices that we * found. */ bus_generic_probe(dev); bus_generic_attach(dev); - /* Attach CPU pseudo-driver. */ - if (!devclass_get_device(devclass_find("cpu"), 0)) { - for (i = 0; i <= mp_maxid; i++) - if (!CPU_ABSENT(i)) { - pc = pcpu_find(i); - KASSERT(pc != NULL, ("pcpu_find failed")); - child = BUS_ADD_CHILD(dev, 0, "cpu", i); - if (child == NULL) - panic("legacy_attach cpu"); - device_probe_and_attach(child); - pc->pc_device = child; - device_set_ivars(child, pc); - } - } - -#ifndef PC98 /* * If we didn't see EISA or ISA on a pci bridge, create some * connection points now so they show up "on motherboard". @@ -265,6 +259,14 @@ legacy_write_ivar(device_t dev, device_t child, int which, uintptr_t value) */ static int cpu_read_ivar(device_t dev, device_t child, int index, uintptr_t *result); +static device_t cpu_add_child(device_t bus, int order, const char *name, + int unit); +static struct resource_list *cpu_get_rlist(device_t dev, device_t child); + +struct cpu_device { + struct resource_list cd_rl; + struct pcpu *cd_pcpu; +}; static device_method_t cpu_methods[] = { /* Device interface */ @@ -276,10 +278,15 @@ static device_method_t cpu_methods[] = { DEVMETHOD(device_resume, bus_generic_resume), /* Bus interface */ + DEVMETHOD(bus_add_child, cpu_add_child), DEVMETHOD(bus_read_ivar, cpu_read_ivar), DEVMETHOD(bus_print_child, bus_generic_print_child), - DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), - DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_get_resource_list, cpu_get_rlist), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), + DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), + DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), @@ -293,19 +300,50 @@ static driver_t cpu_driver = { cpu_methods, 1, /* no softc */ }; -static devclass_t cpu_devclass; +devclass_t cpu_devclass; DRIVER_MODULE(cpu, legacy, cpu_driver, cpu_devclass, 0, 0); +static device_t +cpu_add_child(device_t bus, int order, const char *name, int unit) +{ + struct cpu_device *cd; + device_t child; + struct pcpu *pc; + + if ((cd = malloc(sizeof(*cd), M_DEVBUF, M_NOWAIT | M_ZERO)) == NULL) + return (NULL); + + resource_list_init(&cd->cd_rl); + pc = pcpu_find(unit); + KASSERT(pc != NULL, ("pcpu_find failed")); + cd->cd_pcpu = pc; + + child = device_add_child_ordered(bus, order, name, unit); + if (child != NULL) { + pc->pc_device = child; + device_set_ivars(child, cd); + } else + free(cd, M_DEVBUF); + return (child); +} + +static struct resource_list * +cpu_get_rlist(device_t dev, device_t child) +{ + struct cpu_device *cpdev; + + cpdev = device_get_ivars(child); + return (&cpdev->cd_rl); +} + static int cpu_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) { - struct pcpu *pc; + struct cpu_device *cpdev; - if (index != 0) - return (ENOENT); - pc = device_get_ivars(child); - if (pc == NULL) + if (index != CPU_IVAR_PCPU) return (ENOENT); - *result = (uintptr_t)pc; + cpdev = device_get_ivars(dev); + *result = (uintptr_t)cpdev->cd_pcpu; return (0); } |