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
)
230 static devclass_t acpi_pst_devclass
;
231 DRIVER_MODULE(cpu_pst
, cpu
, acpi_pst_driver
, acpi_pst_devclass
, NULL
, NULL
);
232 MODULE_DEPEND(cpu_pst
, acpi
, 1, 1, 1);
235 acpi_pst_freq2index(int freq
)
239 for (i
= 0; i
< acpi_npstates
; ++i
) {
240 if (acpi_pstates
[i
].st_freq
== freq
)
247 acpi_pst_probe(device_t dev
)
254 if (acpi_disabled("cpu_pst") ||
255 acpi_get_type(dev
) != ACPI_TYPE_PROCESSOR
)
258 if (acpi_pst_md
== NULL
)
259 acpi_pst_md
= acpi_pst_md_probe();
261 handle
= acpi_get_handle(dev
);
267 * Some BIOSes do not expose _PCT for the second thread of
268 * CPU cores. In this case, _PSD should be enough to get the
269 * P-state of the second thread working, since it must have
270 * the same _PCT and _PSS as the first thread in the same
274 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
275 status
= AcpiEvaluateObject(handle
, "_PSD", NULL
, &buf
);
276 if (!ACPI_FAILURE(status
)) {
277 AcpiOsFree((ACPI_OBJECT
*)buf
.Pointer
);
285 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
286 status
= AcpiEvaluateObject(handle
, "_PCT", NULL
, &buf
);
287 if (ACPI_FAILURE(status
)) {
289 device_printf(dev
, "Can't get _PCT package - %s\n",
290 AcpiFormatException(status
));
295 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
296 if (!ACPI_PKG_VALID_EQ(obj
, 2)) {
297 device_printf(dev
, "Invalid _PCT package\n");
307 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
308 status
= AcpiEvaluateObject(handle
, "_PSS", NULL
, &buf
);
309 if (ACPI_FAILURE(status
)) {
310 device_printf(dev
, "Can't get _PSS package - %s\n",
311 AcpiFormatException(status
));
315 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
316 if (!ACPI_PKG_VALID(obj
, 1)) {
317 device_printf(dev
, "Invalid _PSS package\n");
324 device_set_desc(dev
, "ACPI CPU P-State");
329 acpi_pst_attach(device_t dev
)
331 struct acpi_pst_softc
*sc
= device_get_softc(dev
);
332 struct acpi_pst_domain
*dom
= NULL
;
336 struct acpi_pstate
*pstate
, *p
;
337 int i
, npstate
, error
, sstart
, scount
;
340 sc
->pst_parent
= device_get_softc(device_get_parent(dev
));
341 sc
->pst_handle
= acpi_get_handle(dev
);
342 sc
->pst_cpuid
= acpi_get_magic(dev
);
345 * If there is a _PSD, then we create procossor domain
346 * accordingly. If there is no _PSD, we just fake a
347 * default processor domain0.
350 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
351 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PSD", NULL
, &buf
);
352 if (!ACPI_FAILURE(status
)) {
353 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
355 if (acpi_pst_domain_id
> 0) {
356 device_printf(dev
, "Missing _PSD for certain CPUs\n");
360 acpi_pst_domain_id
= -1;
362 if (ACPI_PKG_VALID_EQ(obj
, 1)) {
363 dom
= acpi_pst_domain_create_pkg(dev
,
364 &obj
->Package
.Elements
[0]);
370 if (obj
->Type
!= ACPI_TYPE_INTEGER
) {
372 "Invalid _PSD package, Type 0x%x\n",
377 device_printf(dev
, "Integer _PSD %ju\n",
378 (uintmax_t)obj
->Integer
.Value
);
379 dom
= acpi_pst_domain_create_int(dev
,
389 AcpiOsFree(buf
.Pointer
);
391 if (acpi_pst_domain_id
< 0) {
392 device_printf(dev
, "Missing _PSD for cpu%d\n",
398 * Create a stub one processor domain for each processor
400 dom
= acpi_pst_domain_alloc(acpi_pst_domain_id
,
401 ACPI_PSD_COORD_SWANY
, 1);
402 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_STUB
;
404 ++acpi_pst_domain_id
;
407 /* Make sure that adding us will not overflow our domain */
408 acpi_pst_domain_check_nproc(dev
, dom
);
411 * Get control/status registers from _PCT
414 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
415 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PCT", NULL
, &buf
);
416 if (ACPI_FAILURE(status
)) {
417 struct acpi_pst_softc
*pst
;
420 * No _PCT. See the comment in acpi_pst_probe() near
423 * Use control/status registers of another CPU in the
424 * same domain, or in the same core, if the type of
425 * these registers are "Fixed Hardware", e.g. on most
426 * of the model Intel CPUs.
428 pst
= LIST_FIRST(&dom
->pd_pstlist
);
432 mask
= get_cpumask_from_level(sc
->pst_cpuid
,
434 if (CPUMASK_TESTNZERO(mask
)) {
435 struct acpi_pst_domain
*dom1
;
437 LIST_FOREACH(dom1
, &acpi_pst_domains
, pd_link
) {
438 LIST_FOREACH(pst
, &dom1
->pd_pstlist
,
440 if (CPUMASK_TESTBIT(mask
,
447 if (pst
!= NULL
&& acpi_pst_ht_reuse_domain
) {
449 * Use the same domain for CPUs in the
452 device_printf(dev
, "Destroy domain%u, "
454 dom
->pd_dom
, dom1
->pd_dom
);
455 LIST_REMOVE(dom
, pd_link
);
456 kfree(dom
, M_DEVBUF
);
459 * Make sure that adding us will not
460 * overflow the domain containing
461 * siblings in the same core.
463 acpi_pst_domain_check_nproc(dev
, dom
);
468 pst
->pst_creg
.pr_res
== NULL
&&
469 pst
->pst_creg
.pr_rid
== 0 &&
470 pst
->pst_creg
.pr_gas
.SpaceId
==
471 ACPI_ADR_SPACE_FIXED_HARDWARE
&&
472 pst
->pst_sreg
.pr_res
== NULL
&&
473 pst
->pst_sreg
.pr_rid
== 0 &&
474 pst
->pst_sreg
.pr_gas
.SpaceId
==
475 ACPI_ADR_SPACE_FIXED_HARDWARE
) {
476 sc
->pst_creg
= pst
->pst_creg
;
477 sc
->pst_sreg
= pst
->pst_sreg
;
479 "No _PCT; reuse %s control/status regs\n",
480 device_get_nameunit(pst
->pst_dev
));
483 device_printf(dev
, "Can't get _PCT package - %s\n",
484 AcpiFormatException(status
));
488 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
489 if (!ACPI_PKG_VALID_EQ(obj
, 2)) {
490 device_printf(dev
, "Invalid _PCT package\n");
495 /* Save and try allocating control register */
496 error
= acpi_pst_alloc_resource(dev
, obj
, 0, &sc
->pst_creg
);
502 device_printf(dev
, "control reg %d %jx\n",
503 sc
->pst_creg
.pr_gas
.SpaceId
,
504 (uintmax_t)sc
->pst_creg
.pr_gas
.Address
);
507 /* Save and try allocating status register */
508 error
= acpi_pst_alloc_resource(dev
, obj
, 1, &sc
->pst_sreg
);
514 device_printf(dev
, "status reg %d %jx\n",
515 sc
->pst_sreg
.pr_gas
.SpaceId
,
516 (uintmax_t)sc
->pst_sreg
.pr_gas
.Address
);
524 * Create P-State table according to _PSS
527 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
528 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PSS", NULL
, &buf
);
529 if (ACPI_FAILURE(status
)) {
531 * No _PSS. See the comment in acpi_pst_probe() near
534 * Assume _PSS are same across all CPUs; well, they
535 * should/have to be so.
537 if (acpi_npstates
> 0 && acpi_pstates
!= NULL
) {
538 device_printf(dev
, "No _PSS\n");
541 device_printf(dev
, "Can't get _PSS package - %s\n",
542 AcpiFormatException(status
));
546 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
547 if (!ACPI_PKG_VALID(obj
, 1)) {
548 device_printf(dev
, "Invalid _PSS package\n");
553 /* Don't create too many P-States */
554 npstate
= obj
->Package
.Count
;
555 if (npstate
> ACPI_NPSTATE_MAX
) {
556 device_printf(dev
, "Too many P-States, %d->%d\n",
557 npstate
, ACPI_NPSTATE_MAX
);
558 npstate
= ACPI_NPSTATE_MAX
;
562 * If we have already created P-State table,
563 * we must make sure that number of entries
566 if (acpi_pstates
!= NULL
&& acpi_npstates
!= npstate
) {
567 device_printf(dev
, "Inconsistent # of P-States "
568 "cross Processor objects\n");
574 * Create a temporary P-State table
576 pstate
= kmalloc(sizeof(*pstate
) * npstate
, M_TEMP
, M_WAITOK
);
577 for (i
= 0, p
= pstate
; i
< npstate
; ++i
, ++p
) {
579 uint32_t *ptr
[ACPI_PSS_PX_NENTRY
] = {
580 &p
->st_freq
, &p
->st_power
, &p
->st_xsit_lat
,
581 &p
->st_bm_lat
, &p
->st_cval
, &p
->st_sval
585 pkg
= &obj
->Package
.Elements
[i
];
586 if (!ACPI_PKG_VALID(pkg
, ACPI_PSS_PX_NENTRY
)) {
587 device_printf(dev
, "Invalud _PSS P%d\n", i
);
589 kfree(pstate
, M_TEMP
);
592 for (j
= 0; j
< ACPI_PSS_PX_NENTRY
; ++j
) {
593 if (acpi_PkgInt32(pkg
, j
, ptr
[j
]) != 0) {
594 device_printf(dev
, "Can't extract "
595 "_PSS P%d %dth entry\n", i
, j
);
597 kfree(pstate
, M_TEMP
);
601 if (p
->st_freq
& 0x80000000) {
602 device_printf(dev
, "Invalid _PSS P%d freq: 0x%08x\n",
605 kfree(pstate
, M_TEMP
);
613 if (acpi_pstates
== NULL
) {
615 * If no P-State table is created yet,
616 * save the temporary one we just created.
618 acpi_pstates
= pstate
;
619 acpi_npstates
= npstate
;
623 for (i
= 0; i
< acpi_npstates
; ++i
) {
625 "freq %u, pwr %u, xlat %u, blat %u, "
626 "cv %08x, sv %08x\n",
627 acpi_pstates
[i
].st_freq
,
628 acpi_pstates
[i
].st_power
,
629 acpi_pstates
[i
].st_xsit_lat
,
630 acpi_pstates
[i
].st_bm_lat
,
631 acpi_pstates
[i
].st_cval
,
632 acpi_pstates
[i
].st_sval
);
637 * Make sure that P-State tables are same
638 * for all processors.
640 if (memcmp(pstate
, acpi_pstates
,
641 sizeof(*pstate
) * npstate
) != 0) {
642 device_printf(dev
, "Inconsistent _PSS "
643 "cross Processor objects\n");
646 * Some BIOSes create different P-State tables;
647 * just trust the one from the BSP and move on.
649 kfree(pstate
, M_TEMP
);
653 kfree(pstate
, M_TEMP
);
657 /* By default, we start from P-State table's first entry */
661 * Adjust the usable first entry of P-State table,
662 * if there is _PPC object.
664 error
= acpi_pst_eval_ppc(sc
, &sstart
);
665 if (error
&& error
!= ENOENT
)
668 sc
->pst_flags
|= ACPI_PST_FLAG_PPC
;
669 if (acpi_pstate_start
< 0) {
670 acpi_pstate_start
= sstart
;
671 } else if (acpi_pstate_start
!= sstart
) {
672 device_printf(dev
, "_PPC mismatch, was %d, now %d\n",
673 acpi_pstate_start
, sstart
);
674 if (acpi_pstate_start
< sstart
) {
675 device_printf(dev
, "_PPC %d -> %d\n",
676 acpi_pstate_start
, sstart
);
677 acpi_pstate_start
= sstart
;
682 * By default, we assume number of usable P-States is same as
683 * number of P-States.
685 scount
= acpi_npstates
;
688 * Allow users to override or set _PDL
690 if (acpi_pst_pdl
>= 0) {
691 if (acpi_pst_pdl
< acpi_npstates
) {
693 device_printf(dev
, "_PDL override %d\n",
696 scount
= acpi_pst_pdl
+ 1;
699 device_printf(dev
, "Invalid _PDL override %d, "
700 "must be less than %d\n", acpi_pst_pdl
,
706 * Adjust the number of usable entries in P-State table,
707 * if there is _PDL object.
709 error
= acpi_pst_eval_pdl(sc
, &scount
);
710 if (error
&& error
!= ENOENT
)
713 sc
->pst_flags
|= ACPI_PST_FLAG_PDL
;
715 if (acpi_pstate_count
== 0) {
716 acpi_pstate_count
= scount
;
717 } else if (acpi_pstate_count
!= scount
) {
718 device_printf(dev
, "_PDL mismatch, was %d, now %d\n",
719 acpi_pstate_count
, scount
);
720 if (acpi_pstate_count
> scount
) {
721 device_printf(dev
, "_PDL %d -> %d\n",
722 acpi_pstate_count
, scount
);
723 acpi_pstate_count
= scount
;
728 * Some CPUs only have package P-states, but some BIOSes put each
729 * hyperthread to its own P-state domain; allow user to override.
731 if (LIST_EMPTY(&dom
->pd_pstlist
) &&
732 (acpi_pst_force_pkg_domain
||
733 (cpu_vendor_id
== CPU_VENDOR_INTEL
&&
734 acpi_pst_intel_pkg_domain
))) {
737 mask
= get_cpumask_from_level(sc
->pst_cpuid
, CHIP_LEVEL
);
738 if (CPUMASK_TESTNZERO(mask
)) {
739 struct acpi_pst_softc
*pst
= NULL
;
740 struct acpi_pst_domain
*dom1
;
742 LIST_FOREACH(dom1
, &acpi_pst_domains
, pd_link
) {
743 LIST_FOREACH(pst
, &dom1
->pd_pstlist
,
745 if (CPUMASK_TESTBIT(mask
,
753 memcmp(&pst
->pst_creg
, &sc
->pst_creg
,
754 sizeof(sc
->pst_creg
)) == 0 &&
755 memcmp(&pst
->pst_sreg
, &sc
->pst_sreg
,
756 sizeof(sc
->pst_sreg
)) == 0) {
758 * Use the same domain for CPUs in the
761 device_printf(dev
, "Destroy domain%u, "
762 "force pkg domain%u\n",
763 dom
->pd_dom
, dom1
->pd_dom
);
764 LIST_REMOVE(dom
, pd_link
);
765 kfree(dom
, M_DEVBUF
);
768 * Make sure that adding us will not
769 * overflow the domain containing
770 * siblings in the same package.
772 acpi_pst_domain_check_nproc(dev
, dom
);
777 /* Link us with the domain */
778 sc
->pst_domain
= dom
;
779 LIST_INSERT_HEAD(&dom
->pd_pstlist
, sc
, pst_link
);
781 if (device_get_unit(dev
) == 0)
782 AcpiOsExecute(OSL_NOTIFY_HANDLER
, acpi_pst_postattach
, NULL
);
784 if (sc
->pst_flags
& (ACPI_PST_FLAG_PPC
| ACPI_PST_FLAG_PDL
))
785 sc
->pst_parent
->cpu_pst_notify
= acpi_pst_notify
;
790 static struct acpi_pst_domain
*
791 acpi_pst_domain_create_pkg(device_t dev
, ACPI_OBJECT
*obj
)
793 struct acpi_pst_domain
*dom
;
794 uint32_t val
, domain
, coord
, nproc
;
796 if (!ACPI_PKG_VALID_EQ(obj
, 5)) {
797 device_printf(dev
, "Invalid _PSD package\n");
801 /* NumberOfEntries */
802 if (acpi_PkgInt32(obj
, 0, &val
) != 0 || val
!= 5) {
803 device_printf(dev
, "Invalid _PSD NumberOfEntries\n");
808 if (acpi_PkgInt32(obj
, 1, &val
) != 0 || val
!= 0) {
809 device_printf(dev
, "Invalid _PSD Revision\n");
813 if (acpi_PkgInt32(obj
, 2, &domain
) != 0 ||
814 acpi_PkgInt32(obj
, 3, &coord
) != 0 ||
815 acpi_PkgInt32(obj
, 4, &nproc
) != 0) {
816 device_printf(dev
, "Can't extract _PSD package\n");
820 if (!ACPI_PSD_COORD_VALID(coord
)) {
821 device_printf(dev
, "Invalid _PSD CoordType (%#x)\n", coord
);
825 if (nproc
> MAXCPU
) {
827 * If NumProcessors is greater than MAXCPU
828 * and domain's coordination is SWALL, then
829 * we will never be able to start all CPUs
830 * within this domain, and power state
831 * transition will never be completed, so we
832 * just bail out here.
834 if (coord
== ACPI_PSD_COORD_SWALL
) {
835 device_printf(dev
, "Unsupported _PSD NumProcessors "
839 } else if (nproc
== 0) {
840 device_printf(dev
, "_PSD NumProcessors are zero\n");
844 dom
= acpi_pst_domain_find(domain
);
846 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_INT
) {
847 device_printf(dev
, "Mixed Integer _PSD and "
851 if (dom
->pd_coord
!= coord
) {
852 device_printf(dev
, "Inconsistent _PSD coord "
853 "information cross Processor objects\n");
856 if (dom
->pd_nproc
!= nproc
) {
857 device_printf(dev
, "Inconsistent _PSD nproc "
858 "information cross Processor objects\n");
860 * Some stupid BIOSes will set wrong "# of processors",
861 * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
867 dom
= acpi_pst_domain_alloc(domain
, coord
, nproc
);
869 device_printf(dev
, "create pkg domain%u, coord %#x\n",
870 dom
->pd_dom
, dom
->pd_coord
);
876 static struct acpi_pst_domain
*
877 acpi_pst_domain_create_int(device_t dev
, uint32_t domain
)
879 struct acpi_pst_domain
*dom
;
881 dom
= acpi_pst_domain_find(domain
);
883 if ((dom
->pd_flags
& ACPI_PSTDOM_FLAG_INT
) == 0) {
884 device_printf(dev
, "Mixed Package _PSD and "
888 KKASSERT(dom
->pd_coord
== ACPI_PSD_COORD_SWALL
);
894 dom
= acpi_pst_domain_alloc(domain
, ACPI_PSD_COORD_SWALL
, 1);
895 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_INT
;
898 device_printf(dev
, "create int domain%u\n", dom
->pd_dom
);
903 static struct acpi_pst_domain
*
904 acpi_pst_domain_find(uint32_t domain
)
906 struct acpi_pst_domain
*dom
;
908 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
909 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_STUB
)
911 if (dom
->pd_dom
== domain
)
917 static struct acpi_pst_domain
*
918 acpi_pst_domain_alloc(uint32_t domain
, uint32_t coord
, uint32_t nproc
)
920 struct acpi_pst_domain
*dom
;
922 dom
= kmalloc(sizeof(*dom
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
923 dom
->pd_dom
= domain
;
924 dom
->pd_coord
= coord
;
925 dom
->pd_nproc
= nproc
;
926 LIST_INIT(&dom
->pd_pstlist
);
927 lwkt_serialize_init(&dom
->pd_serialize
);
929 LIST_INSERT_HEAD(&acpi_pst_domains
, dom
, pd_link
);
935 acpi_pst_domain_set_pstate_locked(struct acpi_pst_domain
*dom
, int i
, int *global
)
937 const struct acpi_pstate
*pstate
;
938 struct acpi_pst_softc
*sc
;
941 ASSERT_SERIALIZED(&dom
->pd_serialize
);
943 KKASSERT(i
>= 0 && i
< acpi_npstates
);
944 pstate
= &acpi_pstates
[i
];
947 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
949 error
= acpi_pst_set_pstate(sc
, pstate
);
951 device_printf(sc
->pst_dev
, "can't set "
952 "freq %d\n", pstate
->st_freq
);
953 /* XXX error cleanup? */
955 if (dom
->pd_coord
== ACPI_PSD_COORD_SWANY
)
967 acpi_pst_domain_set_pstate(struct acpi_pst_domain
*dom
, int i
, int *global
)
969 lwkt_serialize_enter(&dom
->pd_serialize
);
970 acpi_pst_domain_set_pstate_locked(dom
, i
, global
);
971 lwkt_serialize_exit(&dom
->pd_serialize
);
975 acpi_pst_global_set_pstate(int i
)
977 struct acpi_pst_domain
*dom
;
978 int *global
= &acpi_pst_global_state
;
980 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
981 /* Skip dead domain */
982 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_DEAD
)
984 acpi_pst_domain_set_pstate(dom
, i
, global
);
990 acpi_pst_global_fixup_pstate(void)
992 struct acpi_pst_domain
*dom
;
993 int *global
= &acpi_pst_global_state
;
996 sstart
= acpi_pstate_start
;
997 scount
= acpi_pstate_count
;
999 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
1002 /* Skip dead domain */
1003 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_DEAD
)
1006 lwkt_serialize_enter(&dom
->pd_serialize
);
1008 if (global
!= NULL
) {
1009 if (*global
< sstart
)
1011 else if (*global
>= scount
)
1012 *global
= scount
- 1;
1015 if (dom
->pd_state
< sstart
)
1017 else if (dom
->pd_state
>= scount
)
1020 acpi_pst_domain_set_pstate_locked(dom
, i
, NULL
);
1022 lwkt_serialize_exit(&dom
->pd_serialize
);
1027 acpi_pst_postattach(void *arg __unused
)
1029 struct acpi_pst_domain
*dom
;
1030 struct acpi_cpu_softc
*cpu
;
1032 int i
, ndevices
, error
, has_domain
;
1036 error
= devclass_get_devices(acpi_pst_devclass
, &devices
, &ndevices
);
1044 for (i
= 0; i
< ndevices
; ++i
) {
1045 cpu
= device_get_softc(device_get_parent(devices
[i
]));
1046 if (cpu
->glob_sysctl_tree
!= NULL
)
1049 kfree(devices
, M_TEMP
);
1050 KKASSERT(cpu
!= NULL
);
1052 if (acpi_pst_md
== NULL
)
1053 kprintf("ACPI: no P-State CPU driver\n");
1056 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
1057 struct acpi_pst_softc
*sc
;
1060 dom
->pd_state
= acpi_pstate_start
;
1063 * Make sure that all processors belonging to this
1064 * domain are located.
1067 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1068 sc
->pst_state
= acpi_pstate_start
;
1071 if (i
!= dom
->pd_nproc
) {
1072 KKASSERT(i
< dom
->pd_nproc
);
1074 kprintf("ACPI: domain%u misses processors, "
1075 "should be %d, got %d\n", dom
->pd_dom
,
1077 if (dom
->pd_coord
== ACPI_PSD_COORD_SWALL
) {
1079 * If this domain's coordination is
1080 * SWALL and we don't see all of the
1081 * member CPUs of this domain, then
1082 * the P-State transition will never
1083 * be completed, so just leave this
1086 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_DEAD
;
1093 * Validate P-State configurations for this domain
1095 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1096 error
= acpi_pst_check_csr(sc
);
1100 error
= acpi_pst_check_pstates(sc
);
1105 kprintf("ACPI: domain%u P-State configuration "
1106 "check failed\n", dom
->pd_dom
);
1107 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_DEAD
;
1112 * Do necssary P-State initialization
1114 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1115 error
= acpi_pst_init(sc
);
1120 kprintf("ACPI: domain%u P-State initialization "
1121 "check failed\n", dom
->pd_dom
);
1122 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_DEAD
;
1128 ksnprintf(buf
, sizeof(buf
), "px_dom%u", dom
->pd_dom
);
1130 sysctl_ctx_init(&dom
->pd_sysctl_ctx
);
1131 dom
->pd_sysctl_tree
=
1132 SYSCTL_ADD_NODE(&dom
->pd_sysctl_ctx
,
1133 SYSCTL_CHILDREN(cpu
->glob_sysctl_tree
),
1134 OID_AUTO
, buf
, CTLFLAG_RD
, 0,
1136 if (dom
->pd_sysctl_tree
== NULL
) {
1137 kprintf("ACPI: Can't create sysctl tree for domain%u",
1142 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1143 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1144 OID_AUTO
, "available",
1145 CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_SKIP
,
1146 dom
, 0, acpi_pst_sysctl_freqs
, "A",
1147 "available frequencies");
1149 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1150 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1152 CTLTYPE_OPAQUE
| CTLFLAG_RD
,
1153 dom
, 0, acpi_pst_sysctl_freqs_bin
, "IU",
1154 "available frequencies");
1156 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1157 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1159 CTLTYPE_OPAQUE
| CTLFLAG_RD
,
1160 dom
, 0, acpi_pst_sysctl_power
, "IU",
1161 "power of available frequencies");
1163 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1164 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1165 OID_AUTO
, "members",
1166 CTLTYPE_STRING
| CTLFLAG_RD
,
1167 dom
, 0, acpi_pst_sysctl_members
, "A",
1170 if (acpi_pst_md
!= NULL
&&
1171 acpi_pst_md
->pmd_set_pstate
!= NULL
) {
1172 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1173 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1175 CTLTYPE_UINT
| CTLFLAG_RW
,
1176 dom
, 0, acpi_pst_sysctl_select
,
1177 "IU", "select freq");
1181 if (has_domain
&& acpi_pst_md
!= NULL
&&
1182 acpi_pst_md
->pmd_set_pstate
!= NULL
) {
1183 SYSCTL_ADD_PROC(&cpu
->glob_sysctl_ctx
,
1184 SYSCTL_CHILDREN(cpu
->glob_sysctl_tree
),
1185 OID_AUTO
, "px_global",
1186 CTLTYPE_UINT
| CTLFLAG_RW
,
1187 NULL
, 0, acpi_pst_sysctl_global
,
1188 "IU", "select freq for all domains");
1189 SYSCTL_ADD_INT(&cpu
->glob_sysctl_ctx
,
1190 SYSCTL_CHILDREN(cpu
->glob_sysctl_tree
),
1191 OID_AUTO
, "px_handle_notify", CTLFLAG_RW
,
1192 &acpi_pst_handle_notify
, 0,
1193 "handle type 0x80 notify");
1195 acpi_pst_global_set_pstate(acpi_pstate_start
);
1200 acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS
)
1202 int i
, error
, sstart
, scount
;
1205 sstart
= acpi_pstate_start
;
1206 scount
= acpi_pstate_count
;
1207 for (i
= 0; i
< acpi_npstates
; ++i
) {
1208 if (error
== 0 && i
)
1209 error
= SYSCTL_OUT(req
, " ", 1);
1214 if (i
< sstart
|| i
>= scount
)
1219 ksnprintf(buf
, sizeof(buf
), pat
,
1220 acpi_pstates
[i
].st_freq
);
1221 error
= SYSCTL_OUT(req
, buf
, strlen(buf
));
1228 acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS
)
1230 uint32_t freqs
[ACPI_NPSTATE_MAX
];
1231 int cnt
, i
, sstart
, scount
;
1233 sstart
= acpi_pstate_start
;
1234 scount
= acpi_pstate_count
;
1236 cnt
= scount
- sstart
;
1237 for (i
= 0; i
< cnt
; ++i
)
1238 freqs
[i
] = acpi_pstates
[sstart
+ i
].st_freq
;
1240 return sysctl_handle_opaque(oidp
, freqs
, cnt
* sizeof(freqs
[0]), req
);
1244 acpi_pst_sysctl_power(SYSCTL_HANDLER_ARGS
)
1246 uint32_t power
[ACPI_NPSTATE_MAX
];
1247 int cnt
, i
, sstart
, scount
;
1249 sstart
= acpi_pstate_start
;
1250 scount
= acpi_pstate_count
;
1252 cnt
= scount
- sstart
;
1253 for (i
= 0; i
< cnt
; ++i
)
1254 power
[i
] = acpi_pstates
[sstart
+ i
].st_power
;
1256 return sysctl_handle_opaque(oidp
, power
, cnt
* sizeof(power
[0]), req
);
1260 acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS
)
1262 struct acpi_pst_domain
*dom
= arg1
;
1263 struct acpi_pst_softc
*sc
;
1267 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1270 if (error
== 0 && loop
)
1271 error
= SYSCTL_OUT(req
, " ", 1);
1273 ksnprintf(buf
, sizeof(buf
), "cpu%d", sc
->pst_cpuid
);
1274 error
= SYSCTL_OUT(req
, buf
, strlen(buf
));
1277 if (error
== 0 && acpi_pst_md
&& acpi_pst_md
->pmd_get_pstate
) {
1278 const struct acpi_pstate
*pstate
;
1281 pstate
= acpi_pst_get_pstate(sc
);
1282 if (pstate
== NULL
) {
1285 ksnprintf(buf
, sizeof(buf
), "(%d)",
1289 error
= SYSCTL_OUT(req
, str
, strlen(str
));
1297 acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS
)
1299 struct acpi_pst_domain
*dom
= arg1
;
1302 KKASSERT(dom
->pd_state
>= 0 && dom
->pd_state
< acpi_npstates
);
1304 freq
= acpi_pstates
[dom
->pd_state
].st_freq
;
1306 error
= sysctl_handle_int(oidp
, &freq
, 0, req
);
1307 if (error
|| req
->newptr
== NULL
)
1310 i
= acpi_pst_freq2index(freq
);
1314 acpi_pst_domain_set_pstate(dom
, i
, NULL
);
1319 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS
)
1323 KKASSERT(acpi_pst_global_state
>= 0 &&
1324 acpi_pst_global_state
< acpi_npstates
);
1326 freq
= acpi_pstates
[acpi_pst_global_state
].st_freq
;
1328 error
= sysctl_handle_int(oidp
, &freq
, 0, req
);
1329 if (error
|| req
->newptr
== NULL
)
1332 i
= acpi_pst_freq2index(freq
);
1336 acpi_pst_global_set_pstate(i
);
1342 acpi_pst_check_csr_handler(struct cpuhelper_msg
*msg
)
1344 struct acpi_pst_chmsg
*pmsg
= (struct acpi_pst_chmsg
*)msg
;
1347 error
= acpi_pst_md
->pmd_check_csr(pmsg
->ch_ctrl
, pmsg
->ch_status
);
1348 cpuhelper_replymsg(msg
, error
);
1352 acpi_pst_check_csr(struct acpi_pst_softc
*sc
)
1354 struct acpi_pst_chmsg msg
;
1356 if (acpi_pst_md
== NULL
)
1359 cpuhelper_initmsg(&msg
.ch_msg
, &curthread
->td_msgport
,
1360 acpi_pst_check_csr_handler
, NULL
, MSGF_PRIORITY
);
1361 msg
.ch_ctrl
= &sc
->pst_creg
;
1362 msg
.ch_status
= &sc
->pst_sreg
;
1364 return (cpuhelper_domsg(&msg
.ch_msg
, sc
->pst_cpuid
));
1368 acpi_pst_check_pstates_handler(struct cpuhelper_msg
*msg
)
1372 error
= acpi_pst_md
->pmd_check_pstates(acpi_pstates
, acpi_npstates
);
1373 cpuhelper_replymsg(msg
, error
);
1377 acpi_pst_check_pstates(struct acpi_pst_softc
*sc
)
1379 struct cpuhelper_msg msg
;
1381 if (acpi_pst_md
== NULL
)
1384 cpuhelper_initmsg(&msg
, &curthread
->td_msgport
,
1385 acpi_pst_check_pstates_handler
, NULL
, MSGF_PRIORITY
);
1386 return (cpuhelper_domsg(&msg
, sc
->pst_cpuid
));
1390 acpi_pst_init_handler(struct cpuhelper_msg
*msg
)
1392 struct acpi_pst_chmsg
*pmsg
= (struct acpi_pst_chmsg
*)msg
;
1395 error
= acpi_pst_md
->pmd_init(pmsg
->ch_ctrl
, pmsg
->ch_status
);
1396 cpuhelper_replymsg(msg
, error
);
1400 acpi_pst_init(struct acpi_pst_softc
*sc
)
1402 struct acpi_pst_chmsg msg
;
1404 if (acpi_pst_md
== NULL
)
1407 cpuhelper_initmsg(&msg
.ch_msg
, &curthread
->td_msgport
,
1408 acpi_pst_init_handler
, NULL
, MSGF_PRIORITY
);
1409 msg
.ch_ctrl
= &sc
->pst_creg
;
1410 msg
.ch_status
= &sc
->pst_sreg
;
1412 return (cpuhelper_domsg(&msg
.ch_msg
, sc
->pst_cpuid
));
1416 acpi_pst_set_pstate_handler(struct cpuhelper_msg
*msg
)
1418 struct acpi_pst_chmsg
*pmsg
= (struct acpi_pst_chmsg
*)msg
;
1421 error
= acpi_pst_md
->pmd_set_pstate(pmsg
->ch_ctrl
, pmsg
->ch_status
,
1423 cpuhelper_replymsg(msg
, error
);
1427 acpi_pst_set_pstate(struct acpi_pst_softc
*sc
, const struct acpi_pstate
*pstate
)
1429 struct acpi_pst_chmsg msg
;
1431 KKASSERT(acpi_pst_md
!= NULL
);
1433 cpuhelper_initmsg(&msg
.ch_msg
, &curthread
->td_msgport
,
1434 acpi_pst_set_pstate_handler
, __DECONST(void *, pstate
),
1436 msg
.ch_ctrl
= &sc
->pst_creg
;
1437 msg
.ch_status
= &sc
->pst_sreg
;
1439 return (cpuhelper_domsg(&msg
.ch_msg
, sc
->pst_cpuid
));
1443 acpi_pst_get_pstate_handler(struct cpuhelper_msg
*msg
)
1445 struct acpi_pst_chmsg
*pmsg
= (struct acpi_pst_chmsg
*)msg
;
1446 const struct acpi_pstate
*pstate
;
1448 pstate
= acpi_pst_md
->pmd_get_pstate(pmsg
->ch_status
, acpi_pstates
,
1450 msg
->ch_cbarg
= __DECONST(void *, pstate
);
1451 cpuhelper_replymsg(msg
, 0);
1454 static const struct acpi_pstate
*
1455 acpi_pst_get_pstate(struct acpi_pst_softc
*sc
)
1457 struct acpi_pst_chmsg msg
;
1459 if (acpi_pst_md
== NULL
)
1462 cpuhelper_initmsg(&msg
.ch_msg
, &curthread
->td_msgport
,
1463 acpi_pst_get_pstate_handler
, NULL
, MSGF_PRIORITY
);
1464 msg
.ch_status
= &sc
->pst_sreg
;
1466 cpuhelper_domsg(&msg
.ch_msg
, sc
->pst_cpuid
);
1467 return (msg
.ch_msg
.ch_cbarg
);
1471 acpi_pst_alloc_resource(device_t dev
, ACPI_OBJECT
*obj
, int idx
,
1472 struct acpi_pst_res
*res
)
1474 struct acpi_pst_softc
*sc
= device_get_softc(dev
);
1478 error
= acpi_PkgRawGas(obj
, idx
, &res
->pr_gas
);
1482 /* Allocate resource, if possible */
1483 res
->pr_rid
= sc
->pst_parent
->cpu_next_rid
;
1484 acpi_bus_alloc_gas(dev
, &type
, &res
->pr_rid
, &res
->pr_gas
, &res
->pr_res
, 0);
1485 if (res
->pr_res
!= NULL
) {
1486 sc
->pst_parent
->cpu_next_rid
++;
1487 res
->pr_bt
= rman_get_bustag(res
->pr_res
);
1488 res
->pr_bh
= rman_get_bushandle(res
->pr_res
);
1496 acpi_pst_domain_check_nproc(device_t dev
, struct acpi_pst_domain
*dom
)
1498 struct acpi_pst_softc
*pst
;
1502 LIST_FOREACH(pst
, &dom
->pd_pstlist
, pst_link
)
1504 if (i
== dom
->pd_nproc
) {
1506 * Some stupid BIOSes will set wrong "# of processors",
1507 * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
1510 device_printf(dev
, "domain%u already contains %d "
1511 "P-States\n", dom
->pd_dom
, dom
->pd_nproc
);
1515 KKASSERT(i
< dom
->pd_nproc
);
1519 acpi_pst_eval_ppc(struct acpi_pst_softc
*sc
, int *sstart
)
1526 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
1527 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PPC", NULL
, &buf
);
1528 if (!ACPI_FAILURE(status
)) {
1529 ACPI_OBJECT_LIST arglist
;
1532 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
1533 if (obj
->Type
== ACPI_TYPE_INTEGER
) {
1534 if (obj
->Integer
.Value
>= acpi_npstates
) {
1535 device_printf(sc
->pst_dev
,
1536 "Invalid _PPC value\n");
1540 *sstart
= obj
->Integer
.Value
;
1542 device_printf(sc
->pst_dev
, "_PPC %d\n",
1546 device_printf(sc
->pst_dev
, "Invalid _PPC object\n");
1554 /* _PPC has been successfully processed */
1555 arglist
.Pointer
= arg
;
1557 arg
[0].Type
= ACPI_TYPE_INTEGER
;
1558 arg
[0].Integer
.Value
= 0x80;
1559 arg
[1].Type
= ACPI_TYPE_INTEGER
;
1560 arg
[1].Integer
.Value
= 0;
1561 AcpiEvaluateObject(sc
->pst_handle
, "_OST", &arglist
, NULL
);
1569 acpi_pst_eval_pdl(struct acpi_pst_softc
*sc
, int *scount
)
1576 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
1577 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PDL", NULL
, &buf
);
1578 if (!ACPI_FAILURE(status
)) {
1579 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
1580 if (obj
->Type
== ACPI_TYPE_INTEGER
) {
1581 if (obj
->Integer
.Value
>= acpi_npstates
) {
1582 device_printf(sc
->pst_dev
,
1583 "Invalid _PDL value\n");
1587 if (obj
->Integer
.Value
>= acpi_pstate_start
) {
1588 *scount
= obj
->Integer
.Value
+ 1;
1590 device_printf(sc
->pst_dev
, "_PDL %d\n",
1594 /* Prefer _PPC as stated in ACPI 5.1 8.4.4.6 */
1595 device_printf(sc
->pst_dev
, "conflict _PDL %ju "
1596 "and _PPC %d, ignore\n",
1597 (uintmax_t)obj
->Integer
.Value
,
1601 device_printf(sc
->pst_dev
, "Invalid _PDL object\n");
1615 * Notify is serialized by acpi task thread.
1618 acpi_pst_notify(device_t dev
)
1620 struct acpi_pst_softc
*sc
= device_get_softc(dev
);
1621 boolean_t fixup
= FALSE
;
1623 if (!acpi_pst_handle_notify
)
1628 * _PPC and _PDL evaluation order is critical. _PDL
1629 * evaluation depends on _PPC evaluation.
1631 if (sc
->pst_flags
& ACPI_PST_FLAG_PPC
) {
1632 int sstart
= acpi_pstate_start
;
1634 acpi_pst_eval_ppc(sc
, &sstart
);
1635 if (acpi_pstate_start
!= sstart
&& sc
->pst_cpuid
== 0) {
1636 acpi_pstate_start
= sstart
;
1640 if (sc
->pst_flags
& ACPI_PST_FLAG_PDL
) {
1641 int scount
= acpi_pstate_count
;
1643 acpi_pst_eval_pdl(sc
, &scount
);
1644 if (acpi_pstate_count
!= scount
&& sc
->pst_cpuid
== 0) {
1645 acpi_pstate_count
= scount
;
1650 if (fixup
&& acpi_pst_md
!= NULL
&&
1651 acpi_pst_md
->pmd_set_pstate
!= NULL
)
1652 acpi_pst_global_fixup_pstate();