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/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/queue.h>
43 #include <sys/sysctl.h>
44 #include <sys/msgport2.h>
45 #include <sys/cpu_topology.h>
47 #include <net/netisr2.h>
48 #include <net/netmsg2.h>
49 #include <net/if_var.h>
54 #include "acpi_cpu_pstate.h"
56 #define ACPI_NPSTATE_MAX 32
58 #define ACPI_PSS_PX_NENTRY 6
60 #define ACPI_PSD_COORD_SWALL 0xfc
61 #define ACPI_PSD_COORD_SWANY 0xfd
62 #define ACPI_PSD_COORD_HWALL 0xfe
63 #define ACPI_PSD_COORD_VALID(coord) \
64 ((coord) == ACPI_PSD_COORD_SWALL || \
65 (coord) == ACPI_PSD_COORD_SWANY || \
66 (coord) == ACPI_PSD_COORD_HWALL)
68 struct acpi_pst_softc
;
69 LIST_HEAD(acpi_pst_list
, acpi_pst_softc
);
71 struct netmsg_acpi_pst
{
72 struct netmsg_base base
;
73 const struct acpi_pst_res
*ctrl
;
74 const struct acpi_pst_res
*status
;
77 struct acpi_pst_domain
{
81 LIST_ENTRY(acpi_pst_domain
) pd_link
;
85 struct lwkt_serialize pd_serialize
;
88 struct acpi_pst_list pd_pstlist
;
90 struct sysctl_ctx_list pd_sysctl_ctx
;
91 struct sysctl_oid
*pd_sysctl_tree
;
93 LIST_HEAD(acpi_pst_domlist
, acpi_pst_domain
);
95 #define ACPI_PSTDOM_FLAG_STUB 0x1 /* stub domain, no _PSD */
96 #define ACPI_PSTDOM_FLAG_DEAD 0x2 /* domain can't be started */
97 #define ACPI_PSTDOM_FLAG_INT 0x4 /* domain created from Integer _PSD */
99 struct acpi_pst_softc
{
101 struct acpi_cpu_softc
*pst_parent
;
102 struct acpi_pst_domain
*pst_domain
;
103 struct acpi_pst_res pst_creg
;
104 struct acpi_pst_res pst_sreg
;
111 ACPI_HANDLE pst_handle
;
113 LIST_ENTRY(acpi_pst_softc
) pst_link
;
116 #define ACPI_PST_FLAG_PPC 0x1
117 #define ACPI_PST_FLAG_PDL 0x2
119 static int acpi_pst_probe(device_t dev
);
120 static int acpi_pst_attach(device_t dev
);
121 static void acpi_pst_notify(device_t dev
);
123 static void acpi_pst_postattach(void *);
124 static struct acpi_pst_domain
*
125 acpi_pst_domain_create_int(device_t
, uint32_t);
126 static struct acpi_pst_domain
*
127 acpi_pst_domain_create_pkg(device_t
, ACPI_OBJECT
*);
128 static struct acpi_pst_domain
*
129 acpi_pst_domain_find(uint32_t);
130 static struct acpi_pst_domain
*
131 acpi_pst_domain_alloc(uint32_t, uint32_t, uint32_t);
132 static void acpi_pst_domain_set_pstate_locked(struct acpi_pst_domain
*,
134 static void acpi_pst_domain_set_pstate(struct acpi_pst_domain
*, int,
136 static void acpi_pst_domain_check_nproc(device_t
, struct acpi_pst_domain
*);
137 static void acpi_pst_global_set_pstate(int);
138 static void acpi_pst_global_fixup_pstate(void);
140 static int acpi_pst_check_csr(struct acpi_pst_softc
*);
141 static int acpi_pst_check_pstates(struct acpi_pst_softc
*);
142 static int acpi_pst_init(struct acpi_pst_softc
*);
143 static int acpi_pst_set_pstate(struct acpi_pst_softc
*,
144 const struct acpi_pstate
*);
145 static const struct acpi_pstate
*
146 acpi_pst_get_pstate(struct acpi_pst_softc
*);
147 static int acpi_pst_alloc_resource(device_t
, ACPI_OBJECT
*, int,
148 struct acpi_pst_res
*);
149 static int acpi_pst_eval_ppc(struct acpi_pst_softc
*, int *);
150 static int acpi_pst_eval_pdl(struct acpi_pst_softc
*, int *);
152 static void acpi_pst_check_csr_handler(netmsg_t
);
153 static void acpi_pst_check_pstates_handler(netmsg_t
);
154 static void acpi_pst_init_handler(netmsg_t
);
155 static void acpi_pst_set_pstate_handler(netmsg_t
);
156 static void acpi_pst_get_pstate_handler(netmsg_t
);
158 static int acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS
);
159 static int acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS
);
160 static int acpi_pst_sysctl_power(SYSCTL_HANDLER_ARGS
);
161 static int acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS
);
162 static int acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS
);
163 static int acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS
);
165 static struct acpi_pst_domlist acpi_pst_domains
=
166 LIST_HEAD_INITIALIZER(acpi_pst_domains
);
167 static int acpi_pst_domain_id
;
169 static int acpi_pst_global_state
;
171 static int acpi_pstate_start
= -1;
172 static int acpi_pstate_count
;
173 static int acpi_npstates
;
174 static struct acpi_pstate
*acpi_pstates
;
176 static const struct acpi_pst_md
*acpi_pst_md
;
178 static int acpi_pst_pdl
= -1;
179 TUNABLE_INT("hw.acpi.cpu.pst.pdl", &acpi_pst_pdl
);
181 static int acpi_pst_ht_reuse_domain
= 1;
182 TUNABLE_INT("hw.acpi.cpu.pst.ht_reuse_domain", &acpi_pst_ht_reuse_domain
);
184 static int acpi_pst_force_pkg_domain
= 0;
185 TUNABLE_INT("hw.acpi.cpu.pst.force_pkg_domain", &acpi_pst_force_pkg_domain
);
187 static int acpi_pst_handle_notify
= 1;
188 TUNABLE_INT("hw.acpi.cpu.pst.handle_notify", &acpi_pst_handle_notify
);
191 * Force CPU package power domain for Intel CPUs.
193 * As of this write (14 July 2015), all Intel CPUs only have CPU package
196 static int acpi_pst_intel_pkg_domain
= 1;
197 TUNABLE_INT("hw.acpi.cpu.pst.intel_pkg_domain", &acpi_pst_intel_pkg_domain
);
199 static device_method_t acpi_pst_methods
[] = {
200 /* Device interface */
201 DEVMETHOD(device_probe
, acpi_pst_probe
),
202 DEVMETHOD(device_attach
, acpi_pst_attach
),
203 DEVMETHOD(device_detach
, bus_generic_detach
),
204 DEVMETHOD(device_shutdown
, bus_generic_shutdown
),
205 DEVMETHOD(device_suspend
, bus_generic_suspend
),
206 DEVMETHOD(device_resume
, bus_generic_resume
),
209 DEVMETHOD(bus_add_child
, bus_generic_add_child
),
210 DEVMETHOD(bus_print_child
, bus_generic_print_child
),
211 DEVMETHOD(bus_read_ivar
, bus_generic_read_ivar
),
212 DEVMETHOD(bus_write_ivar
, bus_generic_write_ivar
),
213 DEVMETHOD(bus_get_resource_list
, bus_generic_get_resource_list
),
214 DEVMETHOD(bus_set_resource
, bus_generic_rl_set_resource
),
215 DEVMETHOD(bus_get_resource
, bus_generic_rl_get_resource
),
216 DEVMETHOD(bus_alloc_resource
, bus_generic_alloc_resource
),
217 DEVMETHOD(bus_release_resource
, bus_generic_release_resource
),
218 DEVMETHOD(bus_driver_added
, bus_generic_driver_added
),
219 DEVMETHOD(bus_activate_resource
, bus_generic_activate_resource
),
220 DEVMETHOD(bus_deactivate_resource
, bus_generic_deactivate_resource
),
221 DEVMETHOD(bus_setup_intr
, bus_generic_setup_intr
),
222 DEVMETHOD(bus_teardown_intr
, bus_generic_teardown_intr
),
227 static driver_t acpi_pst_driver
= {
230 sizeof(struct acpi_pst_softc
)
233 static devclass_t acpi_pst_devclass
;
234 DRIVER_MODULE(cpu_pst
, cpu
, acpi_pst_driver
, acpi_pst_devclass
, NULL
, NULL
);
235 MODULE_DEPEND(cpu_pst
, acpi
, 1, 1, 1);
238 acpi_pst_freq2index(int freq
)
242 for (i
= 0; i
< acpi_npstates
; ++i
) {
243 if (acpi_pstates
[i
].st_freq
== freq
)
250 acpi_pst_probe(device_t dev
)
257 if (acpi_disabled("cpu_pst") ||
258 acpi_get_type(dev
) != ACPI_TYPE_PROCESSOR
)
261 if (acpi_pst_md
== NULL
)
262 acpi_pst_md
= acpi_pst_md_probe();
264 handle
= acpi_get_handle(dev
);
270 * Some BIOSes do not expose _PCT for the second thread of
271 * CPU cores. In this case, _PSD should be enough to get the
272 * P-state of the second thread working, since it must have
273 * the same _PCT and _PSS as the first thread in the same
277 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
278 status
= AcpiEvaluateObject(handle
, "_PSD", NULL
, &buf
);
279 if (!ACPI_FAILURE(status
)) {
280 AcpiOsFree((ACPI_OBJECT
*)buf
.Pointer
);
288 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
289 status
= AcpiEvaluateObject(handle
, "_PCT", NULL
, &buf
);
290 if (ACPI_FAILURE(status
)) {
292 device_printf(dev
, "Can't get _PCT package - %s\n",
293 AcpiFormatException(status
));
298 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
299 if (!ACPI_PKG_VALID_EQ(obj
, 2)) {
300 device_printf(dev
, "Invalid _PCT package\n");
310 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
311 status
= AcpiEvaluateObject(handle
, "_PSS", NULL
, &buf
);
312 if (ACPI_FAILURE(status
)) {
313 device_printf(dev
, "Can't get _PSS package - %s\n",
314 AcpiFormatException(status
));
318 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
319 if (!ACPI_PKG_VALID(obj
, 1)) {
320 device_printf(dev
, "Invalid _PSS package\n");
327 device_set_desc(dev
, "ACPI CPU P-State");
332 acpi_pst_attach(device_t dev
)
334 struct acpi_pst_softc
*sc
= device_get_softc(dev
);
335 struct acpi_pst_domain
*dom
= NULL
;
339 struct acpi_pstate
*pstate
, *p
;
340 int i
, npstate
, error
, sstart
, scount
;
343 sc
->pst_parent
= device_get_softc(device_get_parent(dev
));
344 sc
->pst_handle
= acpi_get_handle(dev
);
345 sc
->pst_cpuid
= acpi_get_magic(dev
);
348 * If there is a _PSD, then we create procossor domain
349 * accordingly. If there is no _PSD, we just fake a
350 * default processor domain0.
353 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
354 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PSD", NULL
, &buf
);
355 if (!ACPI_FAILURE(status
)) {
356 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
358 if (acpi_pst_domain_id
> 0) {
359 device_printf(dev
, "Missing _PSD for certain CPUs\n");
363 acpi_pst_domain_id
= -1;
365 if (ACPI_PKG_VALID_EQ(obj
, 1)) {
366 dom
= acpi_pst_domain_create_pkg(dev
,
367 &obj
->Package
.Elements
[0]);
373 if (obj
->Type
!= ACPI_TYPE_INTEGER
) {
375 "Invalid _PSD package, Type 0x%x\n",
380 device_printf(dev
, "Integer _PSD %ju\n",
381 (uintmax_t)obj
->Integer
.Value
);
382 dom
= acpi_pst_domain_create_int(dev
,
392 AcpiOsFree(buf
.Pointer
);
394 if (acpi_pst_domain_id
< 0) {
395 device_printf(dev
, "Missing _PSD for cpu%d\n",
401 * Create a stub one processor domain for each processor
403 dom
= acpi_pst_domain_alloc(acpi_pst_domain_id
,
404 ACPI_PSD_COORD_SWANY
, 1);
405 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_STUB
;
407 ++acpi_pst_domain_id
;
410 /* Make sure that adding us will not overflow our domain */
411 acpi_pst_domain_check_nproc(dev
, dom
);
414 * Get control/status registers from _PCT
417 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
418 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PCT", NULL
, &buf
);
419 if (ACPI_FAILURE(status
)) {
420 struct acpi_pst_softc
*pst
;
423 * No _PCT. See the comment in acpi_pst_probe() near
426 * Use control/status registers of another CPU in the
427 * same domain, or in the same core, if the type of
428 * these registers are "Fixed Hardware", e.g. on most
429 * of the model Intel CPUs.
431 pst
= LIST_FIRST(&dom
->pd_pstlist
);
435 mask
= get_cpumask_from_level(sc
->pst_cpuid
,
437 if (CPUMASK_TESTNZERO(mask
)) {
438 struct acpi_pst_domain
*dom1
;
440 LIST_FOREACH(dom1
, &acpi_pst_domains
, pd_link
) {
441 LIST_FOREACH(pst
, &dom1
->pd_pstlist
,
443 if (CPUMASK_TESTBIT(mask
,
450 if (pst
!= NULL
&& acpi_pst_ht_reuse_domain
) {
452 * Use the same domain for CPUs in the
455 device_printf(dev
, "Destroy domain%u, "
457 dom
->pd_dom
, dom1
->pd_dom
);
458 LIST_REMOVE(dom
, pd_link
);
459 kfree(dom
, M_DEVBUF
);
462 * Make sure that adding us will not
463 * overflow the domain containing
464 * siblings in the same core.
466 acpi_pst_domain_check_nproc(dev
, dom
);
471 pst
->pst_creg
.pr_res
== NULL
&&
472 pst
->pst_creg
.pr_rid
== 0 &&
473 pst
->pst_creg
.pr_gas
.SpaceId
==
474 ACPI_ADR_SPACE_FIXED_HARDWARE
&&
475 pst
->pst_sreg
.pr_res
== NULL
&&
476 pst
->pst_sreg
.pr_rid
== 0 &&
477 pst
->pst_sreg
.pr_gas
.SpaceId
==
478 ACPI_ADR_SPACE_FIXED_HARDWARE
) {
479 sc
->pst_creg
= pst
->pst_creg
;
480 sc
->pst_sreg
= pst
->pst_sreg
;
482 "No _PCT; reuse %s control/status regs\n",
483 device_get_nameunit(pst
->pst_dev
));
486 device_printf(dev
, "Can't get _PCT package - %s\n",
487 AcpiFormatException(status
));
491 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
492 if (!ACPI_PKG_VALID_EQ(obj
, 2)) {
493 device_printf(dev
, "Invalid _PCT package\n");
498 /* Save and try allocating control register */
499 error
= acpi_pst_alloc_resource(dev
, obj
, 0, &sc
->pst_creg
);
505 device_printf(dev
, "control reg %d %jx\n",
506 sc
->pst_creg
.pr_gas
.SpaceId
,
507 (uintmax_t)sc
->pst_creg
.pr_gas
.Address
);
510 /* Save and try allocating status register */
511 error
= acpi_pst_alloc_resource(dev
, obj
, 1, &sc
->pst_sreg
);
517 device_printf(dev
, "status reg %d %jx\n",
518 sc
->pst_sreg
.pr_gas
.SpaceId
,
519 (uintmax_t)sc
->pst_sreg
.pr_gas
.Address
);
527 * Create P-State table according to _PSS
530 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
531 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PSS", NULL
, &buf
);
532 if (ACPI_FAILURE(status
)) {
534 * No _PSS. See the comment in acpi_pst_probe() near
537 * Assume _PSS are same across all CPUs; well, they
538 * should/have to be so.
540 if (acpi_npstates
> 0 && acpi_pstates
!= NULL
) {
541 device_printf(dev
, "No _PSS\n");
544 device_printf(dev
, "Can't get _PSS package - %s\n",
545 AcpiFormatException(status
));
549 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
550 if (!ACPI_PKG_VALID(obj
, 1)) {
551 device_printf(dev
, "Invalid _PSS package\n");
556 /* Don't create too many P-States */
557 npstate
= obj
->Package
.Count
;
558 if (npstate
> ACPI_NPSTATE_MAX
) {
559 device_printf(dev
, "Too many P-States, %d->%d\n",
560 npstate
, ACPI_NPSTATE_MAX
);
561 npstate
= ACPI_NPSTATE_MAX
;
565 * If we have already created P-State table,
566 * we must make sure that number of entries
569 if (acpi_pstates
!= NULL
&& acpi_npstates
!= npstate
) {
570 device_printf(dev
, "Inconsistent # of P-States "
571 "cross Processor objects\n");
577 * Create a temporary P-State table
579 pstate
= kmalloc(sizeof(*pstate
) * npstate
, M_TEMP
, M_WAITOK
);
580 for (i
= 0, p
= pstate
; i
< npstate
; ++i
, ++p
) {
582 uint32_t *ptr
[ACPI_PSS_PX_NENTRY
] = {
583 &p
->st_freq
, &p
->st_power
, &p
->st_xsit_lat
,
584 &p
->st_bm_lat
, &p
->st_cval
, &p
->st_sval
588 pkg
= &obj
->Package
.Elements
[i
];
589 if (!ACPI_PKG_VALID(pkg
, ACPI_PSS_PX_NENTRY
)) {
590 device_printf(dev
, "Invalud _PSS P%d\n", i
);
592 kfree(pstate
, M_TEMP
);
595 for (j
= 0; j
< ACPI_PSS_PX_NENTRY
; ++j
) {
596 if (acpi_PkgInt32(pkg
, j
, ptr
[j
]) != 0) {
597 device_printf(dev
, "Can't extract "
598 "_PSS P%d %dth entry\n", i
, j
);
600 kfree(pstate
, M_TEMP
);
609 if (acpi_pstates
== NULL
) {
611 * If no P-State table is created yet,
612 * save the temporary one we just created.
614 acpi_pstates
= pstate
;
615 acpi_npstates
= npstate
;
619 for (i
= 0; i
< acpi_npstates
; ++i
) {
621 "freq %u, pwr %u, xlat %u, blat %u, "
622 "cv %08x, sv %08x\n",
623 acpi_pstates
[i
].st_freq
,
624 acpi_pstates
[i
].st_power
,
625 acpi_pstates
[i
].st_xsit_lat
,
626 acpi_pstates
[i
].st_bm_lat
,
627 acpi_pstates
[i
].st_cval
,
628 acpi_pstates
[i
].st_sval
);
633 * Make sure that P-State tables are same
634 * for all processors.
636 if (memcmp(pstate
, acpi_pstates
,
637 sizeof(*pstate
) * npstate
) != 0) {
638 device_printf(dev
, "Inconsistent _PSS "
639 "cross Processor objects\n");
642 * Some BIOSes create different P-State tables;
643 * just trust the one from the BSP and move on.
645 kfree(pstate
, M_TEMP
);
649 kfree(pstate
, M_TEMP
);
653 /* By default, we start from P-State table's first entry */
657 * Adjust the usable first entry of P-State table,
658 * if there is _PPC object.
660 error
= acpi_pst_eval_ppc(sc
, &sstart
);
661 if (error
&& error
!= ENOENT
)
664 sc
->pst_flags
|= ACPI_PST_FLAG_PPC
;
665 if (acpi_pstate_start
< 0) {
666 acpi_pstate_start
= sstart
;
667 } else if (acpi_pstate_start
!= sstart
) {
668 device_printf(dev
, "_PPC mismatch, was %d, now %d\n",
669 acpi_pstate_start
, sstart
);
670 if (acpi_pstate_start
< sstart
) {
671 device_printf(dev
, "_PPC %d -> %d\n",
672 acpi_pstate_start
, sstart
);
673 acpi_pstate_start
= sstart
;
678 * By default, we assume number of usable P-States is same as
679 * number of P-States.
681 scount
= acpi_npstates
;
684 * Allow users to override or set _PDL
686 if (acpi_pst_pdl
>= 0) {
687 if (acpi_pst_pdl
< acpi_npstates
) {
689 device_printf(dev
, "_PDL override %d\n",
692 scount
= acpi_pst_pdl
+ 1;
695 device_printf(dev
, "Invalid _PDL override %d, "
696 "must be less than %d\n", acpi_pst_pdl
,
702 * Adjust the number of usable entries in P-State table,
703 * if there is _PDL object.
705 error
= acpi_pst_eval_pdl(sc
, &scount
);
706 if (error
&& error
!= ENOENT
)
709 sc
->pst_flags
|= ACPI_PST_FLAG_PDL
;
711 if (acpi_pstate_count
== 0) {
712 acpi_pstate_count
= scount
;
713 } else if (acpi_pstate_count
!= scount
) {
714 device_printf(dev
, "_PDL mismatch, was %d, now %d\n",
715 acpi_pstate_count
, scount
);
716 if (acpi_pstate_count
> scount
) {
717 device_printf(dev
, "_PDL %d -> %d\n",
718 acpi_pstate_count
, scount
);
719 acpi_pstate_count
= scount
;
724 * Some CPUs only have package P-states, but some BIOSes put each
725 * hyperthread to its own P-state domain; allow user to override.
727 if (LIST_EMPTY(&dom
->pd_pstlist
) &&
728 (acpi_pst_force_pkg_domain
||
729 (cpu_vendor_id
== CPU_VENDOR_INTEL
&&
730 acpi_pst_intel_pkg_domain
))) {
733 mask
= get_cpumask_from_level(sc
->pst_cpuid
, CHIP_LEVEL
);
734 if (CPUMASK_TESTNZERO(mask
)) {
735 struct acpi_pst_softc
*pst
= NULL
;
736 struct acpi_pst_domain
*dom1
;
738 LIST_FOREACH(dom1
, &acpi_pst_domains
, pd_link
) {
739 LIST_FOREACH(pst
, &dom1
->pd_pstlist
,
741 if (CPUMASK_TESTBIT(mask
,
749 memcmp(&pst
->pst_creg
, &sc
->pst_creg
,
750 sizeof(sc
->pst_creg
)) == 0 &&
751 memcmp(&pst
->pst_sreg
, &sc
->pst_sreg
,
752 sizeof(sc
->pst_sreg
)) == 0) {
754 * Use the same domain for CPUs in the
757 device_printf(dev
, "Destroy domain%u, "
758 "force pkg domain%u\n",
759 dom
->pd_dom
, dom1
->pd_dom
);
760 LIST_REMOVE(dom
, pd_link
);
761 kfree(dom
, M_DEVBUF
);
764 * Make sure that adding us will not
765 * overflow the domain containing
766 * siblings in the same package.
768 acpi_pst_domain_check_nproc(dev
, dom
);
773 /* Link us with the domain */
774 sc
->pst_domain
= dom
;
775 LIST_INSERT_HEAD(&dom
->pd_pstlist
, sc
, pst_link
);
777 if (device_get_unit(dev
) == 0)
778 AcpiOsExecute(OSL_NOTIFY_HANDLER
, acpi_pst_postattach
, NULL
);
780 if (sc
->pst_flags
& (ACPI_PST_FLAG_PPC
| ACPI_PST_FLAG_PDL
))
781 sc
->pst_parent
->cpu_pst_notify
= acpi_pst_notify
;
786 static struct acpi_pst_domain
*
787 acpi_pst_domain_create_pkg(device_t dev
, ACPI_OBJECT
*obj
)
789 struct acpi_pst_domain
*dom
;
790 uint32_t val
, domain
, coord
, nproc
;
792 if (!ACPI_PKG_VALID_EQ(obj
, 5)) {
793 device_printf(dev
, "Invalid _PSD package\n");
797 /* NumberOfEntries */
798 if (acpi_PkgInt32(obj
, 0, &val
) != 0 || val
!= 5) {
799 device_printf(dev
, "Invalid _PSD NumberOfEntries\n");
804 if (acpi_PkgInt32(obj
, 1, &val
) != 0 || val
!= 0) {
805 device_printf(dev
, "Invalid _PSD Revision\n");
809 if (acpi_PkgInt32(obj
, 2, &domain
) != 0 ||
810 acpi_PkgInt32(obj
, 3, &coord
) != 0 ||
811 acpi_PkgInt32(obj
, 4, &nproc
) != 0) {
812 device_printf(dev
, "Can't extract _PSD package\n");
816 if (!ACPI_PSD_COORD_VALID(coord
)) {
817 device_printf(dev
, "Invalid _PSD CoordType (%#x)\n", coord
);
821 if (nproc
> MAXCPU
) {
823 * If NumProcessors is greater than MAXCPU
824 * and domain's coordination is SWALL, then
825 * we will never be able to start all CPUs
826 * within this domain, and power state
827 * transition will never be completed, so we
828 * just bail out here.
830 if (coord
== ACPI_PSD_COORD_SWALL
) {
831 device_printf(dev
, "Unsupported _PSD NumProcessors "
835 } else if (nproc
== 0) {
836 device_printf(dev
, "_PSD NumProcessors are zero\n");
840 dom
= acpi_pst_domain_find(domain
);
842 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_INT
) {
843 device_printf(dev
, "Mixed Integer _PSD and "
847 if (dom
->pd_coord
!= coord
) {
848 device_printf(dev
, "Inconsistent _PSD coord "
849 "information cross Processor objects\n");
852 if (dom
->pd_nproc
!= nproc
) {
853 device_printf(dev
, "Inconsistent _PSD nproc "
854 "information cross Processor objects\n");
856 * Some stupid BIOSes will set wrong "# of processors",
857 * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
863 dom
= acpi_pst_domain_alloc(domain
, coord
, nproc
);
865 device_printf(dev
, "create pkg domain%u, coord %#x\n",
866 dom
->pd_dom
, dom
->pd_coord
);
872 static struct acpi_pst_domain
*
873 acpi_pst_domain_create_int(device_t dev
, uint32_t domain
)
875 struct acpi_pst_domain
*dom
;
877 dom
= acpi_pst_domain_find(domain
);
879 if ((dom
->pd_flags
& ACPI_PSTDOM_FLAG_INT
) == 0) {
880 device_printf(dev
, "Mixed Package _PSD and "
884 KKASSERT(dom
->pd_coord
== ACPI_PSD_COORD_SWALL
);
890 dom
= acpi_pst_domain_alloc(domain
, ACPI_PSD_COORD_SWALL
, 1);
891 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_INT
;
894 device_printf(dev
, "create int domain%u\n", dom
->pd_dom
);
899 static struct acpi_pst_domain
*
900 acpi_pst_domain_find(uint32_t domain
)
902 struct acpi_pst_domain
*dom
;
904 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
905 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_STUB
)
907 if (dom
->pd_dom
== domain
)
913 static struct acpi_pst_domain
*
914 acpi_pst_domain_alloc(uint32_t domain
, uint32_t coord
, uint32_t nproc
)
916 struct acpi_pst_domain
*dom
;
918 dom
= kmalloc(sizeof(*dom
), M_DEVBUF
, M_WAITOK
| M_ZERO
);
919 dom
->pd_dom
= domain
;
920 dom
->pd_coord
= coord
;
921 dom
->pd_nproc
= nproc
;
922 LIST_INIT(&dom
->pd_pstlist
);
923 lwkt_serialize_init(&dom
->pd_serialize
);
925 LIST_INSERT_HEAD(&acpi_pst_domains
, dom
, pd_link
);
931 acpi_pst_domain_set_pstate_locked(struct acpi_pst_domain
*dom
, int i
, int *global
)
933 const struct acpi_pstate
*pstate
;
934 struct acpi_pst_softc
*sc
;
937 ASSERT_SERIALIZED(&dom
->pd_serialize
);
939 KKASSERT(i
>= 0 && i
< acpi_npstates
);
940 pstate
= &acpi_pstates
[i
];
943 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
945 error
= acpi_pst_set_pstate(sc
, pstate
);
947 device_printf(sc
->pst_dev
, "can't set "
948 "freq %d\n", pstate
->st_freq
);
949 /* XXX error cleanup? */
951 if (dom
->pd_coord
== ACPI_PSD_COORD_SWANY
)
963 acpi_pst_domain_set_pstate(struct acpi_pst_domain
*dom
, int i
, int *global
)
965 lwkt_serialize_enter(&dom
->pd_serialize
);
966 acpi_pst_domain_set_pstate_locked(dom
, i
, global
);
967 lwkt_serialize_exit(&dom
->pd_serialize
);
971 acpi_pst_global_set_pstate(int i
)
973 struct acpi_pst_domain
*dom
;
974 int *global
= &acpi_pst_global_state
;
976 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
977 /* Skip dead domain */
978 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_DEAD
)
980 acpi_pst_domain_set_pstate(dom
, i
, global
);
986 acpi_pst_global_fixup_pstate(void)
988 struct acpi_pst_domain
*dom
;
989 int *global
= &acpi_pst_global_state
;
992 sstart
= acpi_pstate_start
;
993 scount
= acpi_pstate_count
;
995 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
998 /* Skip dead domain */
999 if (dom
->pd_flags
& ACPI_PSTDOM_FLAG_DEAD
)
1002 lwkt_serialize_enter(&dom
->pd_serialize
);
1004 if (global
!= NULL
) {
1005 if (*global
< sstart
)
1007 else if (*global
>= scount
)
1008 *global
= scount
- 1;
1011 if (dom
->pd_state
< sstart
)
1013 else if (dom
->pd_state
>= scount
)
1016 acpi_pst_domain_set_pstate_locked(dom
, i
, NULL
);
1018 lwkt_serialize_exit(&dom
->pd_serialize
);
1023 acpi_pst_postattach(void *arg __unused
)
1025 struct acpi_pst_domain
*dom
;
1026 struct acpi_cpu_softc
*cpu
;
1028 int i
, ndevices
, error
, has_domain
;
1032 error
= devclass_get_devices(acpi_pst_devclass
, &devices
, &ndevices
);
1040 for (i
= 0; i
< ndevices
; ++i
) {
1041 cpu
= device_get_softc(device_get_parent(devices
[i
]));
1042 if (cpu
->glob_sysctl_tree
!= NULL
)
1045 kfree(devices
, M_TEMP
);
1046 KKASSERT(cpu
!= NULL
);
1048 if (acpi_pst_md
== NULL
)
1049 kprintf("ACPI: no P-State CPU driver\n");
1052 LIST_FOREACH(dom
, &acpi_pst_domains
, pd_link
) {
1053 struct acpi_pst_softc
*sc
;
1056 dom
->pd_state
= acpi_pstate_start
;
1059 * Make sure that all processors belonging to this
1060 * domain are located.
1063 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1064 sc
->pst_state
= acpi_pstate_start
;
1067 if (i
!= dom
->pd_nproc
) {
1068 KKASSERT(i
< dom
->pd_nproc
);
1070 kprintf("ACPI: domain%u misses processors, "
1071 "should be %d, got %d\n", dom
->pd_dom
,
1073 if (dom
->pd_coord
== ACPI_PSD_COORD_SWALL
) {
1075 * If this domain's coordination is
1076 * SWALL and we don't see all of the
1077 * member CPUs of this domain, then
1078 * the P-State transition will never
1079 * be completed, so just leave this
1082 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_DEAD
;
1089 * Validate P-State configurations for this domain
1091 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1092 error
= acpi_pst_check_csr(sc
);
1096 error
= acpi_pst_check_pstates(sc
);
1101 kprintf("ACPI: domain%u P-State configuration "
1102 "check failed\n", dom
->pd_dom
);
1103 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_DEAD
;
1108 * Do necssary P-State initialization
1110 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1111 error
= acpi_pst_init(sc
);
1116 kprintf("ACPI: domain%u P-State initialization "
1117 "check failed\n", dom
->pd_dom
);
1118 dom
->pd_flags
|= ACPI_PSTDOM_FLAG_DEAD
;
1124 ksnprintf(buf
, sizeof(buf
), "px_dom%u", dom
->pd_dom
);
1126 sysctl_ctx_init(&dom
->pd_sysctl_ctx
);
1127 dom
->pd_sysctl_tree
=
1128 SYSCTL_ADD_NODE(&dom
->pd_sysctl_ctx
,
1129 SYSCTL_CHILDREN(cpu
->glob_sysctl_tree
),
1130 OID_AUTO
, buf
, CTLFLAG_RD
, 0,
1132 if (dom
->pd_sysctl_tree
== NULL
) {
1133 kprintf("ACPI: Can't create sysctl tree for domain%u",
1138 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1139 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1140 OID_AUTO
, "available",
1141 CTLTYPE_STRING
| CTLFLAG_RD
| CTLFLAG_SKIP
,
1142 dom
, 0, acpi_pst_sysctl_freqs
, "A",
1143 "available frequencies");
1145 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1146 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1148 CTLTYPE_OPAQUE
| CTLFLAG_RD
,
1149 dom
, 0, acpi_pst_sysctl_freqs_bin
, "IU",
1150 "available frequencies");
1152 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1153 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1155 CTLTYPE_OPAQUE
| CTLFLAG_RD
,
1156 dom
, 0, acpi_pst_sysctl_power
, "IU",
1157 "power of available frequencies");
1159 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1160 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1161 OID_AUTO
, "members",
1162 CTLTYPE_STRING
| CTLFLAG_RD
,
1163 dom
, 0, acpi_pst_sysctl_members
, "A",
1166 if (acpi_pst_md
!= NULL
&&
1167 acpi_pst_md
->pmd_set_pstate
!= NULL
) {
1168 SYSCTL_ADD_PROC(&dom
->pd_sysctl_ctx
,
1169 SYSCTL_CHILDREN(dom
->pd_sysctl_tree
),
1171 CTLTYPE_UINT
| CTLFLAG_RW
,
1172 dom
, 0, acpi_pst_sysctl_select
,
1173 "IU", "select freq");
1177 if (has_domain
&& acpi_pst_md
!= NULL
&&
1178 acpi_pst_md
->pmd_set_pstate
!= NULL
) {
1179 SYSCTL_ADD_PROC(&cpu
->glob_sysctl_ctx
,
1180 SYSCTL_CHILDREN(cpu
->glob_sysctl_tree
),
1181 OID_AUTO
, "px_global",
1182 CTLTYPE_UINT
| CTLFLAG_RW
,
1183 NULL
, 0, acpi_pst_sysctl_global
,
1184 "IU", "select freq for all domains");
1185 SYSCTL_ADD_INT(&cpu
->glob_sysctl_ctx
,
1186 SYSCTL_CHILDREN(cpu
->glob_sysctl_tree
),
1187 OID_AUTO
, "px_handle_notify", CTLFLAG_RW
,
1188 &acpi_pst_handle_notify
, 0,
1189 "handle type 0x80 notify");
1191 acpi_pst_global_set_pstate(acpi_pstate_start
);
1196 acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS
)
1198 int i
, error
, sstart
, scount
;
1201 sstart
= acpi_pstate_start
;
1202 scount
= acpi_pstate_count
;
1203 for (i
= 0; i
< acpi_npstates
; ++i
) {
1204 if (error
== 0 && i
)
1205 error
= SYSCTL_OUT(req
, " ", 1);
1210 if (i
< sstart
|| i
>= scount
)
1215 ksnprintf(buf
, sizeof(buf
), pat
,
1216 acpi_pstates
[i
].st_freq
);
1217 error
= SYSCTL_OUT(req
, buf
, strlen(buf
));
1224 acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS
)
1226 uint32_t freqs
[ACPI_NPSTATE_MAX
];
1227 int cnt
, i
, sstart
, scount
;
1229 sstart
= acpi_pstate_start
;
1230 scount
= acpi_pstate_count
;
1232 cnt
= scount
- sstart
;
1233 for (i
= 0; i
< cnt
; ++i
)
1234 freqs
[i
] = acpi_pstates
[sstart
+ i
].st_freq
;
1236 return sysctl_handle_opaque(oidp
, freqs
, cnt
* sizeof(freqs
[0]), req
);
1240 acpi_pst_sysctl_power(SYSCTL_HANDLER_ARGS
)
1242 uint32_t power
[ACPI_NPSTATE_MAX
];
1243 int cnt
, i
, sstart
, scount
;
1245 sstart
= acpi_pstate_start
;
1246 scount
= acpi_pstate_count
;
1248 cnt
= scount
- sstart
;
1249 for (i
= 0; i
< cnt
; ++i
)
1250 power
[i
] = acpi_pstates
[sstart
+ i
].st_power
;
1252 return sysctl_handle_opaque(oidp
, power
, cnt
* sizeof(power
[0]), req
);
1256 acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS
)
1258 struct acpi_pst_domain
*dom
= arg1
;
1259 struct acpi_pst_softc
*sc
;
1263 LIST_FOREACH(sc
, &dom
->pd_pstlist
, pst_link
) {
1266 if (error
== 0 && loop
)
1267 error
= SYSCTL_OUT(req
, " ", 1);
1269 ksnprintf(buf
, sizeof(buf
), "cpu%d", sc
->pst_cpuid
);
1270 error
= SYSCTL_OUT(req
, buf
, strlen(buf
));
1273 if (error
== 0 && acpi_pst_md
&& acpi_pst_md
->pmd_get_pstate
) {
1274 const struct acpi_pstate
*pstate
;
1277 pstate
= acpi_pst_get_pstate(sc
);
1278 if (pstate
== NULL
) {
1281 ksnprintf(buf
, sizeof(buf
), "(%d)",
1285 error
= SYSCTL_OUT(req
, str
, strlen(str
));
1293 acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS
)
1295 struct acpi_pst_domain
*dom
= arg1
;
1298 KKASSERT(dom
->pd_state
>= 0 && dom
->pd_state
< acpi_npstates
);
1300 freq
= acpi_pstates
[dom
->pd_state
].st_freq
;
1302 error
= sysctl_handle_int(oidp
, &freq
, 0, req
);
1303 if (error
|| req
->newptr
== NULL
)
1306 i
= acpi_pst_freq2index(freq
);
1310 acpi_pst_domain_set_pstate(dom
, i
, NULL
);
1315 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS
)
1319 KKASSERT(acpi_pst_global_state
>= 0 &&
1320 acpi_pst_global_state
< acpi_npstates
);
1322 freq
= acpi_pstates
[acpi_pst_global_state
].st_freq
;
1324 error
= sysctl_handle_int(oidp
, &freq
, 0, req
);
1325 if (error
|| req
->newptr
== NULL
)
1328 i
= acpi_pst_freq2index(freq
);
1332 acpi_pst_global_set_pstate(i
);
1338 acpi_pst_check_csr_handler(netmsg_t msg
)
1340 struct netmsg_acpi_pst
*rmsg
= (struct netmsg_acpi_pst
*)msg
;
1343 error
= acpi_pst_md
->pmd_check_csr(rmsg
->ctrl
, rmsg
->status
);
1344 lwkt_replymsg(&rmsg
->base
.lmsg
, error
);
1348 acpi_pst_check_csr(struct acpi_pst_softc
*sc
)
1350 struct netmsg_acpi_pst msg
;
1352 if (acpi_pst_md
== NULL
)
1355 netmsg_init(&msg
.base
, NULL
, &curthread
->td_msgport
,
1356 MSGF_PRIORITY
, acpi_pst_check_csr_handler
);
1357 msg
.ctrl
= &sc
->pst_creg
;
1358 msg
.status
= &sc
->pst_sreg
;
1360 return lwkt_domsg(netisr_cpuport(sc
->pst_cpuid
), &msg
.base
.lmsg
, 0);
1364 acpi_pst_check_pstates_handler(netmsg_t msg
)
1368 error
= acpi_pst_md
->pmd_check_pstates(acpi_pstates
, acpi_npstates
);
1369 lwkt_replymsg(&msg
->lmsg
, error
);
1373 acpi_pst_check_pstates(struct acpi_pst_softc
*sc
)
1375 struct netmsg_base msg
;
1377 if (acpi_pst_md
== NULL
)
1380 netmsg_init(&msg
, NULL
, &curthread
->td_msgport
,
1381 MSGF_PRIORITY
, acpi_pst_check_pstates_handler
);
1383 return lwkt_domsg(netisr_cpuport(sc
->pst_cpuid
), &msg
.lmsg
, 0);
1387 acpi_pst_init_handler(netmsg_t msg
)
1389 struct netmsg_acpi_pst
*rmsg
= (struct netmsg_acpi_pst
*)msg
;
1392 error
= acpi_pst_md
->pmd_init(rmsg
->ctrl
, rmsg
->status
);
1393 lwkt_replymsg(&rmsg
->base
.lmsg
, error
);
1397 acpi_pst_init(struct acpi_pst_softc
*sc
)
1399 struct netmsg_acpi_pst msg
;
1401 if (acpi_pst_md
== NULL
)
1404 netmsg_init(&msg
.base
, NULL
, &curthread
->td_msgport
,
1405 MSGF_PRIORITY
, acpi_pst_init_handler
);
1406 msg
.ctrl
= &sc
->pst_creg
;
1407 msg
.status
= &sc
->pst_sreg
;
1409 return lwkt_domsg(netisr_cpuport(sc
->pst_cpuid
), &msg
.base
.lmsg
, 0);
1413 acpi_pst_set_pstate_handler(netmsg_t msg
)
1415 struct netmsg_acpi_pst
*rmsg
= (struct netmsg_acpi_pst
*)msg
;
1418 error
= acpi_pst_md
->pmd_set_pstate(rmsg
->ctrl
, rmsg
->status
,
1419 rmsg
->base
.lmsg
.u
.ms_resultp
);
1420 lwkt_replymsg(&rmsg
->base
.lmsg
, error
);
1424 acpi_pst_set_pstate(struct acpi_pst_softc
*sc
, const struct acpi_pstate
*pstate
)
1426 struct netmsg_acpi_pst msg
;
1428 KKASSERT(acpi_pst_md
!= NULL
);
1430 netmsg_init(&msg
.base
, NULL
, &curthread
->td_msgport
,
1431 MSGF_PRIORITY
, acpi_pst_set_pstate_handler
);
1432 msg
.base
.lmsg
.u
.ms_resultp
= __DECONST(void *, pstate
);
1433 msg
.ctrl
= &sc
->pst_creg
;
1434 msg
.status
= &sc
->pst_sreg
;
1436 return lwkt_domsg(netisr_cpuport(sc
->pst_cpuid
), &msg
.base
.lmsg
, 0);
1440 acpi_pst_get_pstate_handler(netmsg_t msg
)
1442 struct netmsg_acpi_pst
*rmsg
= (struct netmsg_acpi_pst
*)msg
;
1443 const struct acpi_pstate
*pstate
;
1445 pstate
= acpi_pst_md
->pmd_get_pstate(rmsg
->status
, acpi_pstates
,
1447 rmsg
->base
.lmsg
.u
.ms_resultp
= __DECONST(void *, pstate
);
1448 lwkt_replymsg(&rmsg
->base
.lmsg
, 0);
1451 static const struct acpi_pstate
*
1452 acpi_pst_get_pstate(struct acpi_pst_softc
*sc
)
1454 struct netmsg_acpi_pst msg
;
1456 if (acpi_pst_md
== NULL
)
1459 netmsg_init(&msg
.base
, NULL
, &curthread
->td_msgport
,
1460 MSGF_PRIORITY
, acpi_pst_get_pstate_handler
);
1461 msg
.status
= &sc
->pst_sreg
;
1463 lwkt_domsg(netisr_cpuport(sc
->pst_cpuid
), &msg
.base
.lmsg
, 0);
1464 return msg
.base
.lmsg
.u
.ms_resultp
;
1468 acpi_pst_alloc_resource(device_t dev
, ACPI_OBJECT
*obj
, int idx
,
1469 struct acpi_pst_res
*res
)
1471 struct acpi_pst_softc
*sc
= device_get_softc(dev
);
1475 error
= acpi_PkgRawGas(obj
, idx
, &res
->pr_gas
);
1479 /* Allocate resource, if possible */
1480 res
->pr_rid
= sc
->pst_parent
->cpu_next_rid
;
1481 acpi_bus_alloc_gas(dev
, &type
, &res
->pr_rid
, &res
->pr_gas
, &res
->pr_res
, 0);
1482 if (res
->pr_res
!= NULL
) {
1483 sc
->pst_parent
->cpu_next_rid
++;
1484 res
->pr_bt
= rman_get_bustag(res
->pr_res
);
1485 res
->pr_bh
= rman_get_bushandle(res
->pr_res
);
1493 acpi_pst_domain_check_nproc(device_t dev
, struct acpi_pst_domain
*dom
)
1495 struct acpi_pst_softc
*pst
;
1499 LIST_FOREACH(pst
, &dom
->pd_pstlist
, pst_link
)
1501 if (i
== dom
->pd_nproc
) {
1503 * Some stupid BIOSes will set wrong "# of processors",
1504 * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
1507 device_printf(dev
, "domain%u already contains %d "
1508 "P-States\n", dom
->pd_dom
, dom
->pd_nproc
);
1512 KKASSERT(i
< dom
->pd_nproc
);
1516 acpi_pst_eval_ppc(struct acpi_pst_softc
*sc
, int *sstart
)
1523 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
1524 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PPC", NULL
, &buf
);
1525 if (!ACPI_FAILURE(status
)) {
1526 ACPI_OBJECT_LIST arglist
;
1529 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
1530 if (obj
->Type
== ACPI_TYPE_INTEGER
) {
1531 if (obj
->Integer
.Value
>= acpi_npstates
) {
1532 device_printf(sc
->pst_dev
,
1533 "Invalid _PPC value\n");
1537 *sstart
= obj
->Integer
.Value
;
1539 device_printf(sc
->pst_dev
, "_PPC %d\n",
1543 device_printf(sc
->pst_dev
, "Invalid _PPC object\n");
1551 /* _PPC has been successfully processed */
1552 arglist
.Pointer
= arg
;
1554 arg
[0].Type
= ACPI_TYPE_INTEGER
;
1555 arg
[0].Integer
.Value
= 0x80;
1556 arg
[1].Type
= ACPI_TYPE_INTEGER
;
1557 arg
[1].Integer
.Value
= 0;
1558 AcpiEvaluateObject(sc
->pst_handle
, "_OST", &arglist
, NULL
);
1566 acpi_pst_eval_pdl(struct acpi_pst_softc
*sc
, int *scount
)
1573 buf
.Length
= ACPI_ALLOCATE_BUFFER
;
1574 status
= AcpiEvaluateObject(sc
->pst_handle
, "_PDL", NULL
, &buf
);
1575 if (!ACPI_FAILURE(status
)) {
1576 obj
= (ACPI_OBJECT
*)buf
.Pointer
;
1577 if (obj
->Type
== ACPI_TYPE_INTEGER
) {
1578 if (obj
->Integer
.Value
>= acpi_npstates
) {
1579 device_printf(sc
->pst_dev
,
1580 "Invalid _PDL value\n");
1584 if (obj
->Integer
.Value
>= acpi_pstate_start
) {
1585 *scount
= obj
->Integer
.Value
+ 1;
1587 device_printf(sc
->pst_dev
, "_PDL %d\n",
1591 /* Prefer _PPC as stated in ACPI 5.1 8.4.4.6 */
1592 device_printf(sc
->pst_dev
, "conflict _PDL %ju "
1593 "and _PPC %d, ignore\n",
1594 (uintmax_t)obj
->Integer
.Value
,
1598 device_printf(sc
->pst_dev
, "Invalid _PDL object\n");
1612 * Notify is serialized by acpi task thread.
1615 acpi_pst_notify(device_t dev
)
1617 struct acpi_pst_softc
*sc
= device_get_softc(dev
);
1618 boolean_t fixup
= FALSE
;
1620 if (!acpi_pst_handle_notify
)
1625 * _PPC and _PDL evaluation order is critical. _PDL
1626 * evaluation depends on _PPC evaluation.
1628 if (sc
->pst_flags
& ACPI_PST_FLAG_PPC
) {
1629 int sstart
= acpi_pstate_start
;
1631 acpi_pst_eval_ppc(sc
, &sstart
);
1632 if (acpi_pstate_start
!= sstart
&& sc
->pst_cpuid
== 0) {
1633 acpi_pstate_start
= sstart
;
1637 if (sc
->pst_flags
& ACPI_PST_FLAG_PDL
) {
1638 int scount
= acpi_pstate_count
;
1640 acpi_pst_eval_pdl(sc
, &scount
);
1641 if (acpi_pstate_count
!= scount
&& sc
->pst_cpuid
== 0) {
1642 acpi_pstate_count
= scount
;
1647 if (fixup
&& acpi_pst_md
!= NULL
&&
1648 acpi_pst_md
->pmd_set_pstate
!= NULL
)
1649 acpi_pst_global_fixup_pstate();