Index: sys/dev/acpica/acpi_throttle.c =================================================================== --- sys/dev/acpica/acpi_throttle.c (revision 224041) +++ sys/dev/acpica/acpi_throttle.c (working copy) @@ -59,7 +59,7 @@ struct acpi_throttle_softc { ACPI_HANDLE cpu_handle; 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 */ + void *cpu_p_cnt; /* Throttling control register */ int cpu_p_type; /* Resource type for cpu_p_cnt. */ uint32_t cpu_thr_state; /* Current throttle setting. */ }; @@ -278,11 +278,14 @@ acpi_throttle_evaluate(struct acpi_throttle_softc return (ENXIO); } memcpy(&gas, obj.Buffer.Pointer + 3, sizeof(gas)); - acpi_bus_alloc_gas(sc->cpu_dev, &sc->cpu_p_type, &thr_rid, - &gas, &sc->cpu_p_cnt, 0); - if (sc->cpu_p_cnt != NULL && bootverbose) { - device_printf(sc->cpu_dev, "P_CNT from _PTC %#jx\n", - gas.Address); + + /* XXX We don't support FFixedHW yet. */ + if (gas.SpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE) { + acpi_bus_alloc_gas(sc->cpu_dev, &sc->cpu_p_type, + &thr_rid, &gas, &sc->cpu_p_cnt, 0); + if (sc->cpu_p_cnt != NULL && bootverbose) + device_printf(sc->cpu_dev, + "P_CNT from _PTC %#jx\n", gas.Address); } } Index: sys/dev/acpica/acpi.c =================================================================== --- sys/dev/acpica/acpi.c (revision 224041) +++ sys/dev/acpica/acpi.c (working copy) @@ -1392,8 +1392,9 @@ acpi_delete_resource(device_t bus, device_t child, /* 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, - struct resource **res, u_int flags) + void **res, u_int flags) { + struct acpi_ffh *ffh; int error, res_type; error = ENOMEM; @@ -1408,10 +1409,26 @@ acpi_bus_alloc_gas(device_t dev, int *type, int *r case ACPI_ADR_SPACE_SYSTEM_IO: res_type = SYS_RES_IOPORT; break; + case ACPI_ADR_SPACE_FIXED_HARDWARE: + res_type = ACPI_RES_FFH; + break; default: return (EOPNOTSUPP); } + if (res_type == ACPI_RES_FFH) { + ffh = malloc(sizeof(*ffh), M_ACPIDEV, M_NOWAIT); + if (ffh == NULL) + return (ENOMEM); + ffh->vendor = gas->BitWidth; + ffh->class = gas->BitOffset; + ffh->arg0 = gas->Address; + ffh->arg1 = gas->AccessWidth; + *type = res_type; + *res = ffh; + return (0); + } + /* * If the register width is less than 8, assume the BIOS author means * it is a bit field and just allocate a byte. @@ -1435,6 +1452,20 @@ acpi_bus_alloc_gas(device_t dev, int *type, int *r return (error); } +void +acpi_bus_release_gas(device_t dev, int type, int rid, void *res) +{ + + switch (type) { + case ACPI_RES_FFH: + free(res, M_ACPIDEV); + break; + default: + bus_release_resource(dev, type, rid, res); + bus_delete_resource(dev, type, rid); + } +} + /* Probe _HID and _CID for compatible ISA PNP ids. */ static uint32_t acpi_isa_get_logicalid(device_t dev) Index: sys/dev/acpica/acpi_cpu.c =================================================================== --- sys/dev/acpica/acpi_cpu.c (revision 224041) +++ sys/dev/acpica/acpi_cpu.c (working copy) @@ -46,6 +46,9 @@ __FBSDID("$FreeBSD$"); #include #if defined(__amd64__) || defined(__i386__) #include +#include +#include +#include #endif #include @@ -63,11 +66,12 @@ __FBSDID("$FreeBSD$"); ACPI_MODULE_NAME("PROCESSOR") struct acpi_cx { - struct resource *p_lvlx; /* Register to read to enter state. */ + void *p_lvlx; /* Register to read to enter state. */ uint32_t type; /* C1-3 (C4 and up treated as C3). */ uint32_t trans_lat; /* Transition latency (usec). */ uint32_t power; /* Power consumed (mW). */ int res_type; /* Resource type for p_lvlx. */ + int res_rid; /* Resource ID for p_lvlx. */ }; #define MAX_CX_STATES 8 @@ -82,6 +86,7 @@ struct acpi_cpu_softc { int cpu_cx_count; /* Number of valid Cx states. */ int cpu_prev_sleep;/* Last idle sleep duration. */ int cpu_features; /* Child driver supported features. */ + int cpu_cx_native; /* Use MONITOR/MWAIT for Cx. */ /* Runtime state. */ int cpu_non_c3; /* Index of lowest non-C3 state. */ u_int cpu_cx_stats[MAX_CX_STATES];/* Cx usage history. */ @@ -90,7 +95,6 @@ struct acpi_cpu_softc { struct sysctl_oid *cpu_sysctl_tree; int cpu_cx_lowest; char cpu_cx_supported[64]; - int cpu_rid; }; struct acpi_cpu_device { @@ -124,6 +128,25 @@ struct acpi_cpu_device { #define PIIX4_STOP_BREAK_MASK (PIIX4_BRLD_EN_IRQ0 | PIIX4_BRLD_EN_IRQ | PIIX4_BRLD_EN_IRQ8) #define PIIX4_PCNTRL_BST_EN (1<<10) +/* Vendor-specific functional fixed hardware */ + /* Vendor */ +#define FFH_VENDOR_GENERIC 0x00 /* Undefined */ +#define FFH_VENDOR_INTEL 0x01 /* Intel */ + /* Class */ +#define FFH_CLASS_C1_HALT 0x00 /* C1 (STI and HLT) */ +#define FFH_CLASS_C1_IO_HALT 0x01 /* C1 (I/0 then HLT) */ +#define FFH_CLASS_NATIVE 0x02 /* Native (MWAIT) */ + /* Arg1 */ +#define FFH_NATIVE_HW_COORD 0x01 /* Hardware coordination */ +#define FFH_NATIVE_CHECK_BM 0x02 /* Bus master avoidance */ + +/* CPUID 5h %ecx MWAIT extensions. */ +#define CPUID5_MWAIT_EXTENSION 0x00000001 /* Extension supported */ +#define CPUID5_MWAIT_INTR_BRK 0x00000002 /* Interrupt as break-event */ + +/* MWAIT extension. */ +#define MWAIT_INTR_BRK 0x00000001 /* Interrupt breaks MWAIT. */ + /* Platform hardware resource information. */ static uint32_t cpu_smi_cmd; /* Value to write to SMI_CMD. */ static uint8_t cpu_cst_cnt; /* Indicate we are _CST aware. */ @@ -338,7 +361,21 @@ acpi_cpu_attach(device_t dev) * so advertise this ourselves. Note this is not the same as independent * SMP control where each CPU can have different settings. */ - sc->cpu_features = ACPI_CAP_SMP_SAME | ACPI_CAP_SMP_SAME_C3; + sc->cpu_features = ACPI_CAP_C1_IO_HALT; + sc->cpu_features |= ACPI_CAP_SMP_SAME | ACPI_CAP_SMP_SAME_C3; +#if defined(__amd64__) || defined(__i386__) + /* + * We must support extension to break MWAIT by interrupt. + */ + if ((cpu_feature2 & CPUID2_MON) != 0 && cpu_high >= 5) { + u_int regs[4]; + do_cpuid(5, regs); + if ((regs[2] & (CPUID5_MWAIT_EXTENSION | CPUID5_MWAIT_INTR_BRK)) == + (CPUID5_MWAIT_EXTENSION | CPUID5_MWAIT_INTR_BRK)) + sc->cpu_features |= ACPI_CAP_SMP_C1_NATIVE | ACPI_CAP_SMP_C3_NATIVE; + sc->cpu_cx_native = TRUE; + } +#endif if (devclass_get_drivers(acpi_cpu_devclass, &drivers, &drv_count) == 0) { for (i = 0; i < drv_count; i++) { if (ACPI_GET_FEATURES(drivers[i], &features) == 0) @@ -610,13 +647,12 @@ acpi_cpu_generic_cx_probe(struct acpi_cpu_softc *s gas.BitWidth = 8; if (AcpiGbl_FADT.C2Latency <= 100) { gas.Address = sc->cpu_p_blk + 4; - acpi_bus_alloc_gas(sc->cpu_dev, &cx_ptr->res_type, &sc->cpu_rid, + cx_ptr->res_rid = 0; + acpi_bus_alloc_gas(sc->cpu_dev, &cx_ptr->res_type, &cx_ptr->res_rid, &gas, &cx_ptr->p_lvlx, RF_SHAREABLE); if (cx_ptr->p_lvlx != NULL) { - sc->cpu_rid++; cx_ptr->type = ACPI_STATE_C2; cx_ptr->trans_lat = AcpiGbl_FADT.C2Latency; - cx_ptr++; sc->cpu_cx_count++; } } @@ -626,13 +662,13 @@ acpi_cpu_generic_cx_probe(struct acpi_cpu_softc *s /* Validate and allocate resources for C3 (P_LVL3). */ if (AcpiGbl_FADT.C3Latency <= 1000 && !(cpu_quirks & CPU_QUIRK_NO_C3)) { gas.Address = sc->cpu_p_blk + 5; - acpi_bus_alloc_gas(sc->cpu_dev, &cx_ptr->res_type, &sc->cpu_rid, &gas, - &cx_ptr->p_lvlx, RF_SHAREABLE); + cx_ptr++; + cx_ptr->res_rid = 1; + acpi_bus_alloc_gas(sc->cpu_dev, &cx_ptr->res_type, &cx_ptr->res_rid, + &gas, &cx_ptr->p_lvlx, RF_SHAREABLE); if (cx_ptr->p_lvlx != NULL) { - sc->cpu_rid++; cx_ptr->type = ACPI_STATE_C3; cx_ptr->trans_lat = AcpiGbl_FADT.C3Latency; - cx_ptr++; sc->cpu_cx_count++; } } @@ -646,13 +682,15 @@ acpi_cpu_generic_cx_probe(struct acpi_cpu_softc *s static int acpi_cpu_cx_cst(struct acpi_cpu_softc *sc) { + ACPI_GENERIC_ADDRESS gas; struct acpi_cx *cx_ptr; + struct acpi_ffh *cx_ffh; ACPI_STATUS status; ACPI_BUFFER buf; ACPI_OBJECT *top; ACPI_OBJECT *pkg; uint32_t count; - int i; + int error, i; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); @@ -695,6 +733,7 @@ acpi_cpu_cx_cst(struct acpi_cpu_softc *sc) for (i = 0; i < count; i++) { pkg = &top->Package.Elements[i + 1]; if (!ACPI_PKG_VALID(pkg, 4) || + acpi_PkgGas(pkg, 0, &gas) != 0 || acpi_PkgInt32(pkg, 1, &cx_ptr->type) != 0 || acpi_PkgInt32(pkg, 2, &cx_ptr->trans_lat) != 0 || acpi_PkgInt32(pkg, 3, &cx_ptr->power) != 0) { @@ -702,7 +741,39 @@ acpi_cpu_cx_cst(struct acpi_cpu_softc *sc) device_printf(sc->cpu_dev, "skipping invalid Cx state package\n"); continue; } + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: Got C%d - %d latency\n", + device_get_unit(sc->cpu_dev), cx_ptr->type, cx_ptr->trans_lat)); + /* Free up any previous register. */ + if (cx_ptr->p_lvlx != NULL) + acpi_bus_release_gas(sc->cpu_dev, cx_ptr->res_type, cx_ptr->res_rid, + cx_ptr->p_lvlx); + + /* Allocate the control register. */ + cx_ptr->p_lvlx = NULL; + cx_ptr->res_rid = i; + error = acpi_bus_alloc_gas(sc->cpu_dev, &cx_ptr->res_type, + &cx_ptr->res_rid, &gas, &cx_ptr->p_lvlx, RF_SHAREABLE); + if (error != 0) { + device_printf(sc->cpu_dev, "failed to allocate resources\n"); + continue; + } + + /* Decode functional fixed hardware for Intel processors. */ + if (cx_ptr->res_type == ACPI_RES_FFH) { + cx_ffh = cx_ptr->p_lvlx; + if (!(cx_ffh->vendor == FFH_VENDOR_GENERIC || + (cx_ffh->vendor == FFH_VENDOR_INTEL && + (cx_ffh->class == FFH_CLASS_C1_IO_HALT || + cx_ffh->class == FFH_CLASS_NATIVE)))) { + acpi_bus_release_gas(sc->cpu_dev, cx_ptr->res_type, + cx_ptr->res_rid, cx_ptr->p_lvlx); + cx_ptr->p_lvlx = NULL; + device_printf(sc->cpu_dev, "skipping invalid FFixedHW\n"); + continue; + } + } + /* Validate the state to see if we should use it. */ switch (cx_ptr->type) { case ACPI_STATE_C1: @@ -724,28 +795,16 @@ acpi_cpu_cx_cst(struct acpi_cpu_softc *sc) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "acpi_cpu%d: C3[%d] not available.\n", device_get_unit(sc->cpu_dev), i)); + if (cx_ptr->p_lvlx != NULL) { + acpi_bus_release_gas(sc->cpu_dev, cx_ptr->res_type, + cx_ptr->res_rid, cx_ptr->p_lvlx); + cx_ptr->p_lvlx = NULL; + } continue; } break; } - -#ifdef notyet - /* Free up any previous register. */ - if (cx_ptr->p_lvlx != NULL) { - bus_release_resource(sc->cpu_dev, 0, 0, cx_ptr->p_lvlx); - cx_ptr->p_lvlx = NULL; - } -#endif - - /* Allocate the control register for C2 or C3. */ - acpi_PkgGas(sc->cpu_dev, pkg, 0, &cx_ptr->res_type, &sc->cpu_rid, - &cx_ptr->p_lvlx, RF_SHAREABLE); - if (cx_ptr->p_lvlx) { - sc->cpu_rid++; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "acpi_cpu%d: Got C%d - %d latency\n", - device_get_unit(sc->cpu_dev), cx_ptr->type, - cx_ptr->trans_lat)); + if (error == 0) { cx_ptr++; sc->cpu_cx_count++; } @@ -894,6 +953,78 @@ acpi_cpu_startup_cx(struct acpi_cpu_softc *sc) #endif } +#if defined(__amd64__) || defined(__i386__) +/* XXX Copied from machdep.c */ +#define STATE_RUNNING 0x0 +#define STATE_MWAIT 0x1 +#define STATE_SLEEPING 0x2 + +static void +acpi_cpu_mwait(u_int hints) +{ + int *state; + + state = (int *)PCPU_PTR(monitorbuf); + *state = STATE_MWAIT; + if (!sched_runnable()) { + cpu_monitor(state, 0, 0); + if (*state == STATE_MWAIT) + cpu_mwait(MWAIT_INTR_BRK, hints); + } + *state = STATE_SLEEPING; +} +#endif + +static void +acpi_cpu_idle_cx(struct acpi_cx *cx_ptr, int native) +{ + struct acpi_ffh *cx_ffh; + UINT32 dummy; + + if (cx_ptr->res_type == ACPI_RES_FFH) { + cx_ffh = cx_ptr->p_lvlx; + switch (cx_ffh->vendor) { + case FFH_VENDOR_GENERIC: + acpi_cpu_c1(); + return; + case FFH_VENDOR_INTEL: + switch (cx_ffh->class) { + case FFH_CLASS_C1_IO_HALT: + AcpiOsReadPort(cx_ffh->arg0, &dummy, 8); + acpi_cpu_c1(); + return; +#if defined(__amd64__) || defined(__i386__) + case FFH_CLASS_NATIVE: + if (native) { + acpi_cpu_mwait(cx_ffh->arg0); + return; + } + break; +#endif + } + break; + } + } + if (cx_ptr->type == ACPI_STATE_C1) + acpi_cpu_c1(); + else + CPU_GET_REG(cx_ptr->p_lvlx, 1); +} + +static __inline int +acpi_cpu_check_bm(struct acpi_cx *cx_ptr) +{ + struct acpi_ffh *cx_ffh; + + if (cx_ptr->res_type == ACPI_RES_FFH) { + cx_ffh = cx_ptr->p_lvlx; + if (cx_ffh->vendor == FFH_VENDOR_INTEL && + cx_ffh->class == FFH_CLASS_NATIVE) + return ((cx_ffh->arg1 & FFH_NATIVE_CHECK_BM) != 0); + } + return (1); +} + /* * Idle the CPU in the lowest state possible. This function is called with * interrupts disabled. Note that once it re-enables interrupts, a task @@ -938,22 +1069,26 @@ acpi_cpu_idle() } } + /* Select the next state. */ + cx_next = &sc->cpu_cx_states[cx_next_idx]; + /* * Check for bus master activity. If there was activity, clear * the bit and use the lowest non-C3 state. Note that the USB * driver polling for new devices keeps this bit set all the * time if USB is loaded. */ - if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) { + if (acpi_cpu_check_bm(cx_next) && + (cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) { AcpiReadBitRegister(ACPI_BITREG_BUS_MASTER_STATUS, &bm_active); if (bm_active != 0) { AcpiWriteBitRegister(ACPI_BITREG_BUS_MASTER_STATUS, 1); cx_next_idx = min(cx_next_idx, sc->cpu_non_c3); + cx_next = &sc->cpu_cx_states[cx_next_idx]; } } - /* Select the next state and update statistics. */ - cx_next = &sc->cpu_cx_states[cx_next_idx]; + /* Update statistics. */ sc->cpu_cx_stats[cx_next_idx]++; KASSERT(cx_next->type != ACPI_STATE_C0, ("acpi_cpu_idle: C0 sleep")); @@ -965,7 +1100,7 @@ acpi_cpu_idle() */ if (cx_next->type == ACPI_STATE_C1) { AcpiHwRead(&start_time, &AcpiGbl_FADT.XPmTimerBlock); - acpi_cpu_c1(); + acpi_cpu_idle_cx(cx_next, sc->cpu_cx_native); AcpiHwRead(&end_time, &AcpiGbl_FADT.XPmTimerBlock); end_time = PM_USEC(acpi_TimerDelta(end_time, start_time)); if (curthread->td_critnest == 0) @@ -993,7 +1128,7 @@ acpi_cpu_idle() * is the only reliable time source. */ AcpiHwRead(&start_time, &AcpiGbl_FADT.XPmTimerBlock); - CPU_GET_REG(cx_next->p_lvlx, 1); + acpi_cpu_idle_cx(cx_next, sc->cpu_cx_native); /* * Read the end time twice. Since it may take an arbitrary time Index: sys/dev/acpica/acpivar.h =================================================================== --- sys/dev/acpica/acpivar.h (revision 224041) +++ sys/dev/acpica/acpivar.h (working copy) @@ -82,6 +82,15 @@ struct acpi_softc { struct callout susp_force_to; /* Force suspend if no acks. */ }; +/* Vendor-specific functional fixed hardware */ +struct acpi_ffh { + uint8_t vendor; /* Vendor code (Intel = 0x01) */ + uint8_t class; /* Class code */ + uint64_t arg0; /* Arg0 */ + uint8_t arg1; /* Arg1 */ +}; +#define ACPI_RES_FFH 0x7f /* Resource type for FFixedHW (ACPI only) */ + struct acpi_device { /* ACPI ivars */ ACPI_HANDLE ad_handle; @@ -346,8 +355,9 @@ ACPI_STATUS acpi_Startup(void); void acpi_UserNotify(const char *subsystem, ACPI_HANDLE h, uint8_t notify); int acpi_bus_alloc_gas(device_t dev, int *type, int *rid, - ACPI_GENERIC_ADDRESS *gas, struct resource **res, - u_int flags); + ACPI_GENERIC_ADDRESS *gas, void **res, u_int flags); +void acpi_bus_release_gas(device_t dev, int type, int rid, + void *res); void acpi_walk_subtables(void *first, void *end, acpi_subtable_handler *handler, void *arg); BOOLEAN acpi_MatchHid(ACPI_HANDLE h, const char *hid); @@ -461,8 +471,8 @@ int acpi_acad_get_acline(int *); int acpi_PkgInt(ACPI_OBJECT *res, int idx, UINT64 *dst); int acpi_PkgInt32(ACPI_OBJECT *res, int idx, uint32_t *dst); int acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, size_t size); -int acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type, - int *rid, struct resource **dst, u_int flags); +int acpi_PkgGas(ACPI_OBJECT *res, int idx, + ACPI_GENERIC_ADDRESS *dst); ACPI_HANDLE acpi_GetReference(ACPI_HANDLE scope, ACPI_OBJECT *obj); /* Index: sys/dev/acpica/acpi_package.c =================================================================== --- sys/dev/acpica/acpi_package.c (revision 224041) +++ sys/dev/acpica/acpi_package.c (working copy) @@ -104,20 +104,17 @@ acpi_PkgStr(ACPI_OBJECT *res, int idx, void *dst, } int -acpi_PkgGas(device_t dev, ACPI_OBJECT *res, int idx, int *type, int *rid, - struct resource **dst, u_int flags) +acpi_PkgGas(ACPI_OBJECT *res, int idx, ACPI_GENERIC_ADDRESS *dst) { - ACPI_GENERIC_ADDRESS gas; - ACPI_OBJECT *obj; + ACPI_OBJECT *obj; - obj = &res->Package.Elements[idx]; - if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER || - obj->Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3) - return (EINVAL); + obj = &res->Package.Elements[idx]; + if (obj == NULL || obj->Type != ACPI_TYPE_BUFFER || + obj->Buffer.Length < sizeof(ACPI_GENERIC_ADDRESS) + 3) + return (EINVAL); - memcpy(&gas, obj->Buffer.Pointer + 3, sizeof(gas)); - - return (acpi_bus_alloc_gas(dev, type, rid, &gas, dst, flags)); + memcpy(dst, obj->Buffer.Pointer + 3, sizeof(*dst)); + return (0); } ACPI_HANDLE Index: sys/dev/acpica/acpi_perf.c =================================================================== --- sys/dev/acpica/acpi_perf.c (revision 224041) +++ sys/dev/acpica/acpi_perf.c (working copy) @@ -73,15 +73,16 @@ struct acpi_px { struct acpi_perf_softc { device_t dev; ACPI_HANDLE handle; - struct resource *perf_ctrl; /* Set new performance state. */ + void *perf_ctrl; /* Set new performance state. */ int perf_ctrl_type; /* Resource type for perf_ctrl. */ - struct resource *perf_status; /* Check that transition succeeded. */ + int perf_ctrl_rid; /* Resource ID for perf_ctrl. */ + void *perf_status; /* Check that transition succeeded. */ int perf_sts_type; /* Resource type for perf_status. */ + int perf_sts_rid; /* Resource ID for perf_status. */ struct acpi_px *px_states; /* ACPI perf states. */ uint32_t px_count; /* Total number of perf states. */ uint32_t px_max_avail; /* Lowest index state available. */ int px_curr_state; /* Active state index. */ - int px_rid; int info_only; /* Can we set new states? */ }; @@ -169,11 +170,10 @@ acpi_perf_identify(driver_t *driver, device_t pare static int acpi_perf_probe(device_t dev) { + ACPI_GENERIC_ADDRESS ctrl, stat; ACPI_HANDLE handle; ACPI_OBJECT *pkg; - struct resource *res; ACPI_BUFFER buf; - int error, rid, type; if (resource_disabled("acpi_perf", 0)) return (ENXIO); @@ -183,31 +183,23 @@ acpi_perf_probe(device_t dev) * "functional fixed hardware", we attach quietly since we will * only be providing information on settings to other drivers. */ - error = ENXIO; handle = acpi_get_handle(dev); buf.Pointer = NULL; buf.Length = ACPI_ALLOCATE_BUFFER; if (ACPI_FAILURE(AcpiEvaluateObject(handle, "_PCT", NULL, &buf))) - return (error); + return (ENXIO); pkg = (ACPI_OBJECT *)buf.Pointer; - if (ACPI_PKG_VALID(pkg, 2)) { - rid = 0; - error = acpi_PkgGas(dev, pkg, 0, &type, &rid, &res, 0); - switch (error) { - case 0: - bus_release_resource(dev, type, rid, res); - bus_delete_resource(dev, type, rid); - device_set_desc(dev, "ACPI CPU Frequency Control"); - break; - case EOPNOTSUPP: + if (ACPI_PKG_VALID(pkg, 2) && acpi_PkgGas(pkg, 0, &ctrl) == 0 && + acpi_PkgGas(pkg, 1, &stat) == 0) { + if (ctrl.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE || + stat.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE) { + /* FFixedHW is info only. */ device_quiet(dev); - error = 0; - break; - } + } else + device_set_desc(dev, "ACPI CPU Frequency Control"); } AcpiOsFree(buf.Pointer); - - return (error); + return (0); } static int @@ -240,6 +232,7 @@ acpi_perf_detach(device_t dev) static int acpi_perf_evaluate(device_t dev) { + ACPI_GENERIC_ADDRESS ctrl, stat; struct acpi_perf_softc *sc; ACPI_BUFFER buf; ACPI_OBJECT *pkg, *res; @@ -324,38 +317,35 @@ acpi_perf_evaluate(device_t dev) /* Check the package of two registers, each a Buffer in GAS format. */ pkg = (ACPI_OBJECT *)buf.Pointer; - if (!ACPI_PKG_VALID(pkg, 2)) { + if (!ACPI_PKG_VALID(pkg, 2) || acpi_PkgGas(pkg, 0, &ctrl) != 0 || + acpi_PkgGas(pkg, 1, &stat) != 0) { device_printf(dev, "invalid perf register package\n"); goto out; } - error = acpi_PkgGas(sc->dev, pkg, 0, &sc->perf_ctrl_type, &sc->px_rid, - &sc->perf_ctrl, 0); - if (error) { - /* - * If the register is of type FFixedHW, we can only return - * info, we can't get or set new settings. - */ - if (error == EOPNOTSUPP) { - sc->info_only = TRUE; - error = 0; - } else - device_printf(dev, "failed in PERF_CTL attach\n"); + /* + * If the register is of type FFixedHW, we can only return info, + * we can't get or set new settings. + */ + if (ctrl.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE || + stat.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE) { + sc->info_only = TRUE; + error = 0; goto out; } - sc->px_rid++; - - error = acpi_PkgGas(sc->dev, pkg, 1, &sc->perf_sts_type, &sc->px_rid, - &sc->perf_status, 0); - if (error) { - if (error == EOPNOTSUPP) { - sc->info_only = TRUE; - error = 0; - } else - device_printf(dev, "failed in PERF_STATUS attach\n"); + sc->perf_ctrl_rid = 0; + error = acpi_bus_alloc_gas(sc->dev, &sc->perf_ctrl_type, + &sc->perf_ctrl_rid, &ctrl, &sc->perf_ctrl, 0); + if (error != 0) { + device_printf(dev, "failed in PERF_CTL attach\n"); goto out; } - sc->px_rid++; + error = acpi_bus_alloc_gas(sc->dev, &sc->perf_sts_type, + &sc->perf_sts_rid, &stat, &sc->perf_status, 0); + if (error != 0) { + device_printf(dev, "failed in PERF_STATUS attach\n"); + goto out; + } /* Get our current limit and register for notifies. */ acpi_px_available(sc); @@ -370,18 +360,15 @@ out: sc->px_states = NULL; } if (sc->perf_ctrl) { - bus_release_resource(sc->dev, sc->perf_ctrl_type, 0, - sc->perf_ctrl); - bus_delete_resource(sc->dev, sc->perf_ctrl_type, 0); + acpi_bus_release_gas(sc->dev, sc->perf_ctrl_type, + sc->perf_ctrl_rid, sc->perf_ctrl); sc->perf_ctrl = NULL; } if (sc->perf_status) { - bus_release_resource(sc->dev, sc->perf_sts_type, 1, - sc->perf_status); - bus_delete_resource(sc->dev, sc->perf_sts_type, 1); + acpi_bus_release_gas(sc->dev, sc->perf_sts_type, + sc->perf_sts_rid, sc->perf_status); sc->perf_status = NULL; } - sc->px_rid = 0; sc->px_count = 0; } if (buf.Pointer)