2 * Copyright (c) 2009 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Sepherosa Ziehau <sepherosa@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include <sys/param.h>
39 #include <sys/cpuhelper.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/queue.h>
44 #include <sys/sysctl.h>
45 #include <sys/msgport2.h>
46 #include <sys/cpu_topology.h>
51 #include "acpi_cpu_pstate.h"
53 #define ACPI_NPSTATE_MAX 32
55 #define ACPI_PSS_PX_NENTRY 6
57 #define ACPI_PSD_COORD_SWALL 0xfc
58 #define ACPI_PSD_COORD_SWANY 0xfd
59 #define ACPI_PSD_COORD_HWALL 0xfe
60 #define ACPI_PSD_COORD_VALID(coord) \
61 ((coord) == ACPI_PSD_COORD_SWALL || \
62 (coord) == ACPI_PSD_COORD_SWANY || \
63 (coord) == ACPI_PSD_COORD_HWALL)
65 struct acpi_pst_softc
;
66 LIST_HEAD(acpi_pst_list
, acpi_pst_softc
);
68 struct acpi_pst_chmsg
{
69 struct cpuhelper_msg ch_msg
;
70 const struct acpi_pst_res
*ch_ctrl
;
71 const struct acpi_pst_res
*ch_status
;
74 struct acpi_pst_domain
{
78 LIST_ENTRY(acpi_pst_domain
) pd_link
;
82 struct lwkt_serialize pd_serialize
;
85 struct acpi_pst_list pd_pstlist
;
87 struct sysctl_ctx_list pd_sysctl_ctx
;
88 struct sysctl_oid
*pd_sysctl_tree
;
90 LIST_HEAD(acpi_pst_domlist
, acpi_pst_domain
);
92 #define ACPI_PSTDOM_FLAG_STUB 0x1 /* stub domain, no _PSD */
93 #define ACPI_PSTDOM_FLAG_DEAD 0x2 /* domain can't be started */
94 #define ACPI_PSTDOM_FLAG_INT 0x4 /* domain created from Integer _PSD */
96 struct acpi_pst_softc
{
98 struct acpi_cpu_softc
*pst_parent
;
99 struct acpi_pst_domain
*pst_domain
;
100 struct acpi_pst_res pst_creg
;
101 struct acpi_pst_res pst_sreg
;
108 ACPI_HANDLE pst_handle
;
110 LIST_ENTRY(acpi_pst_softc
) pst_link
;
113 #define ACPI_PST_FLAG_PPC 0x1
114 #define ACPI_PST_FLAG_PDL 0x2
116 static int acpi_pst_probe(device_t dev
);
117 static int acpi_pst_attach(device_t dev
);
118 static void acpi_pst_notify(device_t dev
);
120 static void acpi_pst_postattach(void *);
121 static struct acpi_pst_domain
*
122 acpi_pst_domain_create_int(device_t
, uint32_t);
123 static struct acpi_pst_domain
*
124 acpi_pst_domain_create_pkg(device_t
, ACPI_OBJECT
*);
125 static struct acpi_pst_domain
*
126 acpi_pst_domain_find(uint32_t);
127 static struct acpi_pst_domain
*
128 acpi_pst_domain_alloc(uint32_t, uint32_t, uint32_t);
129 static void acpi_pst_domain_set_pstate_locked(struct acpi_pst_domain
*,
131 static void acpi_pst_domain_set_pstate(struct acpi_pst_domain
*, int,
133 static void acpi_pst_domain_check_nproc(device_t
, struct acpi_pst_domain
*);
134 static void acpi_pst_global_set_pstate(int);
135 static void acpi_pst_global_fixup_pstate(void);
137 static int acpi_pst_check_csr(struct acpi_pst_softc
*);
138 static int acpi_pst_check_pstates(struct acpi_pst_softc
*);
139 static int acpi_pst_init(struct acpi_pst_softc
*);
140 static int acpi_pst_set_pstate(struct acpi_pst_softc
*,
141 const struct acpi_pstate
*);
142 static const struct acpi_pstate
*
143 acpi_pst_get_pstate(struct acpi_pst_softc
*);
144 static int acpi_pst_alloc_resource(device_t
, ACPI_OBJECT
*, int,
145 struct acpi_pst_res
*);
146 static int acpi_pst_eval_ppc(struct acpi_pst_softc
*, int *);
147 static int acpi_pst_eval_pdl(struct acpi_pst_softc
*, int *);
149 static void acpi_pst_check_csr_handler(struct cpuhelper_msg
*);
150 static void acpi_pst_check_pstates_handler(struct cpuhelper_msg
*);
151 static void acpi_pst_init_handler(struct cpuhelper_msg
*);
152 static void acpi_pst_set_pstate_handler(struct cpuhelper_msg
*);
153 static void acpi_pst_get_pstate_handler(struct cpuhelper_msg
*);
155 static int acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS
);
156 static int acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS
);
157 static int acpi_pst_sysctl_power(SYSCTL_HANDLER_ARGS
);
158 static int acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS
);
159 static int acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS
);
160 static int acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS
);
162 static struct acpi_pst_domlist acpi_pst_domains
=
163 LIST_HEAD_INITIALIZER(acpi_pst_domains
);
164 static int acpi_pst_domain_id
;
166 static int acpi_pst_global_state
;
168 static int acpi_pstate_start
= -1;
169 static int acpi_pstate_count
;
170 static int acpi_npstates
;
171 static struct acpi_pstate
*acpi_pstates
;
173 static const struct acpi_pst_md
*acpi_pst_md
;
175 static int acpi_pst_pdl
= -1;
176 TUNABLE_INT("hw.acpi.cpu.pst.pdl", &acpi_pst_pdl
);
178 static int acpi_pst_ht_reuse_domain
= 1;
179 TUNABLE_INT("hw.acpi.cpu.pst.ht_reuse_domain", &acpi_pst_ht_reuse_domain
);
181 static int acpi_pst_force_pkg_domain
= 0;
182 TUNABLE_INT("hw.acpi.cpu.pst.force_pkg_domain", &acpi_pst_force_pkg_domain
);
184 static int acpi_pst_handle_notify
= 1;
185 TUNABLE_INT("hw.acpi.cpu.pst.handle_notify", &acpi_pst_handle_notify
);
188 * Force CPU package power domain for Intel CPUs.
190 * As of this write (14 July 2015), all Intel CPUs only have CPU package
193 static int acpi_pst_intel_pkg_domain
= 1;
194 TUNABLE_INT("hw.acpi.cpu.pst.intel_pkg_domain", &acpi_pst_intel_pkg_domain
);
196 static device_method_t acpi_pst_methods
[] = {
197 /* Device interface */
198 DEVMETHOD(device_probe
, acpi_pst_probe
),
199 DEVMETHOD(device_attach
, acpi_pst_attach
),
200 DEVMETHOD(device_detach
, bus_generic_detach
),
201 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
202 DEVMETHOD(device_suspend
, bus_generic_suspend
),
203 DEVMETHOD(device_resume
, bus_generic_resume
),
206 DEVMETHOD(bus_add_child
, bus_generic_add_child
),
207 DEVMETHOD(bus_print_child
, bus_generic_print_child
),
208 DEVMETHOD(bus_read_ivar
, bus_generic_read_ivar
),
209 DEVMETHOD(bus_write_ivar
, bus_generic_write_ivar
),
210 DEVMETHOD(bus_get_resource_list
, bus_generic_get_resource_list
),
211 DEVMETHOD(bus_set_resource
, bus_generic_rl_set_resource
),
212 DEVMETHOD(bus_get_resource
, bus_generic_rl_get_resource
),
213 DEVMETHOD(bus_alloc_resource
, bus_generic_alloc_resource
),
214 DEVMETHOD(bus_release_resource
, bus_generic_release_resource
),
215 DEVMETHOD(bus_driver_added
, bus_generic_driver_added
),
216 DEVMETHOD(bus_activate_resource
, bus_generic_activate_resource
),
217 DEVMETHOD(bus_deactivate_resource
, bus_generic_deactivate_resource
),
218 DEVMETHOD(bus_setup_intr
, bus_generic_setup_intr
),
219 DEVMETHOD(bus_teardown_intr
, bus_generic_teardown_intr
),
224 static driver_t acpi_pst_driver
= {
227 sizeof(struct acpi_pst_softc
),
228 .gpri
= KOBJ_GPRI_ACPI
+2
231 static devclass_t acpi_pst_devclass
;
232 DRIVER_MODULE(cpu_pst
, cpu
, acpi_pst_driver
, acpi_pst_devclass
, NULL
, NULL
);
233 MODULE_DEPEND(cpu_pst
, acpi
, 1, 1, 1);
236 acpi_pst_freq2index(int freq
)
240 for (i
= 0; i
< acpi_npstates
; ++i
) {
241 if (acpi_pstates
[i
].st_freq
== freq
)
248 acpi_pst_probe(device_t dev
)
255 if (acpi_disabled("cpu_pst") ||
256 acpi_get_type(dev
) != ACPI_TYPE_PROCESSOR
)
259 if (acpi_pst_md
== NULL
)
260 acpi_pst_md
= acpi_pst_md_probe();
262 handle
= acpi_get_handle(dev
);
268 * Some BIOSes do not expose _PCT for the second thread of
269 * CPU cores. In this case, _PSD should be enough to get the
270 * P-state of the second thread working, since it must have
271 * the same _PCT and _PSS as the first thread in the same
275 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
276 status
= AcpiEvaluateObject(handle
, "_PSD", NULL
, &buf
);
277 if (!ACPI_FAILURE(status
)) {
278 AcpiOsFree((ACPI_OBJECT
*)buf
.Pointer
);
286 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
287 status
= AcpiEvaluateObject(handle
, "_PCT", NULL
, &buf
);
288 if (ACPI_FAILURE(status
)) {
290 device_printf(dev
, "Can't get _PCT package - %s\n",
291 AcpiFormatException(status
));
296 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
297 if (!ACPI_PKG_VALID_EQ(obj
, 2)) {
298 device_printf(dev
, "Invalid _PCT package\n");
308 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
309 status
= AcpiEvaluateObject(handle
, "_PSS", NULL
, &buf
);
310 if (ACPI_FAILURE(status
)) {
311 device_printf(dev
, "Can't get _PSS package - %s\n",
312 AcpiFormatException(status
));
316 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
317 if (!ACPI_PKG_VALID(obj
, 1)) {
318 device_printf(dev
, "Invalid _PSS package\n");
325 device_set_desc(dev
, "ACPI CPU P-State");
330 acpi_pst_attach(device_t dev
)
332 struct acpi_pst_softc
*sc
= device_get_softc(dev
);
333 struct acpi_pst_domain
*dom
= NULL
;
337 struct acpi_pstate
*pstate
, *p
;
338 int i
, npstate
, error
, sstart
, scount
;
341 sc
->pst_parent
= device_get_softc(device_get_parent(dev
));
342 sc
->pst_handle
= acpi_get_handle(dev
);
343 sc
->pst_cpuid
= acpi_get_magic(dev
);
346 * If there is a _PSD, then we create procossor domain
347 * accordingly. If there is no _PSD, we just fake a
348 * default processor domain0.
351 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
352 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PSD", NULL
, &buf
);
353 if (!ACPI_FAILURE(status
)) {
354 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
356 if (acpi_pst_domain_id
> 0) {
357 device_printf(dev
, "Missing _PSD for certain CPUs\n");
361 acpi_pst_domain_id
= -1;
363 if (ACPI_PKG_VALID_EQ(obj
, 1)) {
364 dom
= acpi_pst_domain_create_pkg(dev
,
365 &obj
->Package
.Elements
[0]);
371 if (obj
->Type
!= ACPI_TYPE_INTEGER
) {
373 "Invalid _PSD package, Type 0x%x\n",
378 device_printf(dev
, "Integer _PSD %ju\n",
379 (uintmax_t)obj
->Integer
.Value
);
380 dom
= acpi_pst_domain_create_int(dev
,
390 AcpiOsFree(buf
.Pointer
);
392 if (acpi_pst_domain_id
< 0) {
393 device_printf(dev
, "Missing _PSD for cpu%d\n",
399 * Create a stub one processor domain for each processor
401 dom
= acpi_pst_domain_alloc(acpi_pst_domain_id
,
402 ACPI_PSD_COORD_SWANY
, 1);
403 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_STUB
;
405 ++acpi_pst_domain_id
;
408 /* Make sure that adding us will not overflow our domain */
409 acpi_pst_domain_check_nproc(dev
, dom
);
412 * Get control/status registers from _PCT
415 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
416 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PCT", NULL
, &buf
);
417 if (ACPI_FAILURE(status
)) {
418 struct acpi_pst_softc
*pst
;
421 * No _PCT. See the comment in acpi_pst_probe() near
424 * Use control/status registers of another CPU in the
425 * same domain, or in the same core, if the type of
426 * these registers are "Fixed Hardware", e.g. on most
427 * of the model Intel CPUs.
429 pst
= LIST_FIRST(&dom
->pd_pstlist
);
433 mask
= get_cpumask_from_level(sc
->pst_cpuid
,
435 if (CPUMASK_TESTNZERO(mask
)) {
436 struct acpi_pst_domain
*dom1
;
438 LIST_FOREACH(dom1
, &acpi_pst_domains
, pd_link
) {
439 LIST_FOREACH(pst
, &dom1
->pd_pstlist
,
441 if (CPUMASK_TESTBIT(mask
,
448 if (pst
!= NULL
&& acpi_pst_ht_reuse_domain
) {
450 * Use the same domain for CPUs in the
453 device_printf(dev
, "Destroy domain%u, "
455 dom
->pd_dom
, dom1
->pd_dom
);
456 LIST_REMOVE(dom
, pd_link
);
457 kfree(dom
, M_DEVBUF
);
460 * Make sure that adding us will not
461 * overflow the domain containing
462 * siblings in the same core.
464 acpi_pst_domain_check_nproc(dev
, dom
);
469 pst
->pst_creg
.pr_res
== NULL
&&
470 pst
->pst_creg
.pr_rid
== 0 &&
471 pst
->pst_creg
.pr_gas
.SpaceId
==
472 ACPI_ADR_SPACE_FIXED_HARDWARE
&&
473 pst
->pst_sreg
.pr_res
== NULL
&&
474 pst
->pst_sreg
.pr_rid
== 0 &&
475 pst
->pst_sreg
.pr_gas
.SpaceId
==
476 ACPI_ADR_SPACE_FIXED_HARDWARE
) {
477 sc
->pst_creg
= pst
->pst_creg
;
478 sc
->pst_sreg
= pst
->pst_sreg
;
480 "No _PCT; reuse %s control/status regs\n",
481 device_get_nameunit(pst
->pst_dev
));
484 device_printf(dev
, "Can't get _PCT package - %s\n",
485 AcpiFormatException(status
));
489 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
490 if (!ACPI_PKG_VALID_EQ(obj
, 2)) {
491 device_printf(dev
, "Invalid _PCT package\n");
496 /* Save and try allocating control register */
497 error
= acpi_pst_alloc_resource(dev
, obj
, 0, &sc
->pst_creg
);
503 device_printf(dev
, "control reg %d %jx\n",
504 sc
->pst_creg
.pr_gas
.SpaceId
,
505 (uintmax_t)sc
->pst_creg
.pr_gas
.Address
);
508 /* Save and try allocating status register */
509 error
= acpi_pst_alloc_resource(dev
, obj
, 1, &sc
->pst_sreg
);
515 device_printf(dev
, "status reg %d %jx\n",
516 sc
->pst_sreg
.pr_gas
.SpaceId
,
517 (uintmax_t)sc
->pst_sreg
.pr_gas
.Address
);
525 * Create P-State table according to _PSS
528 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
529 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PSS", NULL
, &buf
);
530 if (ACPI_FAILURE(status
)) {
532 * No _PSS. See the comment in acpi_pst_probe() near
535 * Assume _PSS are same across all CPUs; well, they
536 * should/have to be so.
538 if (acpi_npstates
> 0 && acpi_pstates
!= NULL
) {
539 device_printf(dev
, "No _PSS\n");
542 device_printf(dev
, "Can't get _PSS package - %s\n",
543 AcpiFormatException(status
));
547 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
548 if (!ACPI_PKG_VALID(obj
, 1)) {
549 device_printf(dev
, "Invalid _PSS package\n");
554 /* Don't create too many P-States */
555 npstate
= obj
->Package
.Count
;
556 if (npstate
> ACPI_NPSTATE_MAX
) {
557 device_printf(dev
, "Too many P-States, %d->%d\n",
558 npstate
, ACPI_NPSTATE_MAX
);
559 npstate
= ACPI_NPSTATE_MAX
;
563 * If we have already created P-State table,
564 * we must make sure that number of entries
567 if (acpi_pstates
!= NULL
&& acpi_npstates
!= npstate
) {
568 device_printf(dev
, "Inconsistent # of P-States "
569 "cross Processor objects\n");
575 * Create a temporary P-State table
577 pstate
= kmalloc(sizeof(*pstate
) * npstate
, M_TEMP
, M_WAITOK
);
578 for (i
= 0, p
= pstate
; i
< npstate
; ++i
, ++p
) {
580 uint32_t *ptr
[ACPI_PSS_PX_NENTRY
] = {
581 &p
->st_freq
, &p
->st_power
, &p
->st_xsit_lat
,
582 &p
->st_bm_lat
, &p
->st_cval
, &p
->st_sval
586 pkg
= &obj
->Package
.Elements
[i
];
587 if (!ACPI_PKG_VALID(pkg
, ACPI_PSS_PX_NENTRY
)) {
588 device_printf(dev
, "Invalud _PSS P%d\n", i
);
590 kfree(pstate
, M_TEMP
);
593 for (j
= 0; j
< ACPI_PSS_PX_NENTRY
; ++j
) {
594 if (acpi_PkgInt32(pkg
, j
, ptr
[j
]) != 0) {
595 device_printf(dev
, "Can't extract "
596 "_PSS P%d %dth entry\n", i
, j
);
598 kfree(pstate
, M_TEMP
);
602 if (p
->st_freq
& 0x80000000) {
603 device_printf(dev
, "Invalid _PSS P%d freq: 0x%08x\n",
606 kfree(pstate
, M_TEMP
);
614 if (acpi_pstates
== NULL
) {
616 * If no P-State table is created yet,
617 * save the temporary one we just created.
619 acpi_pstates
= pstate
;
620 acpi_npstates
= npstate
;
624 for (i
= 0; i
< acpi_npstates
; ++i
) {
626 "freq %u, pwr %u, xlat %u, blat %u, "
627 "cv %08x, sv %08x\n",
628 acpi_pstates
[i
].st_freq
,
629 acpi_pstates
[i
].st_power
,
630 acpi_pstates
[i
].st_xsit_lat
,
631 acpi_pstates
[i
].st_bm_lat
,
632 acpi_pstates
[i
].st_cval
,
633 acpi_pstates
[i
].st_sval
);
638 * Make sure that P-State tables are same
639 * for all processors.
641 if (memcmp(pstate
, acpi_pstates
,
642 sizeof(*pstate
) * npstate
) != 0) {
643 device_printf(dev
, "Inconsistent _PSS "
644 "cross Processor objects\n");
647 * Some BIOSes create different P-State tables;
648 * just trust the one from the BSP and move on.
650 kfree(pstate
, M_TEMP
);
654 kfree(pstate
, M_TEMP
);
658 /* By default, we start from P-State table's first entry */
662 * Adjust the usable first entry of P-State table,
663 * if there is _PPC object.
665 error
= acpi_pst_eval_ppc(sc
, &sstart
);
666 if (error
&& error
!= ENOENT
)
669 sc
->pst_flags
|= ACPI_PST_FLAG_PPC
;
670 if (acpi_pstate_start
< 0) {
671 acpi_pstate_start
= sstart
;
672 } else if (acpi_pstate_start
!= sstart
) {
673 device_printf(dev
, "_PPC mismatch, was %d, now %d\n",
674 acpi_pstate_start
, sstart
);
675 if (acpi_pstate_start
< sstart
) {
676 device_printf(dev
, "_PPC %d -> %d\n",
677 acpi_pstate_start
, sstart
);
678 acpi_pstate_start
= sstart
;
683 * By default, we assume number of usable P-States is same as
684 * number of P-States.
686 scount
= acpi_npstates
;
689 * Allow users to override or set _PDL
691 if (acpi_pst_pdl
>= 0) {
692 if (acpi_pst_pdl
< acpi_npstates
) {
694 device_printf(dev
, "_PDL override %d\n",
697 scount
= acpi_pst_pdl
+ 1;
700 device_printf(dev
, "Invalid _PDL override %d, "
701 "must be less than %d\n", acpi_pst_pdl
,
707 * Adjust the number of usable entries in P-State table,
708 * if there is _PDL object.
710 error
= acpi_pst_eval_pdl(sc
, &scount
);
711 if (error
&& error
!= ENOENT
)
714 sc
->pst_flags
|= ACPI_PST_FLAG_PDL
;
716 if (acpi_pstate_count
== 0) {
717 acpi_pstate_count
= scount
;
718 } else if (acpi_pstate_count
!= scount
) {
719 device_printf(dev
, "_PDL mismatch, was %d, now %d\n",
720 acpi_pstate_count
, scount
);
721 if (acpi_pstate_count
> scount
) {
722 device_printf(dev
, "_PDL %d -> %d\n",
723 acpi_pstate_count
, scount
);
724 acpi_pstate_count
= scount
;
729 * Some CPUs only have package P-states, but some BIOSes put each
730 * hyperthread to its own P-state domain; allow user to override.
732 if (LIST_EMPTY(&dom
->pd_pstlist
) &&
733 (acpi_pst_force_pkg_domain
||
734 (cpu_vendor_id
== CPU_VENDOR_INTEL
&&
735 acpi_pst_intel_pkg_domain
))) {
738 mask
= get_cpumask_from_level(sc
->pst_cpuid
, CHIP_LEVEL
);
739 if (CPUMASK_TESTNZERO(mask
)) {
740 struct acpi_pst_softc
*pst
= NULL
;
741 struct acpi_pst_domain
*dom1
;
743 LIST_FOREACH(dom1
, &acpi_pst_domains
, pd_link
) {
744 LIST_FOREACH(pst
, &dom1
->pd_pstlist
,
746 if (CPUMASK_TESTBIT(mask
,
754 memcmp(&pst
->pst_creg
, &sc
->pst_creg
,
755 sizeof(sc
->pst_creg
)) == 0 &&
756 memcmp(&pst
->pst_sreg
, &sc
->pst_sreg
,
757 sizeof(sc
->pst_sreg
)) == 0) {
759 * Use the same domain for CPUs in the
762 device_printf(dev
, "Destroy domain%u, "
763 "force pkg domain%u\n",
764 dom
->pd_dom
, dom1
->pd_dom
);
765 LIST_REMOVE(dom
, pd_link
);
766 kfree(dom
, M_DEVBUF
);
769 * Make sure that adding us will not
770 * overflow the domain containing
771 * siblings in the same package.
773 acpi_pst_domain_check_nproc(dev
, dom
);
778 /* Link us with the domain */
779 sc
->pst_domain
= dom
;
780 LIST_INSERT_HEAD(&dom
->pd_pstlist
, sc
, pst_link
);
782 if (device_get_unit(dev
) == 0)
783 AcpiOsExecute(OSL_NOTIFY_HANDLER
, acpi_pst_postattach
, NULL
);
785 if (sc
->pst_flags
& (ACPI_PST_FLAG_PPC
| ACPI_PST_FLAG_PDL
))
786 sc
->pst_parent
->cpu_pst_notify
= acpi_pst_notify
;
791 static struct acpi_pst_domain
*
792 acpi_pst_domain_create_pkg(device_t dev
, ACPI_OBJECT
*obj
)
794 struct acpi_pst_domain
*dom
;
795 uint32_t val
, domain
, coord
, nproc
;
797 if (!ACPI_PKG_VALID_EQ(obj
, 5)) {
798 device_printf(dev
, "Invalid _PSD package\n");
802 /* NumberOfEntries */
803 if (acpi_PkgInt32(obj
, 0, &val
) != 0 || val
!= 5) {
804 device_printf(dev
, "Invalid _PSD NumberOfEntries\n");
809 if (acpi_PkgInt32(obj
, 1, &val
) != 0 || val
!= 0) {
810 device_printf(dev
, "Invalid _PSD Revision\n");
814 if (acpi_PkgInt32(obj
, 2, &domain
) != 0 ||
815 acpi_PkgInt32(obj
, 3, &coord
) != 0 ||
816 acpi_PkgInt32(obj
, 4, &nproc
) != 0) {
817 device_printf(dev
, "Can't extract _PSD package\n");
821 if (!ACPI_PSD_COORD_VALID(coord
)) {
822 device_printf(dev
, "Invalid _PSD CoordType (%#x)\n", coord
);
826 if (nproc
> MAXCPU
) {
828 * If NumProcessors is greater than MAXCPU
829 * and domain's coordination is SWALL, then
830 * we will never be able to start all CPUs
831 * within this domain, and power state
832 * transition will never be completed, so we
833 * just bail out here.
835 if (coord
== ACPI_PSD_COORD_SWALL
) {
836 device_printf(dev
, "Unsupported _PSD NumProcessors "
840 } else if (nproc
== 0) {
841 device_printf(dev
, "_PSD NumProcessors are zero\n");
845 dom
= acpi_pst_domain_find(domain
);
847 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_INT
) {
848 device_printf(dev
, "Mixed Integer _PSD and "
852 if (dom
->pd_coord
!= coord
) {
853 device_printf(dev
, "Inconsistent _PSD coord "
854 "information cross Processor objects\n");
857 if (dom
->pd_nproc
!= nproc
) {
858 device_printf(dev
, "Inconsistent _PSD nproc "
859 "information cross Processor objects\n");
861 * Some stupid BIOSes will set wrong "# of processors",
862 * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
868 dom
= acpi_pst_domain_alloc(domain
, coord
, nproc
);
870 device_printf(dev
, "create pkg domain%u, coord %#x\n",
871 dom
->pd_dom
, dom
->pd_coord
);
877 static struct acpi_pst_domain
*
878 acpi_pst_domain_create_int(device_t dev
, uint32_t domain
)
880 struct acpi_pst_domain
*dom
;
882 dom
= acpi_pst_domain_find(domain
);
884 if ((dom
->pd_flags
& ACPI_PSTDOM_FLAG_INT
) == 0) {
885 device_printf(dev
, "Mixed Package _PSD and "
889 KKASSERT(dom
->pd_coord
== ACPI_PSD_COORD_SWALL
);
895 dom
= acpi_pst_domain_alloc(domain
, ACPI_PSD_COORD_SWALL
, 1);
896 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_INT
;
899 device_printf(dev
, "create int domain%u\n", dom
->pd_dom
);
904 static struct acpi_pst_domain
*
905 acpi_pst_domain_find(uint32_t domain
)
907 struct acpi_pst_domain
*dom
;
909 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
910 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_STUB
)
912 if (dom
->pd_dom
== domain
)
918 static struct acpi_pst_domain
*
919 acpi_pst_domain_alloc(uint32_t domain
, uint32_t coord
, uint32_t nproc
)
921 struct acpi_pst_domain
*dom
;
923 dom
= kmalloc(sizeof(*dom
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
924 dom
->pd_dom
= domain
;
925 dom
->pd_coord
= coord
;
926 dom
->pd_nproc
= nproc
;
927 LIST_INIT(&dom
->pd_pstlist
);
928 lwkt_serialize_init(&dom
->pd_serialize
);
930 LIST_INSERT_HEAD(&acpi_pst_domains
, dom
, pd_link
);
936 acpi_pst_domain_set_pstate_locked(struct acpi_pst_domain
*dom
, int i
, int *global
)
938 const struct acpi_pstate
*pstate
;
939 struct acpi_pst_softc
*sc
;
942 ASSERT_SERIALIZED(&dom
->pd_serialize
);
944 KKASSERT(i
>= 0 && i
< acpi_npstates
);
945 pstate
= &acpi_pstates
[i
];
948 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
950 error
= acpi_pst_set_pstate(sc
, pstate
);
952 device_printf(sc
->pst_dev
, "can't set "
953 "freq %d\n", pstate
->st_freq
);
954 /* XXX error cleanup? */
956 if (dom
->pd_coord
== ACPI_PSD_COORD_SWANY
)
968 acpi_pst_domain_set_pstate(struct acpi_pst_domain
*dom
, int i
, int *global
)
970 lwkt_serialize_enter(&dom
->pd_serialize
);
971 acpi_pst_domain_set_pstate_locked(dom
, i
, global
);
972 lwkt_serialize_exit(&dom
->pd_serialize
);
976 acpi_pst_global_set_pstate(int i
)
978 struct acpi_pst_domain
*dom
;
979 int *global
= &acpi_pst_global_state
;
981 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
982 /* Skip dead domain */
983 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_DEAD
)
985 acpi_pst_domain_set_pstate(dom
, i
, global
);
991 acpi_pst_global_fixup_pstate(void)
993 struct acpi_pst_domain
*dom
;
994 int *global
= &acpi_pst_global_state
;
997 sstart
= acpi_pstate_start
;
998 scount
= acpi_pstate_count
;
1000 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
1003 /* Skip dead domain */
1004 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_DEAD
)
1007 lwkt_serialize_enter(&dom
->pd_serialize
);
1009 if (global
!= NULL
) {
1010 if (*global
< sstart
)
1012 else if (*global
>= scount
)
1013 *global
= scount
- 1;
1016 if (dom
->pd_state
< sstart
)
1018 else if (dom
->pd_state
>= scount
)
1021 acpi_pst_domain_set_pstate_locked(dom
, i
, NULL
);
1023 lwkt_serialize_exit(&dom
->pd_serialize
);
1028 acpi_pst_postattach(void *arg __unused
)
1030 struct acpi_pst_domain
*dom
;
1031 struct acpi_cpu_softc
*cpu
;
1033 int i
, ndevices
, error
, has_domain
;
1037 error
= devclass_get_devices(acpi_pst_devclass
, &devices
, &ndevices
);
1045 for (i
= 0; i
< ndevices
; ++i
) {
1046 cpu
= device_get_softc(device_get_parent(devices
[i
]));
1047 if (cpu
->glob_sysctl_tree
!= NULL
)
1050 kfree(devices
, M_TEMP
);
1051 KKASSERT(cpu
!= NULL
);
1053 if (acpi_pst_md
== NULL
)
1054 kprintf("ACPI: no P-State CPU driver\n");
1057 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
1058 struct acpi_pst_softc
*sc
;
1061 dom
->pd_state
= acpi_pstate_start
;
1064 * Make sure that all processors belonging to this
1065 * domain are located.
1068 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1069 sc
->pst_state
= acpi_pstate_start
;
1072 if (i
!= dom
->pd_nproc
) {
1073 KKASSERT(i
< dom
->pd_nproc
);
1075 kprintf("ACPI: domain%u misses processors, "
1076 "should be %d, got %d\n", dom
->pd_dom
,
1078 if (dom
->pd_coord
== ACPI_PSD_COORD_SWALL
) {
1080 * If this domain's coordination is
1081 * SWALL and we don't see all of the
1082 * member CPUs of this domain, then
1083 * the P-State transition will never
1084 * be completed, so just leave this
1087 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_DEAD
;
1094 * Validate P-State configurations for this domain
1096 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1097 error
= acpi_pst_check_csr(sc
);
1101 error
= acpi_pst_check_pstates(sc
);
1106 kprintf("ACPI: domain%u P-State configuration "
1107 "check failed\n", dom
->pd_dom
);
1108 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_DEAD
;
1113 * Do necssary P-State initialization
1115 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1116 error
= acpi_pst_init(sc
);
1121 kprintf("ACPI: domain%u P-State initialization "
1122 "check failed\n", dom
->pd_dom
);
1123 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_DEAD
;
1129 ksnprintf(buf
, sizeof(buf
), "px_dom%u", dom
->pd_dom
);
1131 sysctl_ctx_init(&dom
->pd_sysctl_ctx
);
1132 dom
->pd_sysctl_tree
=
1133 SYSCTL_ADD_NODE(&dom
->pd_sysctl_ctx
,
1134 SYSCTL_CHILDREN(cpu
->glob_sysctl_tree
),
1135 OID_AUTO
, buf
, CTLFLAG_RD
, 0,
1137 if (dom
->pd_sysctl_tree
== NULL
) {
1138 kprintf("ACPI: Can't create sysctl tree for domain%u",
1143 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1144 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1145 OID_AUTO
, "available",
1146 CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_SKIP
,
1147 dom
, 0, acpi_pst_sysctl_freqs
, "A",
1148 "available frequencies");
1150 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1151 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1153 CTLTYPE_OPAQUE
| CTLFLAG_RD
,
1154 dom
, 0, acpi_pst_sysctl_freqs_bin
, "IU",
1155 "available frequencies");
1157 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1158 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1160 CTLTYPE_OPAQUE
| CTLFLAG_RD
,
1161 dom
, 0, acpi_pst_sysctl_power
, "IU",
1162 "power of available frequencies");
1164 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1165 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1166 OID_AUTO
, "members",
1167 CTLTYPE_STRING
| CTLFLAG_RD
,
1168 dom
, 0, acpi_pst_sysctl_members
, "A",
1171 if (acpi_pst_md
!= NULL
&&
1172 acpi_pst_md
->pmd_set_pstate
!= NULL
) {
1173 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1174 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1176 CTLTYPE_UINT
| CTLFLAG_RW
,
1177 dom
, 0, acpi_pst_sysctl_select
,
1178 "IU", "select freq");
1182 if (has_domain
&& acpi_pst_md
!= NULL
&&
1183 acpi_pst_md
->pmd_set_pstate
!= NULL
) {
1184 SYSCTL_ADD_PROC(&cpu
->glob_sysctl_ctx
,
1185 SYSCTL_CHILDREN(cpu
->glob_sysctl_tree
),
1186 OID_AUTO
, "px_global",
1187 CTLTYPE_UINT
| CTLFLAG_RW
,
1188 NULL
, 0, acpi_pst_sysctl_global
,
1189 "IU", "select freq for all domains");
1190 SYSCTL_ADD_INT(&cpu
->glob_sysctl_ctx
,
1191 SYSCTL_CHILDREN(cpu
->glob_sysctl_tree
),
1192 OID_AUTO
, "px_handle_notify", CTLFLAG_RW
,
1193 &acpi_pst_handle_notify
, 0,
1194 "handle type 0x80 notify");
1196 acpi_pst_global_set_pstate(acpi_pstate_start
);
1201 acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS
)
1203 int i
, error
, sstart
, scount
;
1206 sstart
= acpi_pstate_start
;
1207 scount
= acpi_pstate_count
;
1208 for (i
= 0; i
< acpi_npstates
; ++i
) {
1209 if (error
== 0 && i
)
1210 error
= SYSCTL_OUT(req
, " ", 1);
1215 if (i
< sstart
|| i
>= scount
)
1220 ksnprintf(buf
, sizeof(buf
), pat
,
1221 acpi_pstates
[i
].st_freq
);
1222 error
= SYSCTL_OUT(req
, buf
, strlen(buf
));
1229 acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS
)
1231 uint32_t freqs
[ACPI_NPSTATE_MAX
];
1232 int cnt
, i
, sstart
, scount
;
1234 sstart
= acpi_pstate_start
;
1235 scount
= acpi_pstate_count
;
1237 cnt
= scount
- sstart
;
1238 for (i
= 0; i
< cnt
; ++i
)
1239 freqs
[i
] = acpi_pstates
[sstart
+ i
].st_freq
;
1241 return sysctl_handle_opaque(oidp
, freqs
, cnt
* sizeof(freqs
[0]), req
);
1245 acpi_pst_sysctl_power(SYSCTL_HANDLER_ARGS
)
1247 uint32_t power
[ACPI_NPSTATE_MAX
];
1248 int cnt
, i
, sstart
, scount
;
1250 sstart
= acpi_pstate_start
;
1251 scount
= acpi_pstate_count
;
1253 cnt
= scount
- sstart
;
1254 for (i
= 0; i
< cnt
; ++i
)
1255 power
[i
] = acpi_pstates
[sstart
+ i
].st_power
;
1257 return sysctl_handle_opaque(oidp
, power
, cnt
* sizeof(power
[0]), req
);
1261 acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS
)
1263 struct acpi_pst_domain
*dom
= arg1
;
1264 struct acpi_pst_softc
*sc
;
1268 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1271 if (error
== 0 && loop
)
1272 error
= SYSCTL_OUT(req
, " ", 1);
1274 ksnprintf(buf
, sizeof(buf
), "cpu%d", sc
->pst_cpuid
);
1275 error
= SYSCTL_OUT(req
, buf
, strlen(buf
));
1278 if (error
== 0 && acpi_pst_md
&& acpi_pst_md
->pmd_get_pstate
) {
1279 const struct acpi_pstate
*pstate
;
1282 pstate
= acpi_pst_get_pstate(sc
);
1283 if (pstate
== NULL
) {
1286 ksnprintf(buf
, sizeof(buf
), "(%d)",
1290 error
= SYSCTL_OUT(req
, str
, strlen(str
));
1298 acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS
)
1300 struct acpi_pst_domain
*dom
= arg1
;
1303 KKASSERT(dom
->pd_state
>= 0 && dom
->pd_state
< acpi_npstates
);
1305 freq
= acpi_pstates
[dom
->pd_state
].st_freq
;
1307 error
= sysctl_handle_int(oidp
, &freq
, 0, req
);
1308 if (error
|| req
->newptr
== NULL
)
1311 i
= acpi_pst_freq2index(freq
);
1315 acpi_pst_domain_set_pstate(dom
, i
, NULL
);
1320 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS
)
1324 KKASSERT(acpi_pst_global_state
>= 0 &&
1325 acpi_pst_global_state
< acpi_npstates
);
1327 freq
= acpi_pstates
[acpi_pst_global_state
].st_freq
;
1329 error
= sysctl_handle_int(oidp
, &freq
, 0, req
);
1330 if (error
|| req
->newptr
== NULL
)
1333 i
= acpi_pst_freq2index(freq
);
1337 acpi_pst_global_set_pstate(i
);
1343 acpi_pst_check_csr_handler(struct cpuhelper_msg
*msg
)
1345 struct acpi_pst_chmsg
*pmsg
= (struct acpi_pst_chmsg
*)msg
;
1348 error
= acpi_pst_md
->pmd_check_csr(pmsg
->ch_ctrl
, pmsg
->ch_status
);
1349 cpuhelper_replymsg(msg
, error
);
1353 acpi_pst_check_csr(struct acpi_pst_softc
*sc
)
1355 struct acpi_pst_chmsg msg
;
1357 if (acpi_pst_md
== NULL
)
1360 cpuhelper_initmsg(&msg
.ch_msg
, &curthread
->td_msgport
,
1361 acpi_pst_check_csr_handler
, NULL
, MSGF_PRIORITY
);
1362 msg
.ch_ctrl
= &sc
->pst_creg
;
1363 msg
.ch_status
= &sc
->pst_sreg
;
1365 return (cpuhelper_domsg(&msg
.ch_msg
, sc
->pst_cpuid
));
1369 acpi_pst_check_pstates_handler(struct cpuhelper_msg
*msg
)
1373 error
= acpi_pst_md
->pmd_check_pstates(acpi_pstates
, acpi_npstates
);
1374 cpuhelper_replymsg(msg
, error
);
1378 acpi_pst_check_pstates(struct acpi_pst_softc
*sc
)
1380 struct cpuhelper_msg msg
;
1382 if (acpi_pst_md
== NULL
)
1385 cpuhelper_initmsg(&msg
, &curthread
->td_msgport
,
1386 acpi_pst_check_pstates_handler
, NULL
, MSGF_PRIORITY
);
1387 return (cpuhelper_domsg(&msg
, sc
->pst_cpuid
));
1391 acpi_pst_init_handler(struct cpuhelper_msg
*msg
)
1393 struct acpi_pst_chmsg
*pmsg
= (struct acpi_pst_chmsg
*)msg
;
1396 error
= acpi_pst_md
->pmd_init(pmsg
->ch_ctrl
, pmsg
->ch_status
);
1397 cpuhelper_replymsg(msg
, error
);
1401 acpi_pst_init(struct acpi_pst_softc
*sc
)
1403 struct acpi_pst_chmsg msg
;
1405 if (acpi_pst_md
== NULL
)
1408 cpuhelper_initmsg(&msg
.ch_msg
, &curthread
->td_msgport
,
1409 acpi_pst_init_handler
, NULL
, MSGF_PRIORITY
);
1410 msg
.ch_ctrl
= &sc
->pst_creg
;
1411 msg
.ch_status
= &sc
->pst_sreg
;
1413 return (cpuhelper_domsg(&msg
.ch_msg
, sc
->pst_cpuid
));
1417 acpi_pst_set_pstate_handler(struct cpuhelper_msg
*msg
)
1419 struct acpi_pst_chmsg
*pmsg
= (struct acpi_pst_chmsg
*)msg
;
1422 error
= acpi_pst_md
->pmd_set_pstate(pmsg
->ch_ctrl
, pmsg
->ch_status
,
1424 cpuhelper_replymsg(msg
, error
);
1428 acpi_pst_set_pstate(struct acpi_pst_softc
*sc
, const struct acpi_pstate
*pstate
)
1430 struct acpi_pst_chmsg msg
;
1432 KKASSERT(acpi_pst_md
!= NULL
);
1434 cpuhelper_initmsg(&msg
.ch_msg
, &curthread
->td_msgport
,
1435 acpi_pst_set_pstate_handler
, __DECONST(void *, pstate
),
1437 msg
.ch_ctrl
= &sc
->pst_creg
;
1438 msg
.ch_status
= &sc
->pst_sreg
;
1440 return (cpuhelper_domsg(&msg
.ch_msg
, sc
->pst_cpuid
));
1444 acpi_pst_get_pstate_handler(struct cpuhelper_msg
*msg
)
1446 struct acpi_pst_chmsg
*pmsg
= (struct acpi_pst_chmsg
*)msg
;
1447 const struct acpi_pstate
*pstate
;
1449 pstate
= acpi_pst_md
->pmd_get_pstate(pmsg
->ch_status
, acpi_pstates
,
1451 msg
->ch_cbarg
= __DECONST(void *, pstate
);
1452 cpuhelper_replymsg(msg
, 0);
1455 static const struct acpi_pstate
*
1456 acpi_pst_get_pstate(struct acpi_pst_softc
*sc
)
1458 struct acpi_pst_chmsg msg
;
1460 if (acpi_pst_md
== NULL
)
1463 cpuhelper_initmsg(&msg
.ch_msg
, &curthread
->td_msgport
,
1464 acpi_pst_get_pstate_handler
, NULL
, MSGF_PRIORITY
);
1465 msg
.ch_status
= &sc
->pst_sreg
;
1467 cpuhelper_domsg(&msg
.ch_msg
, sc
->pst_cpuid
);
1468 return (msg
.ch_msg
.ch_cbarg
);
1472 acpi_pst_alloc_resource(device_t dev
, ACPI_OBJECT
*obj
, int idx
,
1473 struct acpi_pst_res
*res
)
1475 struct acpi_pst_softc
*sc
= device_get_softc(dev
);
1479 error
= acpi_PkgRawGas(obj
, idx
, &res
->pr_gas
);
1483 /* Allocate resource, if possible */
1484 res
->pr_rid
= sc
->pst_parent
->cpu_next_rid
;
1485 acpi_bus_alloc_gas(dev
, &type
, &res
->pr_rid
, &res
->pr_gas
, &res
->pr_res
, 0);
1486 if (res
->pr_res
!= NULL
) {
1487 sc
->pst_parent
->cpu_next_rid
++;
1488 res
->pr_bt
= rman_get_bustag(res
->pr_res
);
1489 res
->pr_bh
= rman_get_bushandle(res
->pr_res
);
1497 acpi_pst_domain_check_nproc(device_t dev
, struct acpi_pst_domain
*dom
)
1499 struct acpi_pst_softc
*pst
;
1503 LIST_FOREACH(pst
, &dom
->pd_pstlist
, pst_link
)
1505 if (i
== dom
->pd_nproc
) {
1507 * Some stupid BIOSes will set wrong "# of processors",
1508 * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
1511 device_printf(dev
, "domain%u already contains %d "
1512 "P-States\n", dom
->pd_dom
, dom
->pd_nproc
);
1516 KKASSERT(i
< dom
->pd_nproc
);
1520 acpi_pst_eval_ppc(struct acpi_pst_softc
*sc
, int *sstart
)
1527 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
1528 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PPC", NULL
, &buf
);
1529 if (!ACPI_FAILURE(status
)) {
1530 ACPI_OBJECT_LIST arglist
;
1533 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
1534 if (obj
->Type
== ACPI_TYPE_INTEGER
) {
1535 if (obj
->Integer
.Value
>= acpi_npstates
) {
1537 * Some broken BIOSes can set this
1538 * to any values; let's simply start
1539 * from the first P-state, which
1540 * should be the highest frequency
1544 device_printf(sc
->pst_dev
,
1545 "Invalid _PPC value %ju, "
1547 (uintmax_t)obj
->Integer
.Value
,
1552 *sstart
= obj
->Integer
.Value
;
1554 device_printf(sc
->pst_dev
, "_PPC %d\n",
1559 device_printf(sc
->pst_dev
, "Invalid _PPC object\n");
1567 /* _PPC has been successfully processed */
1568 arglist
.Pointer
= arg
;
1570 arg
[0].Type
= ACPI_TYPE_INTEGER
;
1571 arg
[0].Integer
.Value
= 0x80;
1572 arg
[1].Type
= ACPI_TYPE_INTEGER
;
1573 arg
[1].Integer
.Value
= 0;
1574 AcpiEvaluateObject(sc
->pst_handle
, "_OST", &arglist
, NULL
);
1582 acpi_pst_eval_pdl(struct acpi_pst_softc
*sc
, int *scount
)
1589 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
1590 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PDL", NULL
, &buf
);
1591 if (!ACPI_FAILURE(status
)) {
1592 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
1593 if (obj
->Type
== ACPI_TYPE_INTEGER
) {
1594 if (obj
->Integer
.Value
>= acpi_npstates
) {
1595 device_printf(sc
->pst_dev
,
1596 "Invalid _PDL value\n");
1600 if (obj
->Integer
.Value
>= acpi_pstate_start
) {
1601 *scount
= obj
->Integer
.Value
+ 1;
1603 device_printf(sc
->pst_dev
, "_PDL %d\n",
1607 /* Prefer _PPC as stated in ACPI 5.1 8.4.4.6 */
1608 device_printf(sc
->pst_dev
, "conflict _PDL %ju "
1609 "and _PPC %d, ignore\n",
1610 (uintmax_t)obj
->Integer
.Value
,
1614 device_printf(sc
->pst_dev
, "Invalid _PDL object\n");
1628 * Notify is serialized by acpi task thread.
1631 acpi_pst_notify(device_t dev
)
1633 struct acpi_pst_softc
*sc
= device_get_softc(dev
);
1634 boolean_t fixup
= FALSE
;
1636 if (!acpi_pst_handle_notify
)
1641 * _PPC and _PDL evaluation order is critical. _PDL
1642 * evaluation depends on _PPC evaluation.
1644 if (sc
->pst_flags
& ACPI_PST_FLAG_PPC
) {
1645 int sstart
= acpi_pstate_start
;
1647 acpi_pst_eval_ppc(sc
, &sstart
);
1648 if (acpi_pstate_start
!= sstart
&& sc
->pst_cpuid
== 0) {
1649 acpi_pstate_start
= sstart
;
1653 if (sc
->pst_flags
& ACPI_PST_FLAG_PDL
) {
1654 int scount
= acpi_pstate_count
;
1656 acpi_pst_eval_pdl(sc
, &scount
);
1657 if (acpi_pstate_count
!= scount
&& sc
->pst_cpuid
== 0) {
1658 acpi_pstate_count
= scount
;
1663 if (fixup
&& acpi_pst_md
!= NULL
&&
1664 acpi_pst_md
->pmd_set_pstate
!= NULL
)
1665 acpi_pst_global_fixup_pstate();