17f606aceSMark Haywood /*
27f606aceSMark Haywood * CDDL HEADER START
37f606aceSMark Haywood *
47f606aceSMark Haywood * The contents of this file are subject to the terms of the
57f606aceSMark Haywood * Common Development and Distribution License (the "License").
67f606aceSMark Haywood * You may not use this file except in compliance with the License.
77f606aceSMark Haywood *
87f606aceSMark Haywood * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97f606aceSMark Haywood * or http://www.opensolaris.org/os/licensing.
107f606aceSMark Haywood * See the License for the specific language governing permissions
117f606aceSMark Haywood * and limitations under the License.
127f606aceSMark Haywood *
137f606aceSMark Haywood * When distributing Covered Code, include this CDDL HEADER in each
147f606aceSMark Haywood * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157f606aceSMark Haywood * If applicable, add the following below this CDDL HEADER, with the
167f606aceSMark Haywood * fields enclosed by brackets "[]" replaced with your own identifying
177f606aceSMark Haywood * information: Portions Copyright [yyyy] [name of copyright owner]
187f606aceSMark Haywood *
197f606aceSMark Haywood * CDDL HEADER END
207f606aceSMark Haywood */
217f606aceSMark Haywood /*
22*b3ffafc5Sjiang.liu@intel.com * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
237f606aceSMark Haywood */
247f606aceSMark Haywood
257f606aceSMark Haywood #include <sys/cpu_acpi.h>
269aa01d98SBill Holler #include <sys/cpu_idle.h>
2737d22dc0SAnup Pemmaiah #include <sys/dtrace.h>
2837d22dc0SAnup Pemmaiah #include <sys/sdt.h>
297f606aceSMark Haywood
307f606aceSMark Haywood /*
317f606aceSMark Haywood * List of the processor ACPI object types that are being used.
327f606aceSMark Haywood */
337f606aceSMark Haywood typedef enum cpu_acpi_obj {
347f606aceSMark Haywood PDC_OBJ = 0,
357f606aceSMark Haywood PCT_OBJ,
367f606aceSMark Haywood PSS_OBJ,
377f606aceSMark Haywood PSD_OBJ,
387f606aceSMark Haywood PPC_OBJ,
397f606aceSMark Haywood PTC_OBJ,
407f606aceSMark Haywood TSS_OBJ,
417f606aceSMark Haywood TSD_OBJ,
420e751525SEric Saxe TPC_OBJ,
4300f97612SMark Haywood CST_OBJ,
440e751525SEric Saxe CSD_OBJ,
457f606aceSMark Haywood } cpu_acpi_obj_t;
467f606aceSMark Haywood
477f606aceSMark Haywood /*
487f606aceSMark Haywood * Container to store object name.
497f606aceSMark Haywood * Other attributes can be added in the future as necessary.
507f606aceSMark Haywood */
517f606aceSMark Haywood typedef struct cpu_acpi_obj_attr {
527f606aceSMark Haywood char *name;
537f606aceSMark Haywood } cpu_acpi_obj_attr_t;
547f606aceSMark Haywood
557f606aceSMark Haywood /*
567f606aceSMark Haywood * List of object attributes.
577f606aceSMark Haywood * NOTE: Please keep the ordering of the list as same as cpu_acpi_obj_t.
587f606aceSMark Haywood */
597f606aceSMark Haywood static cpu_acpi_obj_attr_t cpu_acpi_obj_attrs[] = {
607f606aceSMark Haywood {"_PDC"},
617f606aceSMark Haywood {"_PCT"},
627f606aceSMark Haywood {"_PSS"},
637f606aceSMark Haywood {"_PSD"},
647f606aceSMark Haywood {"_PPC"},
657f606aceSMark Haywood {"_PTC"},
667f606aceSMark Haywood {"_TSS"},
677f606aceSMark Haywood {"_TSD"},
680e751525SEric Saxe {"_TPC"},
6900f97612SMark Haywood {"_CST"},
700e751525SEric Saxe {"_CSD"}
717f606aceSMark Haywood };
727f606aceSMark Haywood
737f606aceSMark Haywood /*
747f606aceSMark Haywood * Cache the ACPI CPU control data objects.
757f606aceSMark Haywood */
767f606aceSMark Haywood static int
cpu_acpi_cache_ctrl_regs(cpu_acpi_handle_t handle,cpu_acpi_obj_t objtype,cpu_acpi_ctrl_regs_t * regs)777f606aceSMark Haywood cpu_acpi_cache_ctrl_regs(cpu_acpi_handle_t handle, cpu_acpi_obj_t objtype,
787f606aceSMark Haywood cpu_acpi_ctrl_regs_t *regs)
797f606aceSMark Haywood {
8000f97612SMark Haywood ACPI_STATUS astatus;
817f606aceSMark Haywood ACPI_BUFFER abuf;
827f606aceSMark Haywood ACPI_OBJECT *obj;
837f606aceSMark Haywood AML_RESOURCE_GENERIC_REGISTER *greg;
847f606aceSMark Haywood int ret = -1;
857f606aceSMark Haywood int i;
867f606aceSMark Haywood
877f606aceSMark Haywood /*
887f606aceSMark Haywood * Fetch the control registers (if present) for the CPU node.
897f606aceSMark Haywood * Since they are optional, non-existence is not a failure
907f606aceSMark Haywood * (we just consider it a fixed hardware case).
917f606aceSMark Haywood */
927f606aceSMark Haywood abuf.Length = ACPI_ALLOCATE_BUFFER;
937f606aceSMark Haywood abuf.Pointer = NULL;
9400f97612SMark Haywood astatus = AcpiEvaluateObjectTyped(handle->cs_handle,
9500f97612SMark Haywood cpu_acpi_obj_attrs[objtype].name, NULL, &abuf, ACPI_TYPE_PACKAGE);
9600f97612SMark Haywood if (ACPI_FAILURE(astatus)) {
9700f97612SMark Haywood if (astatus == AE_NOT_FOUND) {
9800f97612SMark Haywood DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id,
9900f97612SMark Haywood int, objtype, int, astatus);
10000f97612SMark Haywood regs[0].cr_addrspace_id = ACPI_ADR_SPACE_FIXED_HARDWARE;
10100f97612SMark Haywood regs[1].cr_addrspace_id = ACPI_ADR_SPACE_FIXED_HARDWARE;
10200f97612SMark Haywood return (1);
10300f97612SMark Haywood }
10400f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating %s package "
10500f97612SMark Haywood "for CPU %d.", astatus, cpu_acpi_obj_attrs[objtype].name,
10600f97612SMark Haywood handle->cs_id);
10700f97612SMark Haywood goto out;
1087f606aceSMark Haywood }
1097f606aceSMark Haywood
1107f606aceSMark Haywood obj = abuf.Pointer;
1117f606aceSMark Haywood if (obj->Package.Count != 2) {
11200f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: %s package bad count %d for "
11300f97612SMark Haywood "CPU %d.", cpu_acpi_obj_attrs[objtype].name,
11400f97612SMark Haywood obj->Package.Count, handle->cs_id);
1157f606aceSMark Haywood goto out;
1167f606aceSMark Haywood }
1177f606aceSMark Haywood
1187f606aceSMark Haywood /*
1197f606aceSMark Haywood * Does the package look coherent?
1207f606aceSMark Haywood */
1217f606aceSMark Haywood for (i = 0; i < obj->Package.Count; i++) {
1227f606aceSMark Haywood if (obj->Package.Elements[i].Type != ACPI_TYPE_BUFFER) {
12300f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: Unexpected data in "
12400f97612SMark Haywood "%s package for CPU %d.",
12500f97612SMark Haywood cpu_acpi_obj_attrs[objtype].name,
12600f97612SMark Haywood handle->cs_id);
1277f606aceSMark Haywood goto out;
1287f606aceSMark Haywood }
1297f606aceSMark Haywood
1307f606aceSMark Haywood greg = (AML_RESOURCE_GENERIC_REGISTER *)
1317f606aceSMark Haywood obj->Package.Elements[i].Buffer.Pointer;
1327f606aceSMark Haywood if (greg->DescriptorType !=
1337f606aceSMark Haywood ACPI_RESOURCE_NAME_GENERIC_REGISTER) {
13400f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: %s package has format "
13500f97612SMark Haywood "error for CPU %d.",
13600f97612SMark Haywood cpu_acpi_obj_attrs[objtype].name,
13700f97612SMark Haywood handle->cs_id);
1387f606aceSMark Haywood goto out;
1397f606aceSMark Haywood }
1407f606aceSMark Haywood if (greg->ResourceLength !=
1417f606aceSMark Haywood ACPI_AML_SIZE_LARGE(AML_RESOURCE_GENERIC_REGISTER)) {
14200f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: %s package not right "
14300f97612SMark Haywood "size for CPU %d.",
14400f97612SMark Haywood cpu_acpi_obj_attrs[objtype].name,
14500f97612SMark Haywood handle->cs_id);
1467f606aceSMark Haywood goto out;
1477f606aceSMark Haywood }
1487f606aceSMark Haywood if (greg->AddressSpaceId != ACPI_ADR_SPACE_FIXED_HARDWARE &&
1497f606aceSMark Haywood greg->AddressSpaceId != ACPI_ADR_SPACE_SYSTEM_IO) {
15000f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_apci: %s contains unsupported "
15100f97612SMark Haywood "address space type %x for CPU %d.",
1527f606aceSMark Haywood cpu_acpi_obj_attrs[objtype].name,
15300f97612SMark Haywood greg->AddressSpaceId,
15400f97612SMark Haywood handle->cs_id);
1557f606aceSMark Haywood goto out;
1567f606aceSMark Haywood }
1577f606aceSMark Haywood }
1587f606aceSMark Haywood
1597f606aceSMark Haywood /*
1607f606aceSMark Haywood * Looks good!
1617f606aceSMark Haywood */
1627f606aceSMark Haywood for (i = 0; i < obj->Package.Count; i++) {
1637f606aceSMark Haywood greg = (AML_RESOURCE_GENERIC_REGISTER *)
1647f606aceSMark Haywood obj->Package.Elements[i].Buffer.Pointer;
1657f606aceSMark Haywood regs[i].cr_addrspace_id = greg->AddressSpaceId;
1667f606aceSMark Haywood regs[i].cr_width = greg->BitWidth;
1677f606aceSMark Haywood regs[i].cr_offset = greg->BitOffset;
1687f606aceSMark Haywood regs[i].cr_asize = greg->AccessSize;
1697f606aceSMark Haywood regs[i].cr_address = greg->Address;
1707f606aceSMark Haywood }
1717f606aceSMark Haywood ret = 0;
1727f606aceSMark Haywood out:
17300f97612SMark Haywood if (abuf.Pointer != NULL)
17400f97612SMark Haywood AcpiOsFree(abuf.Pointer);
1757f606aceSMark Haywood return (ret);
1767f606aceSMark Haywood }
1777f606aceSMark Haywood
1787f606aceSMark Haywood /*
1797f606aceSMark Haywood * Cache the ACPI _PCT data. The _PCT data defines the interface to use
1807f606aceSMark Haywood * when making power level transitions (i.e., system IO ports, fixed
1817f606aceSMark Haywood * hardware port, etc).
1827f606aceSMark Haywood */
1837f606aceSMark Haywood static int
cpu_acpi_cache_pct(cpu_acpi_handle_t handle)1847f606aceSMark Haywood cpu_acpi_cache_pct(cpu_acpi_handle_t handle)
1857f606aceSMark Haywood {
1867f606aceSMark Haywood cpu_acpi_pct_t *pct;
1877f606aceSMark Haywood int ret;
1887f606aceSMark Haywood
1897f606aceSMark Haywood CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PCT_CACHED);
1907f606aceSMark Haywood pct = &CPU_ACPI_PCT(handle)[0];
1917f606aceSMark Haywood if ((ret = cpu_acpi_cache_ctrl_regs(handle, PCT_OBJ, pct)) == 0)
1927f606aceSMark Haywood CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PCT_CACHED);
1937f606aceSMark Haywood return (ret);
1947f606aceSMark Haywood }
1957f606aceSMark Haywood
1967f606aceSMark Haywood /*
1977f606aceSMark Haywood * Cache the ACPI _PTC data. The _PTC data defines the interface to use
1987f606aceSMark Haywood * when making T-state transitions (i.e., system IO ports, fixed
1997f606aceSMark Haywood * hardware port, etc).
2007f606aceSMark Haywood */
2017f606aceSMark Haywood static int
cpu_acpi_cache_ptc(cpu_acpi_handle_t handle)2027f606aceSMark Haywood cpu_acpi_cache_ptc(cpu_acpi_handle_t handle)
2037f606aceSMark Haywood {
2047f606aceSMark Haywood cpu_acpi_ptc_t *ptc;
2057f606aceSMark Haywood int ret;
2067f606aceSMark Haywood
2077f606aceSMark Haywood CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PTC_CACHED);
2087f606aceSMark Haywood ptc = &CPU_ACPI_PTC(handle)[0];
2097f606aceSMark Haywood if ((ret = cpu_acpi_cache_ctrl_regs(handle, PTC_OBJ, ptc)) == 0)
2107f606aceSMark Haywood CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PTC_CACHED);
2117f606aceSMark Haywood return (ret);
2127f606aceSMark Haywood }
2137f606aceSMark Haywood
2147f606aceSMark Haywood /*
2157f606aceSMark Haywood * Cache the ACPI CPU state dependency data objects.
2167f606aceSMark Haywood */
2177f606aceSMark Haywood static int
cpu_acpi_cache_state_dependencies(cpu_acpi_handle_t handle,cpu_acpi_obj_t objtype,cpu_acpi_state_dependency_t * sd)2187f606aceSMark Haywood cpu_acpi_cache_state_dependencies(cpu_acpi_handle_t handle,
2197f606aceSMark Haywood cpu_acpi_obj_t objtype, cpu_acpi_state_dependency_t *sd)
2207f606aceSMark Haywood {
22100f97612SMark Haywood ACPI_STATUS astatus;
2227f606aceSMark Haywood ACPI_BUFFER abuf;
2237f606aceSMark Haywood ACPI_OBJECT *pkg, *elements;
2240e751525SEric Saxe int number;
2257f606aceSMark Haywood int ret = -1;
2267f606aceSMark Haywood
2270e751525SEric Saxe if (objtype == CSD_OBJ) {
2280e751525SEric Saxe number = 6;
2290e751525SEric Saxe } else {
2300e751525SEric Saxe number = 5;
2310e751525SEric Saxe }
2327f606aceSMark Haywood /*
2337f606aceSMark Haywood * Fetch the dependencies (if present) for the CPU node.
2347f606aceSMark Haywood * Since they are optional, non-existence is not a failure
2357f606aceSMark Haywood * (it's up to the caller to determine how to handle non-existence).
2367f606aceSMark Haywood */
2377f606aceSMark Haywood abuf.Length = ACPI_ALLOCATE_BUFFER;
2387f606aceSMark Haywood abuf.Pointer = NULL;
23900f97612SMark Haywood astatus = AcpiEvaluateObjectTyped(handle->cs_handle,
24000f97612SMark Haywood cpu_acpi_obj_attrs[objtype].name, NULL, &abuf, ACPI_TYPE_PACKAGE);
24100f97612SMark Haywood if (ACPI_FAILURE(astatus)) {
24200f97612SMark Haywood if (astatus == AE_NOT_FOUND) {
24300f97612SMark Haywood DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id,
24400f97612SMark Haywood int, objtype, int, astatus);
24500f97612SMark Haywood return (1);
24600f97612SMark Haywood }
24700f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating %s package "
24800f97612SMark Haywood "for CPU %d.", astatus, cpu_acpi_obj_attrs[objtype].name,
24900f97612SMark Haywood handle->cs_id);
25000f97612SMark Haywood goto out;
2517f606aceSMark Haywood }
2527f606aceSMark Haywood
2537f606aceSMark Haywood pkg = abuf.Pointer;
2540e751525SEric Saxe
2550e751525SEric Saxe if (((objtype != CSD_OBJ) && (pkg->Package.Count != 1)) ||
2560e751525SEric Saxe ((objtype == CSD_OBJ) && (pkg->Package.Count != 1) &&
2570e751525SEric Saxe (pkg->Package.Count != 2))) {
25800f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: %s unsupported package count %d "
25900f97612SMark Haywood "for CPU %d.", cpu_acpi_obj_attrs[objtype].name,
26000f97612SMark Haywood pkg->Package.Count, handle->cs_id);
2617f606aceSMark Haywood goto out;
2627f606aceSMark Haywood }
2637f606aceSMark Haywood
2640e751525SEric Saxe /*
2650e751525SEric Saxe * For C-state domain, we assume C2 and C3 have the same
2660e751525SEric Saxe * domain information
2670e751525SEric Saxe */
2687f606aceSMark Haywood if (pkg->Package.Elements[0].Type != ACPI_TYPE_PACKAGE ||
2690e751525SEric Saxe pkg->Package.Elements[0].Package.Count != number) {
27000f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: Unexpected data in %s package "
27100f97612SMark Haywood "for CPU %d.", cpu_acpi_obj_attrs[objtype].name,
27200f97612SMark Haywood handle->cs_id);
2737f606aceSMark Haywood goto out;
2747f606aceSMark Haywood }
2757f606aceSMark Haywood elements = pkg->Package.Elements[0].Package.Elements;
2760e751525SEric Saxe if (elements[0].Integer.Value != number ||
2770e751525SEric Saxe elements[1].Integer.Value != 0) {
27800f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: Unexpected %s revision for "
27900f97612SMark Haywood "CPU %d.", cpu_acpi_obj_attrs[objtype].name,
28000f97612SMark Haywood handle->cs_id);
2817f606aceSMark Haywood goto out;
2827f606aceSMark Haywood }
2837f606aceSMark Haywood
2847f606aceSMark Haywood sd->sd_entries = elements[0].Integer.Value;
2857f606aceSMark Haywood sd->sd_revision = elements[1].Integer.Value;
2867f606aceSMark Haywood sd->sd_domain = elements[2].Integer.Value;
2877f606aceSMark Haywood sd->sd_type = elements[3].Integer.Value;
2887f606aceSMark Haywood sd->sd_num = elements[4].Integer.Value;
2890e751525SEric Saxe if (objtype == CSD_OBJ) {
2900e751525SEric Saxe sd->sd_index = elements[5].Integer.Value;
2910e751525SEric Saxe }
2927f606aceSMark Haywood
2937f606aceSMark Haywood ret = 0;
2947f606aceSMark Haywood out:
29500f97612SMark Haywood if (abuf.Pointer != NULL)
29600f97612SMark Haywood AcpiOsFree(abuf.Pointer);
2977f606aceSMark Haywood return (ret);
2987f606aceSMark Haywood }
2997f606aceSMark Haywood
3007f606aceSMark Haywood /*
3017f606aceSMark Haywood * Cache the ACPI _PSD data. The _PSD data defines P-state CPU dependencies
3027f606aceSMark Haywood * (think CPU domains).
3037f606aceSMark Haywood */
3047f606aceSMark Haywood static int
cpu_acpi_cache_psd(cpu_acpi_handle_t handle)3057f606aceSMark Haywood cpu_acpi_cache_psd(cpu_acpi_handle_t handle)
3067f606aceSMark Haywood {
3077f606aceSMark Haywood cpu_acpi_psd_t *psd;
3087f606aceSMark Haywood int ret;
3097f606aceSMark Haywood
3107f606aceSMark Haywood CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PSD_CACHED);
3117f606aceSMark Haywood psd = &CPU_ACPI_PSD(handle);
3127f606aceSMark Haywood ret = cpu_acpi_cache_state_dependencies(handle, PSD_OBJ, psd);
3137f606aceSMark Haywood if (ret == 0)
3147f606aceSMark Haywood CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PSD_CACHED);
3157f606aceSMark Haywood return (ret);
3167f606aceSMark Haywood
3177f606aceSMark Haywood }
3187f606aceSMark Haywood
3197f606aceSMark Haywood /*
3207f606aceSMark Haywood * Cache the ACPI _TSD data. The _TSD data defines T-state CPU dependencies
3217f606aceSMark Haywood * (think CPU domains).
3227f606aceSMark Haywood */
3237f606aceSMark Haywood static int
cpu_acpi_cache_tsd(cpu_acpi_handle_t handle)3247f606aceSMark Haywood cpu_acpi_cache_tsd(cpu_acpi_handle_t handle)
3257f606aceSMark Haywood {
3267f606aceSMark Haywood cpu_acpi_tsd_t *tsd;
3277f606aceSMark Haywood int ret;
3287f606aceSMark Haywood
3297f606aceSMark Haywood CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_TSD_CACHED);
3307f606aceSMark Haywood tsd = &CPU_ACPI_TSD(handle);
3317f606aceSMark Haywood ret = cpu_acpi_cache_state_dependencies(handle, TSD_OBJ, tsd);
3327f606aceSMark Haywood if (ret == 0)
3337f606aceSMark Haywood CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_TSD_CACHED);
3347f606aceSMark Haywood return (ret);
3357f606aceSMark Haywood
3367f606aceSMark Haywood }
3377f606aceSMark Haywood
3380e751525SEric Saxe /*
3390e751525SEric Saxe * Cache the ACPI _CSD data. The _CSD data defines C-state CPU dependencies
3400e751525SEric Saxe * (think CPU domains).
3410e751525SEric Saxe */
3420e751525SEric Saxe static int
cpu_acpi_cache_csd(cpu_acpi_handle_t handle)3430e751525SEric Saxe cpu_acpi_cache_csd(cpu_acpi_handle_t handle)
3440e751525SEric Saxe {
3450e751525SEric Saxe cpu_acpi_csd_t *csd;
3460e751525SEric Saxe int ret;
3470e751525SEric Saxe
3480e751525SEric Saxe CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_CSD_CACHED);
3490e751525SEric Saxe csd = &CPU_ACPI_CSD(handle);
3500e751525SEric Saxe ret = cpu_acpi_cache_state_dependencies(handle, CSD_OBJ, csd);
3510e751525SEric Saxe if (ret == 0)
3520e751525SEric Saxe CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_CSD_CACHED);
3530e751525SEric Saxe return (ret);
3540e751525SEric Saxe
3550e751525SEric Saxe }
3560e751525SEric Saxe
3577f606aceSMark Haywood static void
cpu_acpi_cache_pstate(cpu_acpi_handle_t handle,ACPI_OBJECT * obj,int cnt)3587f606aceSMark Haywood cpu_acpi_cache_pstate(cpu_acpi_handle_t handle, ACPI_OBJECT *obj, int cnt)
3597f606aceSMark Haywood {
3607f606aceSMark Haywood cpu_acpi_pstate_t *pstate;
3617f606aceSMark Haywood ACPI_OBJECT *q, *l;
3627f606aceSMark Haywood int i, j;
3637f606aceSMark Haywood
3647f606aceSMark Haywood CPU_ACPI_PSTATES_COUNT(handle) = cnt;
3657f606aceSMark Haywood CPU_ACPI_PSTATES(handle) = kmem_zalloc(CPU_ACPI_PSTATES_SIZE(cnt),
3667f606aceSMark Haywood KM_SLEEP);
3677f606aceSMark Haywood pstate = (cpu_acpi_pstate_t *)CPU_ACPI_PSTATES(handle);
3687f606aceSMark Haywood for (i = 0, l = NULL; i < obj->Package.Count && cnt > 0; i++, l = q) {
3697f606aceSMark Haywood uint32_t *up;
3707f606aceSMark Haywood
3717f606aceSMark Haywood q = obj->Package.Elements[i].Package.Elements;
3727f606aceSMark Haywood
3737f606aceSMark Haywood /*
3747f606aceSMark Haywood * Skip duplicate entries.
3757f606aceSMark Haywood */
3767f606aceSMark Haywood if (l != NULL && l[0].Integer.Value == q[0].Integer.Value)
3777f606aceSMark Haywood continue;
3787f606aceSMark Haywood
3797f606aceSMark Haywood up = (uint32_t *)pstate;
3807f606aceSMark Haywood for (j = 0; j < CPU_ACPI_PSS_CNT; j++)
3817f606aceSMark Haywood up[j] = q[j].Integer.Value;
3827f606aceSMark Haywood pstate++;
3837f606aceSMark Haywood cnt--;
3847f606aceSMark Haywood }
3857f606aceSMark Haywood }
3867f606aceSMark Haywood
3877f606aceSMark Haywood static void
cpu_acpi_cache_tstate(cpu_acpi_handle_t handle,ACPI_OBJECT * obj,int cnt)3887f606aceSMark Haywood cpu_acpi_cache_tstate(cpu_acpi_handle_t handle, ACPI_OBJECT *obj, int cnt)
3897f606aceSMark Haywood {
3907f606aceSMark Haywood cpu_acpi_tstate_t *tstate;
3917f606aceSMark Haywood ACPI_OBJECT *q, *l;
3927f606aceSMark Haywood int i, j;
3937f606aceSMark Haywood
3947f606aceSMark Haywood CPU_ACPI_TSTATES_COUNT(handle) = cnt;
3957f606aceSMark Haywood CPU_ACPI_TSTATES(handle) = kmem_zalloc(CPU_ACPI_TSTATES_SIZE(cnt),
3967f606aceSMark Haywood KM_SLEEP);
3977f606aceSMark Haywood tstate = (cpu_acpi_tstate_t *)CPU_ACPI_TSTATES(handle);
3987f606aceSMark Haywood for (i = 0, l = NULL; i < obj->Package.Count && cnt > 0; i++, l = q) {
3997f606aceSMark Haywood uint32_t *up;
4007f606aceSMark Haywood
4017f606aceSMark Haywood q = obj->Package.Elements[i].Package.Elements;
4027f606aceSMark Haywood
4037f606aceSMark Haywood /*
4047f606aceSMark Haywood * Skip duplicate entries.
4057f606aceSMark Haywood */
4067f606aceSMark Haywood if (l != NULL && l[0].Integer.Value == q[0].Integer.Value)
4077f606aceSMark Haywood continue;
4087f606aceSMark Haywood
4097f606aceSMark Haywood up = (uint32_t *)tstate;
4107f606aceSMark Haywood for (j = 0; j < CPU_ACPI_TSS_CNT; j++)
4117f606aceSMark Haywood up[j] = q[j].Integer.Value;
4127f606aceSMark Haywood tstate++;
4137f606aceSMark Haywood cnt--;
4147f606aceSMark Haywood }
4157f606aceSMark Haywood }
4167f606aceSMark Haywood
4177f606aceSMark Haywood /*
4187f606aceSMark Haywood * Cache the _PSS or _TSS data.
4197f606aceSMark Haywood */
4207f606aceSMark Haywood static int
cpu_acpi_cache_supported_states(cpu_acpi_handle_t handle,cpu_acpi_obj_t objtype,int fcnt)4217f606aceSMark Haywood cpu_acpi_cache_supported_states(cpu_acpi_handle_t handle,
4227f606aceSMark Haywood cpu_acpi_obj_t objtype, int fcnt)
4237f606aceSMark Haywood {
42400f97612SMark Haywood ACPI_STATUS astatus;
4257f606aceSMark Haywood ACPI_BUFFER abuf;
4267f606aceSMark Haywood ACPI_OBJECT *obj, *q, *l;
4277f606aceSMark Haywood boolean_t eot = B_FALSE;
4287f606aceSMark Haywood int ret = -1;
4297f606aceSMark Haywood int cnt;
4307f606aceSMark Haywood int i, j;
4317f606aceSMark Haywood
4327f606aceSMark Haywood /*
43300f97612SMark Haywood * Fetch the state data (if present) for the CPU node.
4347f606aceSMark Haywood */
4357f606aceSMark Haywood abuf.Length = ACPI_ALLOCATE_BUFFER;
4367f606aceSMark Haywood abuf.Pointer = NULL;
43700f97612SMark Haywood astatus = AcpiEvaluateObjectTyped(handle->cs_handle,
4387f606aceSMark Haywood cpu_acpi_obj_attrs[objtype].name, NULL, &abuf,
43900f97612SMark Haywood ACPI_TYPE_PACKAGE);
44000f97612SMark Haywood if (ACPI_FAILURE(astatus)) {
44100f97612SMark Haywood if (astatus == AE_NOT_FOUND) {
44200f97612SMark Haywood DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id,
44300f97612SMark Haywood int, objtype, int, astatus);
44400f97612SMark Haywood return (1);
44500f97612SMark Haywood }
44600f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating %s package "
44700f97612SMark Haywood "for CPU %d.", astatus, cpu_acpi_obj_attrs[objtype].name,
44800f97612SMark Haywood handle->cs_id);
44900f97612SMark Haywood goto out;
4507f606aceSMark Haywood }
4517f606aceSMark Haywood obj = abuf.Pointer;
4527f606aceSMark Haywood if (obj->Package.Count < 2) {
45300f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: %s package bad count %d for "
45400f97612SMark Haywood "CPU %d.", cpu_acpi_obj_attrs[objtype].name,
45500f97612SMark Haywood obj->Package.Count, handle->cs_id);
4567f606aceSMark Haywood goto out;
4577f606aceSMark Haywood }
4587f606aceSMark Haywood
4597f606aceSMark Haywood /*
4607f606aceSMark Haywood * Does the package look coherent?
4617f606aceSMark Haywood */
4627f606aceSMark Haywood cnt = 0;
4637f606aceSMark Haywood for (i = 0, l = NULL; i < obj->Package.Count; i++, l = q) {
4647f606aceSMark Haywood if (obj->Package.Elements[i].Type != ACPI_TYPE_PACKAGE ||
4657f606aceSMark Haywood obj->Package.Elements[i].Package.Count != fcnt) {
46600f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: Unexpected data in "
46700f97612SMark Haywood "%s package for CPU %d.",
46800f97612SMark Haywood cpu_acpi_obj_attrs[objtype].name,
46900f97612SMark Haywood handle->cs_id);
4707f606aceSMark Haywood goto out;
4717f606aceSMark Haywood }
4727f606aceSMark Haywood
4737f606aceSMark Haywood q = obj->Package.Elements[i].Package.Elements;
4747f606aceSMark Haywood for (j = 0; j < fcnt; j++) {
4757f606aceSMark Haywood if (q[j].Type != ACPI_TYPE_INTEGER) {
47600f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: %s element "
47700f97612SMark Haywood "invalid (type) for CPU %d.",
47800f97612SMark Haywood cpu_acpi_obj_attrs[objtype].name,
47900f97612SMark Haywood handle->cs_id);
4807f606aceSMark Haywood goto out;
4817f606aceSMark Haywood }
4827f606aceSMark Haywood }
4837f606aceSMark Haywood
4847f606aceSMark Haywood /*
4857f606aceSMark Haywood * Ignore duplicate entries.
4867f606aceSMark Haywood */
4877f606aceSMark Haywood if (l != NULL && l[0].Integer.Value == q[0].Integer.Value)
4887f606aceSMark Haywood continue;
4897f606aceSMark Haywood
4907f606aceSMark Haywood /*
4917f606aceSMark Haywood * Some supported state tables are larger than required
4927f606aceSMark Haywood * and unused elements are filled with patterns
4937f606aceSMark Haywood * of 0xff. Simply check here for frequency = 0xffff
4947f606aceSMark Haywood * and stop counting if found.
4957f606aceSMark Haywood */
4967f606aceSMark Haywood if (q[0].Integer.Value == 0xffff) {
4977f606aceSMark Haywood eot = B_TRUE;
4987f606aceSMark Haywood continue;
4997f606aceSMark Haywood }
5007f606aceSMark Haywood
5017f606aceSMark Haywood /*
5027f606aceSMark Haywood * We should never find a valid entry after we've hit
5037f606aceSMark Haywood * an the end-of-table entry.
5047f606aceSMark Haywood */
5057f606aceSMark Haywood if (eot) {
50600f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: Unexpected data in %s "
50700f97612SMark Haywood "package after eot for CPU %d.",
50800f97612SMark Haywood cpu_acpi_obj_attrs[objtype].name,
50900f97612SMark Haywood handle->cs_id);
5107f606aceSMark Haywood goto out;
5117f606aceSMark Haywood }
5127f606aceSMark Haywood
5137f606aceSMark Haywood /*
5147f606aceSMark Haywood * states must be defined in order from highest to lowest.
5157f606aceSMark Haywood */
5167f606aceSMark Haywood if (l != NULL && l[0].Integer.Value < q[0].Integer.Value) {
51700f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: %s package state "
51800f97612SMark Haywood "definitions out of order for CPU %d.",
51900f97612SMark Haywood cpu_acpi_obj_attrs[objtype].name,
52000f97612SMark Haywood handle->cs_id);
5217f606aceSMark Haywood goto out;
5227f606aceSMark Haywood }
5237f606aceSMark Haywood
5247f606aceSMark Haywood /*
5257f606aceSMark Haywood * This entry passes.
5267f606aceSMark Haywood */
5277f606aceSMark Haywood cnt++;
5287f606aceSMark Haywood }
5297f606aceSMark Haywood if (cnt == 0)
5307f606aceSMark Haywood goto out;
5317f606aceSMark Haywood
5327f606aceSMark Haywood /*
5337f606aceSMark Haywood * Yes, fill in the structure.
5347f606aceSMark Haywood */
5357f606aceSMark Haywood ASSERT(objtype == PSS_OBJ || objtype == TSS_OBJ);
5367f606aceSMark Haywood (objtype == PSS_OBJ) ? cpu_acpi_cache_pstate(handle, obj, cnt) :
5377f606aceSMark Haywood cpu_acpi_cache_tstate(handle, obj, cnt);
5387f606aceSMark Haywood
5397f606aceSMark Haywood ret = 0;
5407f606aceSMark Haywood out:
54100f97612SMark Haywood if (abuf.Pointer != NULL)
54200f97612SMark Haywood AcpiOsFree(abuf.Pointer);
5437f606aceSMark Haywood return (ret);
5447f606aceSMark Haywood }
5457f606aceSMark Haywood
5467f606aceSMark Haywood /*
5477f606aceSMark Haywood * Cache the _PSS data. The _PSS data defines the different power levels
5487f606aceSMark Haywood * supported by the CPU and the attributes associated with each power level
5497f606aceSMark Haywood * (i.e., frequency, voltage, etc.). The power levels are number from
5507f606aceSMark Haywood * highest to lowest. That is, the highest power level is _PSS entry 0
5517f606aceSMark Haywood * and the lowest power level is the last _PSS entry.
5527f606aceSMark Haywood */
5537f606aceSMark Haywood static int
cpu_acpi_cache_pstates(cpu_acpi_handle_t handle)5547f606aceSMark Haywood cpu_acpi_cache_pstates(cpu_acpi_handle_t handle)
5557f606aceSMark Haywood {
5567f606aceSMark Haywood int ret;
5577f606aceSMark Haywood
5587f606aceSMark Haywood CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PSS_CACHED);
5597f606aceSMark Haywood ret = cpu_acpi_cache_supported_states(handle, PSS_OBJ,
5607f606aceSMark Haywood CPU_ACPI_PSS_CNT);
5617f606aceSMark Haywood if (ret == 0)
5627f606aceSMark Haywood CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PSS_CACHED);
5637f606aceSMark Haywood return (ret);
5647f606aceSMark Haywood }
5657f606aceSMark Haywood
5667f606aceSMark Haywood /*
5677f606aceSMark Haywood * Cache the _TSS data. The _TSS data defines the different freq throttle
5687f606aceSMark Haywood * levels supported by the CPU and the attributes associated with each
5697f606aceSMark Haywood * throttle level (i.e., frequency throttle percentage, voltage, etc.).
5707f606aceSMark Haywood * The throttle levels are number from highest to lowest.
5717f606aceSMark Haywood */
5727f606aceSMark Haywood static int
cpu_acpi_cache_tstates(cpu_acpi_handle_t handle)5737f606aceSMark Haywood cpu_acpi_cache_tstates(cpu_acpi_handle_t handle)
5747f606aceSMark Haywood {
5757f606aceSMark Haywood int ret;
5767f606aceSMark Haywood
5777f606aceSMark Haywood CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_TSS_CACHED);
5787f606aceSMark Haywood ret = cpu_acpi_cache_supported_states(handle, TSS_OBJ,
5797f606aceSMark Haywood CPU_ACPI_TSS_CNT);
5807f606aceSMark Haywood if (ret == 0)
5817f606aceSMark Haywood CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_TSS_CACHED);
5827f606aceSMark Haywood return (ret);
5837f606aceSMark Haywood }
5847f606aceSMark Haywood
5857f606aceSMark Haywood /*
5867f606aceSMark Haywood * Cache the ACPI CPU present capabilities data objects.
5877f606aceSMark Haywood */
5887f606aceSMark Haywood static int
cpu_acpi_cache_present_capabilities(cpu_acpi_handle_t handle,cpu_acpi_obj_t objtype,cpu_acpi_present_capabilities_t * pc)5897f606aceSMark Haywood cpu_acpi_cache_present_capabilities(cpu_acpi_handle_t handle,
5907f606aceSMark Haywood cpu_acpi_obj_t objtype, cpu_acpi_present_capabilities_t *pc)
5917f606aceSMark Haywood
5927f606aceSMark Haywood {
59300f97612SMark Haywood ACPI_STATUS astatus;
5947f606aceSMark Haywood ACPI_BUFFER abuf;
5957f606aceSMark Haywood ACPI_OBJECT *obj;
59600f97612SMark Haywood int ret = -1;
5977f606aceSMark Haywood
5987f606aceSMark Haywood /*
5997f606aceSMark Haywood * Fetch the present capabilites object (if present) for the CPU node.
6007f606aceSMark Haywood */
6017f606aceSMark Haywood abuf.Length = ACPI_ALLOCATE_BUFFER;
6027f606aceSMark Haywood abuf.Pointer = NULL;
60300f97612SMark Haywood astatus = AcpiEvaluateObject(handle->cs_handle,
60400f97612SMark Haywood cpu_acpi_obj_attrs[objtype].name, NULL, &abuf);
60500f97612SMark Haywood if (ACPI_FAILURE(astatus) && astatus != AE_NOT_FOUND) {
60600f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating %s "
60700f97612SMark Haywood "package for CPU %d.", astatus,
60800f97612SMark Haywood cpu_acpi_obj_attrs[objtype].name, handle->cs_id);
60900f97612SMark Haywood goto out;
61000f97612SMark Haywood }
61100f97612SMark Haywood if (astatus == AE_NOT_FOUND || abuf.Length == 0) {
6127f606aceSMark Haywood *pc = 0;
6137f606aceSMark Haywood return (1);
6147f606aceSMark Haywood }
6157f606aceSMark Haywood
6167f606aceSMark Haywood obj = (ACPI_OBJECT *)abuf.Pointer;
6177f606aceSMark Haywood *pc = obj->Integer.Value;
61800f97612SMark Haywood
61900f97612SMark Haywood ret = 0;
62000f97612SMark Haywood out:
62100f97612SMark Haywood if (abuf.Pointer != NULL)
62200f97612SMark Haywood AcpiOsFree(abuf.Pointer);
62300f97612SMark Haywood return (ret);
6247f606aceSMark Haywood }
6257f606aceSMark Haywood
6267f606aceSMark Haywood /*
6277f606aceSMark Haywood * Cache the _PPC data. The _PPC simply contains an integer value which
6287f606aceSMark Haywood * represents the highest power level that a CPU should transition to.
6297f606aceSMark Haywood * That is, it's an index into the array of _PSS entries and will be
6307f606aceSMark Haywood * greater than or equal to zero.
6317f606aceSMark Haywood */
6327f606aceSMark Haywood void
cpu_acpi_cache_ppc(cpu_acpi_handle_t handle)6337f606aceSMark Haywood cpu_acpi_cache_ppc(cpu_acpi_handle_t handle)
6347f606aceSMark Haywood {
6357f606aceSMark Haywood cpu_acpi_ppc_t *ppc;
6367f606aceSMark Haywood int ret;
6377f606aceSMark Haywood
6387f606aceSMark Haywood CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_PPC_CACHED);
6397f606aceSMark Haywood ppc = &CPU_ACPI_PPC(handle);
6407f606aceSMark Haywood ret = cpu_acpi_cache_present_capabilities(handle, PPC_OBJ, ppc);
6417f606aceSMark Haywood if (ret == 0)
6427f606aceSMark Haywood CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_PPC_CACHED);
6437f606aceSMark Haywood }
6447f606aceSMark Haywood
6457f606aceSMark Haywood /*
6467f606aceSMark Haywood * Cache the _TPC data. The _TPC simply contains an integer value which
6477f606aceSMark Haywood * represents the throttle level that a CPU should transition to.
6487f606aceSMark Haywood * That is, it's an index into the array of _TSS entries and will be
6497f606aceSMark Haywood * greater than or equal to zero.
6507f606aceSMark Haywood */
6517f606aceSMark Haywood void
cpu_acpi_cache_tpc(cpu_acpi_handle_t handle)6527f606aceSMark Haywood cpu_acpi_cache_tpc(cpu_acpi_handle_t handle)
6537f606aceSMark Haywood {
6547f606aceSMark Haywood cpu_acpi_tpc_t *tpc;
6557f606aceSMark Haywood int ret;
6567f606aceSMark Haywood
6577f606aceSMark Haywood CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_TPC_CACHED);
6587f606aceSMark Haywood tpc = &CPU_ACPI_TPC(handle);
6597f606aceSMark Haywood ret = cpu_acpi_cache_present_capabilities(handle, TPC_OBJ, tpc);
6607f606aceSMark Haywood if (ret == 0)
6617f606aceSMark Haywood CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_TPC_CACHED);
6627f606aceSMark Haywood }
6637f606aceSMark Haywood
6640e751525SEric Saxe int
cpu_acpi_verify_cstate(cpu_acpi_cstate_t * cstate)6650e751525SEric Saxe cpu_acpi_verify_cstate(cpu_acpi_cstate_t *cstate)
6660e751525SEric Saxe {
6670e751525SEric Saxe uint32_t addrspaceid = cstate->cs_addrspace_id;
6680e751525SEric Saxe
6690e751525SEric Saxe if ((addrspaceid != ACPI_ADR_SPACE_FIXED_HARDWARE) &&
6700e751525SEric Saxe (addrspaceid != ACPI_ADR_SPACE_SYSTEM_IO)) {
67100f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: _CST unsupported address space id"
6720e751525SEric Saxe ":C%d, type: %d\n", cstate->cs_type, addrspaceid);
6730e751525SEric Saxe return (1);
6740e751525SEric Saxe }
6750e751525SEric Saxe return (0);
6760e751525SEric Saxe }
6770e751525SEric Saxe
6780e751525SEric Saxe int
cpu_acpi_cache_cst(cpu_acpi_handle_t handle)6790e751525SEric Saxe cpu_acpi_cache_cst(cpu_acpi_handle_t handle)
6800e751525SEric Saxe {
68100f97612SMark Haywood ACPI_STATUS astatus;
6820e751525SEric Saxe ACPI_BUFFER abuf;
6830e751525SEric Saxe ACPI_OBJECT *obj;
684*b3ffafc5Sjiang.liu@intel.com ACPI_INTEGER cnt, old_cnt;
6850e751525SEric Saxe cpu_acpi_cstate_t *cstate, *p;
686621e6c37SBill Holler size_t alloc_size;
6870e751525SEric Saxe int i, count;
68800f97612SMark Haywood int ret = 1;
6890e751525SEric Saxe
6900e751525SEric Saxe CPU_ACPI_OBJ_IS_NOT_CACHED(handle, CPU_ACPI_CST_CACHED);
6910e751525SEric Saxe
6920e751525SEric Saxe abuf.Length = ACPI_ALLOCATE_BUFFER;
6930e751525SEric Saxe abuf.Pointer = NULL;
6940e751525SEric Saxe
69500f97612SMark Haywood /*
69600f97612SMark Haywood * Fetch the C-state data (if present) for the CPU node.
69700f97612SMark Haywood */
69800f97612SMark Haywood astatus = AcpiEvaluateObjectTyped(handle->cs_handle, "_CST",
69900f97612SMark Haywood NULL, &abuf, ACPI_TYPE_PACKAGE);
70000f97612SMark Haywood if (ACPI_FAILURE(astatus)) {
70100f97612SMark Haywood if (astatus == AE_NOT_FOUND) {
70200f97612SMark Haywood DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id,
70300f97612SMark Haywood int, CST_OBJ, int, astatus);
70400f97612SMark Haywood return (1);
70500f97612SMark Haywood }
70600f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating _CST package "
70700f97612SMark Haywood "for CPU %d.", astatus, handle->cs_id);
70800f97612SMark Haywood goto out;
70900f97612SMark Haywood
7100e751525SEric Saxe }
7110e751525SEric Saxe obj = (ACPI_OBJECT *)abuf.Pointer;
7120e751525SEric Saxe if (obj->Package.Count < 2) {
71300f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: _CST unsupported package "
71400f97612SMark Haywood "count %d for CPU %d.", obj->Package.Count, handle->cs_id);
71500f97612SMark Haywood goto out;
7160e751525SEric Saxe }
7170e751525SEric Saxe
7180e751525SEric Saxe /*
7190e751525SEric Saxe * Does the package look coherent?
7200e751525SEric Saxe */
7210e751525SEric Saxe cnt = obj->Package.Elements[0].Integer.Value;
7220e751525SEric Saxe if (cnt < 1 || cnt != obj->Package.Count - 1) {
72300f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: _CST invalid element "
72400f97612SMark Haywood "count %d != Package count %d for CPU %d",
72500f97612SMark Haywood (int)cnt, (int)obj->Package.Count - 1, handle->cs_id);
72600f97612SMark Haywood goto out;
7270e751525SEric Saxe }
7280e751525SEric Saxe
729*b3ffafc5Sjiang.liu@intel.com /*
730*b3ffafc5Sjiang.liu@intel.com * Reuse the old buffer if the number of C states is the same.
731*b3ffafc5Sjiang.liu@intel.com */
732*b3ffafc5Sjiang.liu@intel.com if (CPU_ACPI_CSTATES(handle) &&
733*b3ffafc5Sjiang.liu@intel.com (old_cnt = CPU_ACPI_CSTATES_COUNT(handle)) != cnt) {
734*b3ffafc5Sjiang.liu@intel.com kmem_free(CPU_ACPI_CSTATES(handle),
735*b3ffafc5Sjiang.liu@intel.com CPU_ACPI_CSTATES_SIZE(old_cnt));
736*b3ffafc5Sjiang.liu@intel.com CPU_ACPI_CSTATES(handle) = NULL;
737*b3ffafc5Sjiang.liu@intel.com }
738*b3ffafc5Sjiang.liu@intel.com
7390e751525SEric Saxe CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)cnt;
740621e6c37SBill Holler alloc_size = CPU_ACPI_CSTATES_SIZE(cnt);
741a3114836SGerry Liu if (CPU_ACPI_CSTATES(handle) == NULL)
742a3114836SGerry Liu CPU_ACPI_CSTATES(handle) = kmem_zalloc(alloc_size, KM_SLEEP);
7430e751525SEric Saxe cstate = (cpu_acpi_cstate_t *)CPU_ACPI_CSTATES(handle);
7440e751525SEric Saxe p = cstate;
7450e751525SEric Saxe
7460e751525SEric Saxe for (i = 1, count = 1; i <= cnt; i++) {
7470e751525SEric Saxe ACPI_OBJECT *pkg;
7480e751525SEric Saxe AML_RESOURCE_GENERIC_REGISTER *reg;
7490e751525SEric Saxe ACPI_OBJECT *element;
7500e751525SEric Saxe
7510e751525SEric Saxe pkg = &(obj->Package.Elements[i]);
7520e751525SEric Saxe reg = (AML_RESOURCE_GENERIC_REGISTER *)
7530e751525SEric Saxe pkg->Package.Elements[0].Buffer.Pointer;
7540e751525SEric Saxe cstate->cs_addrspace_id = reg->AddressSpaceId;
7550e751525SEric Saxe cstate->cs_address = reg->Address;
7560e751525SEric Saxe element = &(pkg->Package.Elements[1]);
7570e751525SEric Saxe cstate->cs_type = element->Integer.Value;
7580e751525SEric Saxe element = &(pkg->Package.Elements[2]);
7590e751525SEric Saxe cstate->cs_latency = element->Integer.Value;
7600e751525SEric Saxe element = &(pkg->Package.Elements[3]);
7610e751525SEric Saxe cstate->cs_power = element->Integer.Value;
7620e751525SEric Saxe
7630e751525SEric Saxe if (cpu_acpi_verify_cstate(cstate)) {
7640e751525SEric Saxe /*
7650e751525SEric Saxe * ignore this entry if it's not valid
7660e751525SEric Saxe */
7670e751525SEric Saxe continue;
7680e751525SEric Saxe }
7690e751525SEric Saxe if (cstate == p) {
7700e751525SEric Saxe cstate++;
7710e751525SEric Saxe } else if (p->cs_type == cstate->cs_type) {
7720e751525SEric Saxe /*
7730e751525SEric Saxe * if there are duplicate entries, we keep the
7740e751525SEric Saxe * last one. This fixes:
7750e751525SEric Saxe * 1) some buggy BIOS have total duplicate entries.
7760e751525SEric Saxe * 2) ACPI Spec allows the same cstate entry with
7770e751525SEric Saxe * different power and latency, we use the one
7780e751525SEric Saxe * with more power saving.
7790e751525SEric Saxe */
7800e751525SEric Saxe (void) memcpy(p, cstate, sizeof (cpu_acpi_cstate_t));
7810e751525SEric Saxe } else {
7820e751525SEric Saxe /*
7830e751525SEric Saxe * we got a valid entry, cache it to the
7840e751525SEric Saxe * cstate structure
7850e751525SEric Saxe */
7860e751525SEric Saxe p = cstate++;
7870e751525SEric Saxe count++;
7880e751525SEric Saxe }
7890e751525SEric Saxe }
7900e751525SEric Saxe
7910e751525SEric Saxe if (count < 2) {
79200f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: _CST invalid count %d < 2 for "
79300f97612SMark Haywood "CPU %d", count, handle->cs_id);
794621e6c37SBill Holler kmem_free(CPU_ACPI_CSTATES(handle), alloc_size);
795621e6c37SBill Holler CPU_ACPI_CSTATES(handle) = NULL;
796621e6c37SBill Holler CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)0;
79700f97612SMark Haywood goto out;
7980e751525SEric Saxe }
7999aa01d98SBill Holler cstate = (cpu_acpi_cstate_t *)CPU_ACPI_CSTATES(handle);
8009aa01d98SBill Holler if (cstate[0].cs_type != CPU_ACPI_C1) {
80100f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: _CST first element type not "
80200f97612SMark Haywood "C1: %d for CPU %d", (int)cstate->cs_type, handle->cs_id);
803621e6c37SBill Holler kmem_free(CPU_ACPI_CSTATES(handle), alloc_size);
804621e6c37SBill Holler CPU_ACPI_CSTATES(handle) = NULL;
805621e6c37SBill Holler CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)0;
80600f97612SMark Haywood goto out;
8079aa01d98SBill Holler }
8080e751525SEric Saxe
809621e6c37SBill Holler if (count != cnt) {
810621e6c37SBill Holler void *orig = CPU_ACPI_CSTATES(handle);
811621e6c37SBill Holler
8120e751525SEric Saxe CPU_ACPI_CSTATES_COUNT(handle) = (uint32_t)count;
813621e6c37SBill Holler CPU_ACPI_CSTATES(handle) = kmem_zalloc(
814621e6c37SBill Holler CPU_ACPI_CSTATES_SIZE(count), KM_SLEEP);
815621e6c37SBill Holler (void) memcpy(CPU_ACPI_CSTATES(handle), orig,
816621e6c37SBill Holler CPU_ACPI_CSTATES_SIZE(count));
817621e6c37SBill Holler kmem_free(orig, alloc_size);
818621e6c37SBill Holler }
8190e751525SEric Saxe
8200e751525SEric Saxe CPU_ACPI_OBJ_IS_CACHED(handle, CPU_ACPI_CST_CACHED);
82100f97612SMark Haywood
82200f97612SMark Haywood ret = 0;
82300f97612SMark Haywood
82400f97612SMark Haywood out:
82500f97612SMark Haywood if (abuf.Pointer != NULL)
82600f97612SMark Haywood AcpiOsFree(abuf.Pointer);
82700f97612SMark Haywood return (ret);
8280e751525SEric Saxe }
8290e751525SEric Saxe
8307f606aceSMark Haywood /*
8317f606aceSMark Haywood * Cache the _PCT, _PSS, _PSD and _PPC data.
8327f606aceSMark Haywood */
8337f606aceSMark Haywood int
cpu_acpi_cache_pstate_data(cpu_acpi_handle_t handle)8347f606aceSMark Haywood cpu_acpi_cache_pstate_data(cpu_acpi_handle_t handle)
8357f606aceSMark Haywood {
8367f606aceSMark Haywood if (cpu_acpi_cache_pct(handle) < 0) {
83700f97612SMark Haywood DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
83800f97612SMark Haywood int, PCT_OBJ);
8397f606aceSMark Haywood return (-1);
8407f606aceSMark Haywood }
8417f606aceSMark Haywood
8427f606aceSMark Haywood if (cpu_acpi_cache_pstates(handle) != 0) {
84300f97612SMark Haywood DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
84400f97612SMark Haywood int, PSS_OBJ);
8457f606aceSMark Haywood return (-1);
8467f606aceSMark Haywood }
8477f606aceSMark Haywood
8487f606aceSMark Haywood if (cpu_acpi_cache_psd(handle) < 0) {
84900f97612SMark Haywood DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
85000f97612SMark Haywood int, PSD_OBJ);
8517f606aceSMark Haywood return (-1);
8527f606aceSMark Haywood }
8537f606aceSMark Haywood
8547f606aceSMark Haywood cpu_acpi_cache_ppc(handle);
8557f606aceSMark Haywood
8567f606aceSMark Haywood return (0);
8577f606aceSMark Haywood }
8587f606aceSMark Haywood
8597f606aceSMark Haywood void
cpu_acpi_free_pstate_data(cpu_acpi_handle_t handle)8607f606aceSMark Haywood cpu_acpi_free_pstate_data(cpu_acpi_handle_t handle)
8617f606aceSMark Haywood {
8627f606aceSMark Haywood if (handle != NULL) {
8637f606aceSMark Haywood if (CPU_ACPI_PSTATES(handle)) {
8647f606aceSMark Haywood kmem_free(CPU_ACPI_PSTATES(handle),
8657f606aceSMark Haywood CPU_ACPI_PSTATES_SIZE(
8667f606aceSMark Haywood CPU_ACPI_PSTATES_COUNT(handle)));
8677f606aceSMark Haywood CPU_ACPI_PSTATES(handle) = NULL;
8687f606aceSMark Haywood }
8697f606aceSMark Haywood }
8707f606aceSMark Haywood }
8717f606aceSMark Haywood
8727f606aceSMark Haywood /*
8737f606aceSMark Haywood * Cache the _PTC, _TSS, _TSD and _TPC data.
8747f606aceSMark Haywood */
8757f606aceSMark Haywood int
cpu_acpi_cache_tstate_data(cpu_acpi_handle_t handle)8767f606aceSMark Haywood cpu_acpi_cache_tstate_data(cpu_acpi_handle_t handle)
8777f606aceSMark Haywood {
87800f97612SMark Haywood int ret;
87937d22dc0SAnup Pemmaiah
8807f606aceSMark Haywood if (cpu_acpi_cache_ptc(handle) < 0) {
88100f97612SMark Haywood DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
88200f97612SMark Haywood int, PTC_OBJ);
8837f606aceSMark Haywood return (-1);
8847f606aceSMark Haywood }
8857f606aceSMark Haywood
88600f97612SMark Haywood if ((ret = cpu_acpi_cache_tstates(handle)) != 0) {
88700f97612SMark Haywood DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
88800f97612SMark Haywood int, TSS_OBJ);
88900f97612SMark Haywood return (ret);
8907f606aceSMark Haywood }
8917f606aceSMark Haywood
8927f606aceSMark Haywood if (cpu_acpi_cache_tsd(handle) < 0) {
89300f97612SMark Haywood DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
89400f97612SMark Haywood int, TSD_OBJ);
8957f606aceSMark Haywood return (-1);
8967f606aceSMark Haywood }
8977f606aceSMark Haywood
8987f606aceSMark Haywood cpu_acpi_cache_tpc(handle);
8997f606aceSMark Haywood
9007f606aceSMark Haywood return (0);
9017f606aceSMark Haywood }
9027f606aceSMark Haywood
9037f606aceSMark Haywood void
cpu_acpi_free_tstate_data(cpu_acpi_handle_t handle)9047f606aceSMark Haywood cpu_acpi_free_tstate_data(cpu_acpi_handle_t handle)
9057f606aceSMark Haywood {
9067f606aceSMark Haywood if (handle != NULL) {
9077f606aceSMark Haywood if (CPU_ACPI_TSTATES(handle)) {
9087f606aceSMark Haywood kmem_free(CPU_ACPI_TSTATES(handle),
9097f606aceSMark Haywood CPU_ACPI_TSTATES_SIZE(
9107f606aceSMark Haywood CPU_ACPI_TSTATES_COUNT(handle)));
9117f606aceSMark Haywood CPU_ACPI_TSTATES(handle) = NULL;
9127f606aceSMark Haywood }
9137f606aceSMark Haywood }
9147f606aceSMark Haywood }
9157f606aceSMark Haywood
9160e751525SEric Saxe /*
9170e751525SEric Saxe * Cache the _CST data.
9180e751525SEric Saxe */
9190e751525SEric Saxe int
cpu_acpi_cache_cstate_data(cpu_acpi_handle_t handle)9200e751525SEric Saxe cpu_acpi_cache_cstate_data(cpu_acpi_handle_t handle)
9210e751525SEric Saxe {
92200f97612SMark Haywood int ret;
92300f97612SMark Haywood
92400f97612SMark Haywood if ((ret = cpu_acpi_cache_cst(handle)) != 0) {
92500f97612SMark Haywood DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
92600f97612SMark Haywood int, CST_OBJ);
92700f97612SMark Haywood return (ret);
9280e751525SEric Saxe }
9290e751525SEric Saxe
9300e751525SEric Saxe if (cpu_acpi_cache_csd(handle) < 0) {
93100f97612SMark Haywood DTRACE_PROBE2(cpu_acpi__cache__err, int, handle->cs_id,
93200f97612SMark Haywood int, CSD_OBJ);
9330e751525SEric Saxe return (-1);
9340e751525SEric Saxe }
9350e751525SEric Saxe
9360e751525SEric Saxe return (0);
9370e751525SEric Saxe }
9380e751525SEric Saxe
9390e751525SEric Saxe void
cpu_acpi_free_cstate_data(cpu_acpi_handle_t handle)9400e751525SEric Saxe cpu_acpi_free_cstate_data(cpu_acpi_handle_t handle)
9410e751525SEric Saxe {
9420e751525SEric Saxe if (handle != NULL) {
9430e751525SEric Saxe if (CPU_ACPI_CSTATES(handle)) {
9440e751525SEric Saxe kmem_free(CPU_ACPI_CSTATES(handle),
9450e751525SEric Saxe CPU_ACPI_CSTATES_SIZE(
9460e751525SEric Saxe CPU_ACPI_CSTATES_COUNT(handle)));
9470e751525SEric Saxe CPU_ACPI_CSTATES(handle) = NULL;
9480e751525SEric Saxe }
9490e751525SEric Saxe }
9500e751525SEric Saxe }
9510e751525SEric Saxe
9527f606aceSMark Haywood /*
9537f606aceSMark Haywood * Register a handler for processor change notifications.
9547f606aceSMark Haywood */
9557f606aceSMark Haywood void
cpu_acpi_install_notify_handler(cpu_acpi_handle_t handle,ACPI_NOTIFY_HANDLER handler,void * ctx)9567f606aceSMark Haywood cpu_acpi_install_notify_handler(cpu_acpi_handle_t handle,
9570e751525SEric Saxe ACPI_NOTIFY_HANDLER handler, void *ctx)
9587f606aceSMark Haywood {
9597f606aceSMark Haywood if (ACPI_FAILURE(AcpiInstallNotifyHandler(handle->cs_handle,
9600e751525SEric Saxe ACPI_DEVICE_NOTIFY, handler, ctx)))
9617f606aceSMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: Unable to register "
96200f97612SMark Haywood "notify handler for CPU %d.", handle->cs_id);
9630e751525SEric Saxe }
9640e751525SEric Saxe
9650e751525SEric Saxe /*
9660e751525SEric Saxe * Remove a handler for processor change notifications.
9670e751525SEric Saxe */
9680e751525SEric Saxe void
cpu_acpi_remove_notify_handler(cpu_acpi_handle_t handle,ACPI_NOTIFY_HANDLER handler)9690e751525SEric Saxe cpu_acpi_remove_notify_handler(cpu_acpi_handle_t handle,
9700e751525SEric Saxe ACPI_NOTIFY_HANDLER handler)
9710e751525SEric Saxe {
9720e751525SEric Saxe if (ACPI_FAILURE(AcpiRemoveNotifyHandler(handle->cs_handle,
9730e751525SEric Saxe ACPI_DEVICE_NOTIFY, handler)))
9740e751525SEric Saxe cmn_err(CE_NOTE, "!cpu_acpi: Unable to remove "
97500f97612SMark Haywood "notify handler for CPU %d.", handle->cs_id);
9767f606aceSMark Haywood }
9777f606aceSMark Haywood
9787f606aceSMark Haywood /*
9797f606aceSMark Haywood * Write _PDC.
9807f606aceSMark Haywood */
9817f606aceSMark Haywood int
cpu_acpi_write_pdc(cpu_acpi_handle_t handle,uint32_t revision,uint32_t count,uint32_t * capabilities)9827f606aceSMark Haywood cpu_acpi_write_pdc(cpu_acpi_handle_t handle, uint32_t revision, uint32_t count,
9837f606aceSMark Haywood uint32_t *capabilities)
9847f606aceSMark Haywood {
98500f97612SMark Haywood ACPI_STATUS astatus;
9867f606aceSMark Haywood ACPI_OBJECT obj;
9877f606aceSMark Haywood ACPI_OBJECT_LIST list = { 1, &obj};
9887f606aceSMark Haywood uint32_t *buffer;
9897f606aceSMark Haywood uint32_t *bufptr;
9907f606aceSMark Haywood uint32_t bufsize;
9917f606aceSMark Haywood int i;
99200f97612SMark Haywood int ret = 0;
9937f606aceSMark Haywood
9947f606aceSMark Haywood bufsize = (count + 2) * sizeof (uint32_t);
9957f606aceSMark Haywood buffer = kmem_zalloc(bufsize, KM_SLEEP);
9967f606aceSMark Haywood buffer[0] = revision;
9977f606aceSMark Haywood buffer[1] = count;
9987f606aceSMark Haywood bufptr = &buffer[2];
9997f606aceSMark Haywood for (i = 0; i < count; i++)
10007f606aceSMark Haywood *bufptr++ = *capabilities++;
10017f606aceSMark Haywood
10027f606aceSMark Haywood obj.Type = ACPI_TYPE_BUFFER;
10037f606aceSMark Haywood obj.Buffer.Length = bufsize;
10047f606aceSMark Haywood obj.Buffer.Pointer = (void *)buffer;
10057f606aceSMark Haywood
10067f606aceSMark Haywood /*
100700f97612SMark Haywood * Fetch the ??? (if present) for the CPU node.
10087f606aceSMark Haywood */
100900f97612SMark Haywood astatus = AcpiEvaluateObject(handle->cs_handle, "_PDC", &list, NULL);
101000f97612SMark Haywood if (ACPI_FAILURE(astatus)) {
101100f97612SMark Haywood if (astatus == AE_NOT_FOUND) {
101200f97612SMark Haywood DTRACE_PROBE3(cpu_acpi__eval__err, int, handle->cs_id,
101300f97612SMark Haywood int, PDC_OBJ, int, astatus);
101400f97612SMark Haywood ret = 1;
101500f97612SMark Haywood } else {
101600f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: error %d evaluating _PDC "
101700f97612SMark Haywood "package for CPU %d.", astatus, handle->cs_id);
101800f97612SMark Haywood ret = -1;
101900f97612SMark Haywood }
10207f606aceSMark Haywood }
10217f606aceSMark Haywood
10227f606aceSMark Haywood kmem_free(buffer, bufsize);
102300f97612SMark Haywood return (ret);
10247f606aceSMark Haywood }
10257f606aceSMark Haywood
10267f606aceSMark Haywood /*
10277f606aceSMark Haywood * Write to system IO port.
10287f606aceSMark Haywood */
10297f606aceSMark Haywood int
cpu_acpi_write_port(ACPI_IO_ADDRESS address,uint32_t value,uint32_t width)10307f606aceSMark Haywood cpu_acpi_write_port(ACPI_IO_ADDRESS address, uint32_t value, uint32_t width)
10317f606aceSMark Haywood {
10327f606aceSMark Haywood if (ACPI_FAILURE(AcpiOsWritePort(address, value, width))) {
103300f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: error writing system IO port "
10347f606aceSMark Haywood "%lx.", (long)address);
10357f606aceSMark Haywood return (-1);
10367f606aceSMark Haywood }
10377f606aceSMark Haywood return (0);
10387f606aceSMark Haywood }
10397f606aceSMark Haywood
10407f606aceSMark Haywood /*
10417f606aceSMark Haywood * Read from a system IO port.
10427f606aceSMark Haywood */
10437f606aceSMark Haywood int
cpu_acpi_read_port(ACPI_IO_ADDRESS address,uint32_t * value,uint32_t width)10447f606aceSMark Haywood cpu_acpi_read_port(ACPI_IO_ADDRESS address, uint32_t *value, uint32_t width)
10457f606aceSMark Haywood {
10467f606aceSMark Haywood if (ACPI_FAILURE(AcpiOsReadPort(address, value, width))) {
104700f97612SMark Haywood cmn_err(CE_NOTE, "!cpu_acpi: error reading system IO port "
10487f606aceSMark Haywood "%lx.", (long)address);
10497f606aceSMark Haywood return (-1);
10507f606aceSMark Haywood }
10517f606aceSMark Haywood return (0);
10527f606aceSMark Haywood }
10537f606aceSMark Haywood
10547f606aceSMark Haywood /*
10557f606aceSMark Haywood * Return supported frequencies.
10567f606aceSMark Haywood */
10577f606aceSMark Haywood uint_t
cpu_acpi_get_speeds(cpu_acpi_handle_t handle,int ** speeds)10587f606aceSMark Haywood cpu_acpi_get_speeds(cpu_acpi_handle_t handle, int **speeds)
10597f606aceSMark Haywood {
10607f606aceSMark Haywood cpu_acpi_pstate_t *pstate;
10617f606aceSMark Haywood int *hspeeds;
10627f606aceSMark Haywood uint_t nspeeds;
10637f606aceSMark Haywood int i;
10647f606aceSMark Haywood
10657f606aceSMark Haywood nspeeds = CPU_ACPI_PSTATES_COUNT(handle);
10667f606aceSMark Haywood pstate = (cpu_acpi_pstate_t *)CPU_ACPI_PSTATES(handle);
10677f606aceSMark Haywood hspeeds = kmem_zalloc(nspeeds * sizeof (int), KM_SLEEP);
10687f606aceSMark Haywood for (i = 0; i < nspeeds; i++) {
10697f606aceSMark Haywood hspeeds[i] = CPU_ACPI_FREQ(pstate);
10707f606aceSMark Haywood pstate++;
10717f606aceSMark Haywood }
10727f606aceSMark Haywood *speeds = hspeeds;
10737f606aceSMark Haywood return (nspeeds);
10747f606aceSMark Haywood }
10757f606aceSMark Haywood
10767f606aceSMark Haywood /*
10777f606aceSMark Haywood * Free resources allocated by cpu_acpi_get_speeds().
10787f606aceSMark Haywood */
10797f606aceSMark Haywood void
cpu_acpi_free_speeds(int * speeds,uint_t nspeeds)10807f606aceSMark Haywood cpu_acpi_free_speeds(int *speeds, uint_t nspeeds)
10817f606aceSMark Haywood {
10827f606aceSMark Haywood kmem_free(speeds, nspeeds * sizeof (int));
10837f606aceSMark Haywood }
10847f606aceSMark Haywood
10850e751525SEric Saxe uint_t
cpu_acpi_get_max_cstates(cpu_acpi_handle_t handle)10860e751525SEric Saxe cpu_acpi_get_max_cstates(cpu_acpi_handle_t handle)
10870e751525SEric Saxe {
10880e751525SEric Saxe if (CPU_ACPI_CSTATES(handle))
10890e751525SEric Saxe return (CPU_ACPI_CSTATES_COUNT(handle));
10900e751525SEric Saxe else
10910e751525SEric Saxe return (1);
10920e751525SEric Saxe }
10930e751525SEric Saxe
10940e751525SEric Saxe void
cpu_acpi_set_register(uint32_t bitreg,uint32_t value)10950e751525SEric Saxe cpu_acpi_set_register(uint32_t bitreg, uint32_t value)
10960e751525SEric Saxe {
1097444f66e7SMark Haywood (void) AcpiWriteBitRegister(bitreg, value);
10980e751525SEric Saxe }
10990e751525SEric Saxe
11000e751525SEric Saxe void
cpu_acpi_get_register(uint32_t bitreg,uint32_t * value)11010e751525SEric Saxe cpu_acpi_get_register(uint32_t bitreg, uint32_t *value)
11020e751525SEric Saxe {
1103444f66e7SMark Haywood (void) AcpiReadBitRegister(bitreg, value);
11040e751525SEric Saxe }
11050e751525SEric Saxe
11067f606aceSMark Haywood /*
11077f606aceSMark Haywood * Map the dip to an ACPI handle for the device.
11087f606aceSMark Haywood */
11097f606aceSMark Haywood cpu_acpi_handle_t
cpu_acpi_init(cpu_t * cp)11100e751525SEric Saxe cpu_acpi_init(cpu_t *cp)
11117f606aceSMark Haywood {
11127f606aceSMark Haywood cpu_acpi_handle_t handle;
11137f606aceSMark Haywood
11147f606aceSMark Haywood handle = kmem_zalloc(sizeof (cpu_acpi_state_t), KM_SLEEP);
11157f606aceSMark Haywood
11160e751525SEric Saxe if (ACPI_FAILURE(acpica_get_handle_cpu(cp->cpu_id,
11170e751525SEric Saxe &handle->cs_handle))) {
11187f606aceSMark Haywood kmem_free(handle, sizeof (cpu_acpi_state_t));
11197f606aceSMark Haywood return (NULL);
11207f606aceSMark Haywood }
11210e751525SEric Saxe handle->cs_id = cp->cpu_id;
11227f606aceSMark Haywood return (handle);
11237f606aceSMark Haywood }
11247f606aceSMark Haywood
11257f606aceSMark Haywood /*
11267f606aceSMark Haywood * Free any resources.
11277f606aceSMark Haywood */
11287f606aceSMark Haywood void
cpu_acpi_fini(cpu_acpi_handle_t handle)11297f606aceSMark Haywood cpu_acpi_fini(cpu_acpi_handle_t handle)
11307f606aceSMark Haywood {
11317f606aceSMark Haywood if (handle)
11327f606aceSMark Haywood kmem_free(handle, sizeof (cpu_acpi_state_t));
11337f606aceSMark Haywood }
1134