sys: Some whitespace cleanup.
[dragonfly.git] / sys / dev / acpica / acpi_cpu_pstate.c
blobb72a5b02cb5bd1b63ba2fa3aa2d24b1662671da7
1 /*
2 * Copyright (c) 2009 The DragonFly Project. All rights reserved.
3 *
4 * This code is derived from software contributed to The DragonFly Project
5 * by Sepherosa Ziehau <sepherosa@gmail.com>
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
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
16 * distribution.
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
32 * SUCH DAMAGE.
35 #include "opt_acpi.h"
37 #include <sys/param.h>
38 #include <sys/bus.h>
39 #include <sys/cpuhelper.h>
40 #include <sys/kernel.h>
41 #include <sys/malloc.h>
42 #include <sys/queue.h>
43 #include <sys/rman.h>
44 #include <sys/sysctl.h>
45 #include <sys/msgport2.h>
46 #include <sys/cpu_topology.h>
48 #include "acpi.h"
49 #include "acpivar.h"
50 #include "acpi_cpu.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 {
75 uint32_t pd_dom;
76 uint32_t pd_coord;
77 uint32_t pd_nproc;
78 LIST_ENTRY(acpi_pst_domain) pd_link;
80 uint32_t pd_flags;
82 struct lwkt_serialize pd_serialize;
84 int pd_state;
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 {
97 device_t pst_dev;
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;
103 int pst_state;
104 int pst_cpuid;
106 uint32_t pst_flags;
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 *,
130 int, int *);
131 static void acpi_pst_domain_set_pstate(struct acpi_pst_domain *, int,
132 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
191 * power domain.
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),
205 /* Bus interface */
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),
221 DEVMETHOD_END
224 static driver_t acpi_pst_driver = {
225 "cpu_pst",
226 acpi_pst_methods,
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);
234 static __inline int
235 acpi_pst_freq2index(int freq)
237 int i;
239 for (i = 0; i < acpi_npstates; ++i) {
240 if (acpi_pstates[i].st_freq == freq)
241 return i;
243 return -1;
246 static int
247 acpi_pst_probe(device_t dev)
249 ACPI_BUFFER buf;
250 ACPI_HANDLE handle;
251 ACPI_STATUS status;
252 ACPI_OBJECT *obj;
254 if (acpi_disabled("cpu_pst") ||
255 acpi_get_type(dev) != ACPI_TYPE_PROCESSOR)
256 return ENXIO;
258 if (acpi_pst_md == NULL)
259 acpi_pst_md = acpi_pst_md_probe();
261 handle = acpi_get_handle(dev);
264 * Check _PSD package
266 * NOTE:
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
271 * core.
273 buf.Pointer = NULL;
274 buf.Length = ACPI_ALLOCATE_BUFFER;
275 status = AcpiEvaluateObject(handle, "_PSD", NULL, &buf);
276 if (!ACPI_FAILURE(status)) {
277 AcpiOsFree((ACPI_OBJECT *)buf.Pointer);
278 goto done;
282 * Check _PCT package
284 buf.Pointer = NULL;
285 buf.Length = ACPI_ALLOCATE_BUFFER;
286 status = AcpiEvaluateObject(handle, "_PCT", NULL, &buf);
287 if (ACPI_FAILURE(status)) {
288 if (bootverbose) {
289 device_printf(dev, "Can't get _PCT package - %s\n",
290 AcpiFormatException(status));
292 return ENXIO;
295 obj = (ACPI_OBJECT *)buf.Pointer;
296 if (!ACPI_PKG_VALID_EQ(obj, 2)) {
297 device_printf(dev, "Invalid _PCT package\n");
298 AcpiOsFree(obj);
299 return ENXIO;
301 AcpiOsFree(obj);
304 * Check _PSS package
306 buf.Pointer = NULL;
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));
312 return ENXIO;
315 obj = (ACPI_OBJECT *)buf.Pointer;
316 if (!ACPI_PKG_VALID(obj, 1)) {
317 device_printf(dev, "Invalid _PSS package\n");
318 AcpiOsFree(obj);
319 return ENXIO;
321 AcpiOsFree(obj);
323 done:
324 device_set_desc(dev, "ACPI CPU P-State");
325 return 0;
328 static int
329 acpi_pst_attach(device_t dev)
331 struct acpi_pst_softc *sc = device_get_softc(dev);
332 struct acpi_pst_domain *dom = NULL;
333 ACPI_BUFFER buf;
334 ACPI_STATUS status;
335 ACPI_OBJECT *obj;
336 struct acpi_pstate *pstate, *p;
337 int i, npstate, error, sstart, scount;
339 sc->pst_dev = dev;
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.
349 buf.Pointer = NULL;
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");
357 AcpiOsFree(obj);
358 return ENXIO;
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]);
365 if (dom == NULL) {
366 AcpiOsFree(obj);
367 return ENXIO;
369 } else {
370 if (obj->Type != ACPI_TYPE_INTEGER) {
371 device_printf(dev,
372 "Invalid _PSD package, Type 0x%x\n",
373 obj->Type);
374 AcpiOsFree(obj);
375 return ENXIO;
376 } else {
377 device_printf(dev, "Integer _PSD %ju\n",
378 (uintmax_t)obj->Integer.Value);
379 dom = acpi_pst_domain_create_int(dev,
380 obj->Integer.Value);
381 if (dom == NULL) {
382 AcpiOsFree(obj);
383 return ENXIO;
388 /* Free _PSD */
389 AcpiOsFree(buf.Pointer);
390 } else {
391 if (acpi_pst_domain_id < 0) {
392 device_printf(dev, "Missing _PSD for cpu%d\n",
393 sc->pst_cpuid);
394 return ENXIO;
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
413 buf.Pointer = NULL;
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
421 * _PSD check.
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);
429 if (pst == NULL) {
430 cpumask_t mask;
432 mask = get_cpumask_from_level(sc->pst_cpuid,
433 CORE_LEVEL);
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,
439 pst_link) {
440 if (CPUMASK_TESTBIT(mask,
441 pst->pst_cpuid))
442 break;
444 if (pst != NULL)
445 break;
447 if (pst != NULL && acpi_pst_ht_reuse_domain) {
449 * Use the same domain for CPUs in the
450 * same core.
452 device_printf(dev, "Destroy domain%u, "
453 "reuse domain%u\n",
454 dom->pd_dom, dom1->pd_dom);
455 LIST_REMOVE(dom, pd_link);
456 kfree(dom, M_DEVBUF);
457 dom = dom1;
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);
467 if (pst != NULL &&
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;
478 device_printf(dev,
479 "No _PCT; reuse %s control/status regs\n",
480 device_get_nameunit(pst->pst_dev));
481 goto fetch_pss;
483 device_printf(dev, "Can't get _PCT package - %s\n",
484 AcpiFormatException(status));
485 return ENXIO;
488 obj = (ACPI_OBJECT *)buf.Pointer;
489 if (!ACPI_PKG_VALID_EQ(obj, 2)) {
490 device_printf(dev, "Invalid _PCT package\n");
491 AcpiOsFree(obj);
492 return ENXIO;
495 /* Save and try allocating control register */
496 error = acpi_pst_alloc_resource(dev, obj, 0, &sc->pst_creg);
497 if (error) {
498 AcpiOsFree(obj);
499 return error;
501 if (bootverbose) {
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);
509 if (error) {
510 AcpiOsFree(obj);
511 return error;
513 if (bootverbose) {
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);
519 /* Free _PCT */
520 AcpiOsFree(obj);
522 fetch_pss:
524 * Create P-State table according to _PSS
526 buf.Pointer = NULL;
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
532 * _PSD check.
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");
539 goto fetch_ppc;
541 device_printf(dev, "Can't get _PSS package - %s\n",
542 AcpiFormatException(status));
543 return ENXIO;
546 obj = (ACPI_OBJECT *)buf.Pointer;
547 if (!ACPI_PKG_VALID(obj, 1)) {
548 device_printf(dev, "Invalid _PSS package\n");
549 AcpiOsFree(obj);
550 return ENXIO;
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
564 * is consistent.
566 if (acpi_pstates != NULL && acpi_npstates != npstate) {
567 device_printf(dev, "Inconsistent # of P-States "
568 "cross Processor objects\n");
569 AcpiOsFree(obj);
570 return ENXIO;
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) {
578 ACPI_OBJECT *pkg;
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
583 int j;
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);
588 AcpiOsFree(obj);
589 kfree(pstate, M_TEMP);
590 return ENXIO;
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);
596 AcpiOsFree(obj);
597 kfree(pstate, M_TEMP);
598 return ENXIO;
601 if (p->st_freq & 0x80000000) {
602 device_printf(dev, "Invalid _PSS P%d freq: 0x%08x\n",
603 i, p->st_freq);
604 AcpiOsFree(obj);
605 kfree(pstate, M_TEMP);
606 return ENXIO;
610 /* Free _PSS */
611 AcpiOsFree(obj);
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;
620 pstate = NULL;
622 if (bootverbose) {
623 for (i = 0; i < acpi_npstates; ++i) {
624 device_printf(dev,
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);
635 } else {
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");
644 #if 0
646 * Some BIOSes create different P-State tables;
647 * just trust the one from the BSP and move on.
649 kfree(pstate, M_TEMP);
650 return ENXIO;
651 #endif
653 kfree(pstate, M_TEMP);
656 fetch_ppc:
657 /* By default, we start from P-State table's first entry */
658 sstart = 0;
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)
666 return error;
667 else if (!error)
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) {
692 if (bootverbose) {
693 device_printf(dev, "_PDL override %d\n",
694 acpi_pst_pdl);
696 scount = acpi_pst_pdl + 1;
697 goto proc_pdl;
698 } else {
699 device_printf(dev, "Invalid _PDL override %d, "
700 "must be less than %d\n", acpi_pst_pdl,
701 acpi_npstates);
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)
711 return error;
712 else if (!error)
713 sc->pst_flags |= ACPI_PST_FLAG_PDL;
714 proc_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))) {
735 cpumask_t mask;
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,
744 pst_link) {
745 if (CPUMASK_TESTBIT(mask,
746 pst->pst_cpuid))
747 break;
749 if (pst != NULL)
750 break;
752 if (pst != NULL &&
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
759 * same package.
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);
766 dom = dom1;
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;
787 return 0;
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");
798 return NULL;
801 /* NumberOfEntries */
802 if (acpi_PkgInt32(obj, 0, &val) != 0 || val != 5) {
803 device_printf(dev, "Invalid _PSD NumberOfEntries\n");
804 return NULL;
807 /* Revision */
808 if (acpi_PkgInt32(obj, 1, &val) != 0 || val != 0) {
809 device_printf(dev, "Invalid _PSD Revision\n");
810 return NULL;
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");
817 return NULL;
820 if (!ACPI_PSD_COORD_VALID(coord)) {
821 device_printf(dev, "Invalid _PSD CoordType (%#x)\n", coord);
822 return NULL;
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 "
836 "(%d)\n", nproc);
837 return NULL;
839 } else if (nproc == 0) {
840 device_printf(dev, "_PSD NumProcessors are zero\n");
841 return NULL;
844 dom = acpi_pst_domain_find(domain);
845 if (dom != NULL) {
846 if (dom->pd_flags & ACPI_PSTDOM_FLAG_INT) {
847 device_printf(dev, "Mixed Integer _PSD and "
848 "Package _PSD\n");
849 return NULL;
851 if (dom->pd_coord != coord) {
852 device_printf(dev, "Inconsistent _PSD coord "
853 "information cross Processor objects\n");
854 return NULL;
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.
864 return dom;
867 dom = acpi_pst_domain_alloc(domain, coord, nproc);
868 if (bootverbose) {
869 device_printf(dev, "create pkg domain%u, coord %#x\n",
870 dom->pd_dom, dom->pd_coord);
873 return dom;
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);
882 if (dom != NULL) {
883 if ((dom->pd_flags & ACPI_PSTDOM_FLAG_INT) == 0) {
884 device_printf(dev, "Mixed Package _PSD and "
885 "Integer _PSD\n");
886 return NULL;
888 KKASSERT(dom->pd_coord == ACPI_PSD_COORD_SWALL);
890 dom->pd_nproc++;
891 return dom;
894 dom = acpi_pst_domain_alloc(domain, ACPI_PSD_COORD_SWALL, 1);
895 dom->pd_flags |= ACPI_PSTDOM_FLAG_INT;
897 if (bootverbose)
898 device_printf(dev, "create int domain%u\n", dom->pd_dom);
900 return 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)
910 continue;
911 if (dom->pd_dom == domain)
912 return dom;
914 return NULL;
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);
931 return dom;
934 static void
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;
939 int done, error;
941 ASSERT_SERIALIZED(&dom->pd_serialize);
943 KKASSERT(i >= 0 && i < acpi_npstates);
944 pstate = &acpi_pstates[i];
946 done = 0;
947 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
948 if (!done) {
949 error = acpi_pst_set_pstate(sc, pstate);
950 if (error) {
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)
956 done = 1;
958 sc->pst_state = i;
960 dom->pd_state = i;
962 if (global != NULL)
963 *global = i;
966 static void
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);
974 static void
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)
983 continue;
984 acpi_pst_domain_set_pstate(dom, i, global);
985 global = NULL;
989 static void
990 acpi_pst_global_fixup_pstate(void)
992 struct acpi_pst_domain *dom;
993 int *global = &acpi_pst_global_state;
994 int sstart, scount;
996 sstart = acpi_pstate_start;
997 scount = acpi_pstate_count;
999 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
1000 int i = -1;
1002 /* Skip dead domain */
1003 if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD)
1004 continue;
1006 lwkt_serialize_enter(&dom->pd_serialize);
1008 if (global != NULL) {
1009 if (*global < sstart)
1010 *global = sstart;
1011 else if (*global >= scount)
1012 *global = scount - 1;
1013 global = NULL;
1015 if (dom->pd_state < sstart)
1016 i = sstart;
1017 else if (dom->pd_state >= scount)
1018 i = scount - 1;
1019 if (i >= 0)
1020 acpi_pst_domain_set_pstate_locked(dom, i, NULL);
1022 lwkt_serialize_exit(&dom->pd_serialize);
1026 static void
1027 acpi_pst_postattach(void *arg __unused)
1029 struct acpi_pst_domain *dom;
1030 struct acpi_cpu_softc *cpu;
1031 device_t *devices;
1032 int i, ndevices, error, has_domain;
1034 devices = NULL;
1035 ndevices = 0;
1036 error = devclass_get_devices(acpi_pst_devclass, &devices, &ndevices);
1037 if (error)
1038 return;
1040 if (ndevices == 0)
1041 return;
1043 cpu = NULL;
1044 for (i = 0; i < ndevices; ++i) {
1045 cpu = device_get_softc(device_get_parent(devices[i]));
1046 if (cpu->glob_sysctl_tree != NULL)
1047 break;
1049 kfree(devices, M_TEMP);
1050 KKASSERT(cpu != NULL);
1052 if (acpi_pst_md == NULL)
1053 kprintf("ACPI: no P-State CPU driver\n");
1055 has_domain = 0;
1056 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
1057 struct acpi_pst_softc *sc;
1058 char buf[32];
1060 dom->pd_state = acpi_pstate_start;
1063 * Make sure that all processors belonging to this
1064 * domain are located.
1066 i = 0;
1067 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1068 sc->pst_state = acpi_pstate_start;
1069 ++i;
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,
1076 dom->pd_nproc, i);
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
1084 * domain out.
1086 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1087 continue;
1089 dom->pd_nproc = i;
1093 * Validate P-State configurations for this domain
1095 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1096 error = acpi_pst_check_csr(sc);
1097 if (error)
1098 break;
1100 error = acpi_pst_check_pstates(sc);
1101 if (error)
1102 break;
1104 if (sc != NULL) {
1105 kprintf("ACPI: domain%u P-State configuration "
1106 "check failed\n", dom->pd_dom);
1107 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1108 continue;
1112 * Do necssary P-State initialization
1114 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1115 error = acpi_pst_init(sc);
1116 if (error)
1117 break;
1119 if (sc != NULL) {
1120 kprintf("ACPI: domain%u P-State initialization "
1121 "check failed\n", dom->pd_dom);
1122 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1123 continue;
1126 has_domain = 1;
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,
1135 "P-State domain");
1136 if (dom->pd_sysctl_tree == NULL) {
1137 kprintf("ACPI: Can't create sysctl tree for domain%u",
1138 dom->pd_dom);
1139 continue;
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),
1151 OID_AUTO, "avail",
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),
1158 OID_AUTO, "power",
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",
1168 "member cpus");
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),
1174 OID_AUTO, "select",
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);
1199 static int
1200 acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS)
1202 int i, error, sstart, scount;
1204 error = 0;
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);
1210 if (error == 0) {
1211 const char *pat;
1212 char buf[32];
1214 if (i < sstart || i >= scount)
1215 pat = "(%u)";
1216 else
1217 pat = "%u";
1219 ksnprintf(buf, sizeof(buf), pat,
1220 acpi_pstates[i].st_freq);
1221 error = SYSCTL_OUT(req, buf, strlen(buf));
1224 return error;
1227 static int
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);
1243 static int
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);
1259 static int
1260 acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS)
1262 struct acpi_pst_domain *dom = arg1;
1263 struct acpi_pst_softc *sc;
1264 int loop, error;
1266 loop = error = 0;
1267 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1268 char buf[32];
1270 if (error == 0 && loop)
1271 error = SYSCTL_OUT(req, " ", 1);
1272 if (error == 0) {
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;
1279 const char *str;
1281 pstate = acpi_pst_get_pstate(sc);
1282 if (pstate == NULL) {
1283 str = "(*)";
1284 } else {
1285 ksnprintf(buf, sizeof(buf), "(%d)",
1286 pstate->st_freq);
1287 str = buf;
1289 error = SYSCTL_OUT(req, str, strlen(str));
1291 ++loop;
1293 return error;
1296 static int
1297 acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS)
1299 struct acpi_pst_domain *dom = arg1;
1300 int error, i, freq;
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)
1308 return error;
1310 i = acpi_pst_freq2index(freq);
1311 if (i < 0)
1312 return EINVAL;
1314 acpi_pst_domain_set_pstate(dom, i, NULL);
1315 return 0;
1318 static int
1319 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS)
1321 int error, i, freq;
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)
1330 return error;
1332 i = acpi_pst_freq2index(freq);
1333 if (i < 0)
1334 return EINVAL;
1336 acpi_pst_global_set_pstate(i);
1338 return 0;
1341 static void
1342 acpi_pst_check_csr_handler(struct cpuhelper_msg *msg)
1344 struct acpi_pst_chmsg *pmsg = (struct acpi_pst_chmsg *)msg;
1345 int error;
1347 error = acpi_pst_md->pmd_check_csr(pmsg->ch_ctrl, pmsg->ch_status);
1348 cpuhelper_replymsg(msg, error);
1351 static int
1352 acpi_pst_check_csr(struct acpi_pst_softc *sc)
1354 struct acpi_pst_chmsg msg;
1356 if (acpi_pst_md == NULL)
1357 return 0;
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));
1367 static void
1368 acpi_pst_check_pstates_handler(struct cpuhelper_msg *msg)
1370 int error;
1372 error = acpi_pst_md->pmd_check_pstates(acpi_pstates, acpi_npstates);
1373 cpuhelper_replymsg(msg, error);
1376 static int
1377 acpi_pst_check_pstates(struct acpi_pst_softc *sc)
1379 struct cpuhelper_msg msg;
1381 if (acpi_pst_md == NULL)
1382 return 0;
1384 cpuhelper_initmsg(&msg, &curthread->td_msgport,
1385 acpi_pst_check_pstates_handler, NULL, MSGF_PRIORITY);
1386 return (cpuhelper_domsg(&msg, sc->pst_cpuid));
1389 static void
1390 acpi_pst_init_handler(struct cpuhelper_msg *msg)
1392 struct acpi_pst_chmsg *pmsg = (struct acpi_pst_chmsg *)msg;
1393 int error;
1395 error = acpi_pst_md->pmd_init(pmsg->ch_ctrl, pmsg->ch_status);
1396 cpuhelper_replymsg(msg, error);
1399 static int
1400 acpi_pst_init(struct acpi_pst_softc *sc)
1402 struct acpi_pst_chmsg msg;
1404 if (acpi_pst_md == NULL)
1405 return 0;
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));
1415 static void
1416 acpi_pst_set_pstate_handler(struct cpuhelper_msg *msg)
1418 struct acpi_pst_chmsg *pmsg = (struct acpi_pst_chmsg *)msg;
1419 int error;
1421 error = acpi_pst_md->pmd_set_pstate(pmsg->ch_ctrl, pmsg->ch_status,
1422 msg->ch_cbarg);
1423 cpuhelper_replymsg(msg, error);
1426 static int
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),
1435 MSGF_PRIORITY);
1436 msg.ch_ctrl = &sc->pst_creg;
1437 msg.ch_status = &sc->pst_sreg;
1439 return (cpuhelper_domsg(&msg.ch_msg, sc->pst_cpuid));
1442 static void
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,
1449 acpi_npstates);
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)
1460 return 0;
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);
1470 static int
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);
1475 int error, type;
1477 /* Save GAS */
1478 error = acpi_PkgRawGas(obj, idx, &res->pr_gas);
1479 if (error)
1480 return error;
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);
1489 } else {
1490 res->pr_rid = 0;
1492 return 0;
1495 static void
1496 acpi_pst_domain_check_nproc(device_t dev, struct acpi_pst_domain *dom)
1498 struct acpi_pst_softc *pst;
1499 int i;
1501 i = 0;
1502 LIST_FOREACH(pst, &dom->pd_pstlist, pst_link)
1503 ++i;
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.
1509 if (bootverbose) {
1510 device_printf(dev, "domain%u already contains %d "
1511 "P-States\n", dom->pd_dom, dom->pd_nproc);
1513 dom->pd_nproc++;
1515 KKASSERT(i < dom->pd_nproc);
1518 static int
1519 acpi_pst_eval_ppc(struct acpi_pst_softc *sc, int *sstart)
1521 ACPI_BUFFER buf;
1522 ACPI_STATUS status;
1523 ACPI_OBJECT *obj;
1525 buf.Pointer = NULL;
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;
1530 ACPI_OBJECT arg[2];
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");
1537 AcpiOsFree(obj);
1538 return ENXIO;
1540 *sstart = obj->Integer.Value;
1541 if (bootverbose) {
1542 device_printf(sc->pst_dev, "_PPC %d\n",
1543 *sstart);
1545 } else {
1546 device_printf(sc->pst_dev, "Invalid _PPC object\n");
1547 AcpiOsFree(obj);
1548 return ENXIO;
1551 /* Free _PPC */
1552 AcpiOsFree(obj);
1554 /* _PPC has been successfully processed */
1555 arglist.Pointer = arg;
1556 arglist.Count = 2;
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);
1563 return 0;
1565 return ENOENT;
1568 static int
1569 acpi_pst_eval_pdl(struct acpi_pst_softc *sc, int *scount)
1571 ACPI_BUFFER buf;
1572 ACPI_STATUS status;
1573 ACPI_OBJECT *obj;
1575 buf.Pointer = NULL;
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");
1584 AcpiOsFree(obj);
1585 return ENXIO;
1587 if (obj->Integer.Value >= acpi_pstate_start) {
1588 *scount = obj->Integer.Value + 1;
1589 if (bootverbose) {
1590 device_printf(sc->pst_dev, "_PDL %d\n",
1591 *scount);
1593 } else {
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,
1598 acpi_pstate_start);
1600 } else {
1601 device_printf(sc->pst_dev, "Invalid _PDL object\n");
1602 AcpiOsFree(obj);
1603 return ENXIO;
1606 /* Free _PDL */
1607 AcpiOsFree(obj);
1609 return 0;
1611 return ENOENT;
1615 * Notify is serialized by acpi task thread.
1617 static void
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)
1624 return;
1627 * NOTE:
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;
1637 fixup = TRUE;
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;
1646 fixup = TRUE;
1650 if (fixup && acpi_pst_md != NULL &&
1651 acpi_pst_md->pmd_set_pstate != NULL)
1652 acpi_pst_global_fixup_pstate();