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);
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);
606 if (acpi_pstates == NULL) {
608 * If no P-State table is created yet,
609 * save the temporary one we just created.
611 acpi_pstates = pstate;
612 acpi_npstates = npstate;
616 for (i = 0; i < acpi_npstates; ++i) {
618 "freq %u, pwr %u, xlat %u, blat %u, "
619 "cv %08x, sv %08x\n",
620 acpi_pstates[i].st_freq,
621 acpi_pstates[i].st_power,
622 acpi_pstates[i].st_xsit_lat,
623 acpi_pstates[i].st_bm_lat,
624 acpi_pstates[i].st_cval,
625 acpi_pstates[i].st_sval);
630 * Make sure that P-State tables are same
631 * for all processors.
633 if (memcmp(pstate, acpi_pstates,
634 sizeof(*pstate) * npstate) != 0) {
635 device_printf(dev, "Inconsistent _PSS "
636 "cross Processor objects\n");
639 * Some BIOSes create different P-State tables;
640 * just trust the one from the BSP and move on.
642 kfree(pstate, M_TEMP);
646 kfree(pstate, M_TEMP);
650 /* By default, we start from P-State table's first entry */
654 * Adjust the usable first entry of P-State table,
655 * if there is _PPC object.
657 error = acpi_pst_eval_ppc(sc, &sstart);
658 if (error && error != ENOENT)
661 sc->pst_flags |= ACPI_PST_FLAG_PPC;
662 if (acpi_pstate_start < 0) {
663 acpi_pstate_start = sstart;
664 } else if (acpi_pstate_start != sstart) {
665 device_printf(dev, "_PPC mismatch, was %d, now %d\n",
666 acpi_pstate_start, sstart);
667 if (acpi_pstate_start < sstart) {
668 device_printf(dev, "_PPC %d -> %d\n",
669 acpi_pstate_start, sstart);
670 acpi_pstate_start = sstart;
675 * By default, we assume number of usable P-States is same as
676 * number of P-States.
678 scount = acpi_npstates;
681 * Allow users to override or set _PDL
683 if (acpi_pst_pdl >= 0) {
684 if (acpi_pst_pdl < acpi_npstates) {
686 device_printf(dev, "_PDL override %d\n",
689 scount = acpi_pst_pdl + 1;
692 device_printf(dev, "Invalid _PDL override %d, "
693 "must be less than %d\n", acpi_pst_pdl,
699 * Adjust the number of usable entries in P-State table,
700 * if there is _PDL object.
702 error = acpi_pst_eval_pdl(sc, &scount);
703 if (error && error != ENOENT)
706 sc->pst_flags |= ACPI_PST_FLAG_PDL;
708 if (acpi_pstate_count == 0) {
709 acpi_pstate_count = scount;
710 } else if (acpi_pstate_count != scount) {
711 device_printf(dev, "_PDL mismatch, was %d, now %d\n",
712 acpi_pstate_count, scount);
713 if (acpi_pstate_count > scount) {
714 device_printf(dev, "_PDL %d -> %d\n",
715 acpi_pstate_count, scount);
716 acpi_pstate_count = scount;
721 * Some CPUs only have package P-states, but some BIOSes put each
722 * hyperthread to its own P-state domain; allow user to override.
724 if (LIST_EMPTY(&dom->pd_pstlist) &&
725 (acpi_pst_force_pkg_domain ||
726 (cpu_vendor_id == CPU_VENDOR_INTEL &&
727 acpi_pst_intel_pkg_domain))) {
730 mask = get_cpumask_from_level(sc->pst_cpuid, CHIP_LEVEL);
731 if (CPUMASK_TESTNZERO(mask)) {
732 struct acpi_pst_softc *pst = NULL;
733 struct acpi_pst_domain *dom1;
735 LIST_FOREACH(dom1, &acpi_pst_domains, pd_link) {
736 LIST_FOREACH(pst, &dom1->pd_pstlist,
738 if (CPUMASK_TESTBIT(mask,
746 memcmp(&pst->pst_creg, &sc->pst_creg,
747 sizeof(sc->pst_creg)) == 0 &&
748 memcmp(&pst->pst_sreg, &sc->pst_sreg,
749 sizeof(sc->pst_sreg)) == 0) {
751 * Use the same domain for CPUs in the
754 device_printf(dev, "Destroy domain%u, "
755 "force pkg domain%u\n",
756 dom->pd_dom, dom1->pd_dom);
757 LIST_REMOVE(dom, pd_link);
758 kfree(dom, M_DEVBUF);
761 * Make sure that adding us will not
762 * overflow the domain containing
763 * siblings in the same package.
765 acpi_pst_domain_check_nproc(dev, dom);
770 /* Link us with the domain */
771 sc->pst_domain = dom;
772 LIST_INSERT_HEAD(&dom->pd_pstlist, sc, pst_link);
774 if (device_get_unit(dev) == 0)
775 AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_pst_postattach, NULL);
777 if (sc->pst_flags & (ACPI_PST_FLAG_PPC | ACPI_PST_FLAG_PDL))
778 sc->pst_parent->cpu_pst_notify = acpi_pst_notify;
783 static struct acpi_pst_domain *
784 acpi_pst_domain_create_pkg(device_t dev, ACPI_OBJECT *obj)
786 struct acpi_pst_domain *dom;
787 uint32_t val, domain, coord, nproc;
789 if (!ACPI_PKG_VALID_EQ(obj, 5)) {
790 device_printf(dev, "Invalid _PSD package\n");
794 /* NumberOfEntries */
795 if (acpi_PkgInt32(obj, 0, &val) != 0 || val != 5) {
796 device_printf(dev, "Invalid _PSD NumberOfEntries\n");
801 if (acpi_PkgInt32(obj, 1, &val) != 0 || val != 0) {
802 device_printf(dev, "Invalid _PSD Revision\n");
806 if (acpi_PkgInt32(obj, 2, &domain) != 0 ||
807 acpi_PkgInt32(obj, 3, &coord) != 0 ||
808 acpi_PkgInt32(obj, 4, &nproc) != 0) {
809 device_printf(dev, "Can't extract _PSD package\n");
813 if (!ACPI_PSD_COORD_VALID(coord)) {
814 device_printf(dev, "Invalid _PSD CoordType (%#x)\n", coord);
818 if (nproc > MAXCPU) {
820 * If NumProcessors is greater than MAXCPU
821 * and domain's coordination is SWALL, then
822 * we will never be able to start all CPUs
823 * within this domain, and power state
824 * transition will never be completed, so we
825 * just bail out here.
827 if (coord == ACPI_PSD_COORD_SWALL) {
828 device_printf(dev, "Unsupported _PSD NumProcessors "
832 } else if (nproc == 0) {
833 device_printf(dev, "_PSD NumProcessors are zero\n");
837 dom = acpi_pst_domain_find(domain);
839 if (dom->pd_flags & ACPI_PSTDOM_FLAG_INT) {
840 device_printf(dev, "Mixed Integer _PSD and "
844 if (dom->pd_coord != coord) {
845 device_printf(dev, "Inconsistent _PSD coord "
846 "information cross Processor objects\n");
849 if (dom->pd_nproc != nproc) {
850 device_printf(dev, "Inconsistent _PSD nproc "
851 "information cross Processor objects\n");
853 * Some stupid BIOSes will set wrong "# of processors",
854 * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
860 dom = acpi_pst_domain_alloc(domain, coord, nproc);
862 device_printf(dev, "create pkg domain%u, coord %#x\n",
863 dom->pd_dom, dom->pd_coord);
869 static struct acpi_pst_domain *
870 acpi_pst_domain_create_int(device_t dev, uint32_t domain)
872 struct acpi_pst_domain *dom;
874 dom = acpi_pst_domain_find(domain);
876 if ((dom->pd_flags & ACPI_PSTDOM_FLAG_INT) == 0) {
877 device_printf(dev, "Mixed Package _PSD and "
881 KKASSERT(dom->pd_coord == ACPI_PSD_COORD_SWALL);
887 dom = acpi_pst_domain_alloc(domain, ACPI_PSD_COORD_SWALL, 1);
888 dom->pd_flags |= ACPI_PSTDOM_FLAG_INT;
891 device_printf(dev, "create int domain%u\n", dom->pd_dom);
896 static struct acpi_pst_domain *
897 acpi_pst_domain_find(uint32_t domain)
899 struct acpi_pst_domain *dom;
901 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
902 if (dom->pd_flags & ACPI_PSTDOM_FLAG_STUB)
904 if (dom->pd_dom == domain)
910 static struct acpi_pst_domain *
911 acpi_pst_domain_alloc(uint32_t domain, uint32_t coord, uint32_t nproc)
913 struct acpi_pst_domain *dom;
915 dom = kmalloc(sizeof(*dom), M_DEVBUF, M_WAITOK | M_ZERO);
916 dom->pd_dom = domain;
917 dom->pd_coord = coord;
918 dom->pd_nproc = nproc;
919 LIST_INIT(&dom->pd_pstlist);
920 lwkt_serialize_init(&dom->pd_serialize);
922 LIST_INSERT_HEAD(&acpi_pst_domains, dom, pd_link);
928 acpi_pst_domain_set_pstate_locked(struct acpi_pst_domain *dom, int i, int *global)
930 const struct acpi_pstate *pstate;
931 struct acpi_pst_softc *sc;
934 ASSERT_SERIALIZED(&dom->pd_serialize);
936 KKASSERT(i >= 0 && i < acpi_npstates);
937 pstate = &acpi_pstates[i];
940 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
942 error = acpi_pst_set_pstate(sc, pstate);
944 device_printf(sc->pst_dev, "can't set "
945 "freq %d\n", pstate->st_freq);
946 /* XXX error cleanup? */
948 if (dom->pd_coord == ACPI_PSD_COORD_SWANY)
960 acpi_pst_domain_set_pstate(struct acpi_pst_domain *dom, int i, int *global)
962 lwkt_serialize_enter(&dom->pd_serialize);
963 acpi_pst_domain_set_pstate_locked(dom, i, global);
964 lwkt_serialize_exit(&dom->pd_serialize);
968 acpi_pst_global_set_pstate(int i)
970 struct acpi_pst_domain *dom;
971 int *global = &acpi_pst_global_state;
973 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
974 /* Skip dead domain */
975 if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD)
977 acpi_pst_domain_set_pstate(dom, i, global);
983 acpi_pst_global_fixup_pstate(void)
985 struct acpi_pst_domain *dom;
986 int *global = &acpi_pst_global_state;
989 sstart = acpi_pstate_start;
990 scount = acpi_pstate_count;
992 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
995 /* Skip dead domain */
996 if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD)
999 lwkt_serialize_enter(&dom->pd_serialize);
1001 if (global != NULL) {
1002 if (*global < sstart)
1004 else if (*global >= scount)
1005 *global = scount - 1;
1008 if (dom->pd_state < sstart)
1010 else if (dom->pd_state >= scount)
1013 acpi_pst_domain_set_pstate_locked(dom, i, NULL);
1015 lwkt_serialize_exit(&dom->pd_serialize);
1020 acpi_pst_postattach(void *arg __unused)
1022 struct acpi_pst_domain *dom;
1023 struct acpi_cpu_softc *cpu;
1025 int i, ndevices, error, has_domain;
1029 error = devclass_get_devices(acpi_pst_devclass, &devices, &ndevices);
1037 for (i = 0; i < ndevices; ++i) {
1038 cpu = device_get_softc(device_get_parent(devices[i]));
1039 if (cpu->glob_sysctl_tree != NULL)
1042 kfree(devices, M_TEMP);
1043 KKASSERT(cpu != NULL);
1045 if (acpi_pst_md == NULL)
1046 kprintf("ACPI: no P-State CPU driver\n");
1049 LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
1050 struct acpi_pst_softc *sc;
1053 dom->pd_state = acpi_pstate_start;
1056 * Make sure that all processors belonging to this
1057 * domain are located.
1060 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1061 sc->pst_state = acpi_pstate_start;
1064 if (i != dom->pd_nproc) {
1065 KKASSERT(i < dom->pd_nproc);
1067 kprintf("ACPI: domain%u misses processors, "
1068 "should be %d, got %d\n", dom->pd_dom,
1070 if (dom->pd_coord == ACPI_PSD_COORD_SWALL) {
1072 * If this domain's coordination is
1073 * SWALL and we don't see all of the
1074 * member CPUs of this domain, then
1075 * the P-State transition will never
1076 * be completed, so just leave this
1079 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1086 * Validate P-State configurations for this domain
1088 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1089 error = acpi_pst_check_csr(sc);
1093 error = acpi_pst_check_pstates(sc);
1098 kprintf("ACPI: domain%u P-State configuration "
1099 "check failed\n", dom->pd_dom);
1100 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1105 * Do necssary P-State initialization
1107 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1108 error = acpi_pst_init(sc);
1113 kprintf("ACPI: domain%u P-State initialization "
1114 "check failed\n", dom->pd_dom);
1115 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1121 ksnprintf(buf, sizeof(buf), "px_dom%u", dom->pd_dom);
1123 sysctl_ctx_init(&dom->pd_sysctl_ctx);
1124 dom->pd_sysctl_tree =
1125 SYSCTL_ADD_NODE(&dom->pd_sysctl_ctx,
1126 SYSCTL_CHILDREN(cpu->glob_sysctl_tree),
1127 OID_AUTO, buf, CTLFLAG_RD, 0,
1129 if (dom->pd_sysctl_tree == NULL) {
1130 kprintf("ACPI: Can't create sysctl tree for domain%u",
1135 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1136 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1137 OID_AUTO, "available",
1138 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_SKIP,
1139 dom, 0, acpi_pst_sysctl_freqs, "A",
1140 "available frequencies");
1142 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1143 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1145 CTLTYPE_OPAQUE | CTLFLAG_RD,
1146 dom, 0, acpi_pst_sysctl_freqs_bin, "IU",
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_power, "IU",
1154 "power of available frequencies");
1156 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1157 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1158 OID_AUTO, "members",
1159 CTLTYPE_STRING | CTLFLAG_RD,
1160 dom, 0, acpi_pst_sysctl_members, "A",
1163 if (acpi_pst_md != NULL &&
1164 acpi_pst_md->pmd_set_pstate != NULL) {
1165 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1166 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1168 CTLTYPE_UINT | CTLFLAG_RW,
1169 dom, 0, acpi_pst_sysctl_select,
1170 "IU", "select freq");
1174 if (has_domain && acpi_pst_md != NULL &&
1175 acpi_pst_md->pmd_set_pstate != NULL) {
1176 SYSCTL_ADD_PROC(&cpu->glob_sysctl_ctx,
1177 SYSCTL_CHILDREN(cpu->glob_sysctl_tree),
1178 OID_AUTO, "px_global",
1179 CTLTYPE_UINT | CTLFLAG_RW,
1180 NULL, 0, acpi_pst_sysctl_global,
1181 "IU", "select freq for all domains");
1183 acpi_pst_global_set_pstate(acpi_pstate_start);
1188 acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS)
1190 int i, error, sstart, scount;
1193 sstart = acpi_pstate_start;
1194 scount = acpi_pstate_count;
1195 for (i = 0; i < acpi_npstates; ++i) {
1196 if (error == 0 && i)
1197 error = SYSCTL_OUT(req, " ", 1);
1202 if (i < sstart || i >= scount)
1207 ksnprintf(buf, sizeof(buf), pat,
1208 acpi_pstates[i].st_freq);
1209 error = SYSCTL_OUT(req, buf, strlen(buf));
1216 acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS)
1218 uint32_t freqs[ACPI_NPSTATE_MAX];
1219 int cnt, i, sstart, scount;
1221 sstart = acpi_pstate_start;
1222 scount = acpi_pstate_count;
1224 cnt = scount - sstart;
1225 for (i = 0; i < cnt; ++i)
1226 freqs[i] = acpi_pstates[sstart + i].st_freq;
1228 return sysctl_handle_opaque(oidp, freqs, cnt * sizeof(freqs[0]), req);
1232 acpi_pst_sysctl_power(SYSCTL_HANDLER_ARGS)
1234 uint32_t power[ACPI_NPSTATE_MAX];
1235 int cnt, i, sstart, scount;
1237 sstart = acpi_pstate_start;
1238 scount = acpi_pstate_count;
1240 cnt = scount - sstart;
1241 for (i = 0; i < cnt; ++i)
1242 power[i] = acpi_pstates[sstart + i].st_power;
1244 return sysctl_handle_opaque(oidp, power, cnt * sizeof(power[0]), req);
1248 acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS)
1250 struct acpi_pst_domain *dom = arg1;
1251 struct acpi_pst_softc *sc;
1255 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1258 if (error == 0 && loop)
1259 error = SYSCTL_OUT(req, " ", 1);
1261 ksnprintf(buf, sizeof(buf), "cpu%d", sc->pst_cpuid);
1262 error = SYSCTL_OUT(req, buf, strlen(buf));
1265 if (error == 0 && acpi_pst_md && acpi_pst_md->pmd_get_pstate) {
1266 const struct acpi_pstate *pstate;
1269 pstate = acpi_pst_get_pstate(sc);
1270 if (pstate == NULL) {
1273 ksnprintf(buf, sizeof(buf), "(%d)",
1277 error = SYSCTL_OUT(req, str, strlen(str));
1285 acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS)
1287 struct acpi_pst_domain *dom = arg1;
1290 KKASSERT(dom->pd_state >= 0 && dom->pd_state < acpi_npstates);
1292 freq = acpi_pstates[dom->pd_state].st_freq;
1294 error = sysctl_handle_int(oidp, &freq, 0, req);
1295 if (error || req->newptr == NULL)
1298 i = acpi_pst_freq2index(freq);
1302 acpi_pst_domain_set_pstate(dom, i, NULL);
1307 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS)
1311 KKASSERT(acpi_pst_global_state >= 0 &&
1312 acpi_pst_global_state < acpi_npstates);
1314 freq = acpi_pstates[acpi_pst_global_state].st_freq;
1316 error = sysctl_handle_int(oidp, &freq, 0, req);
1317 if (error || req->newptr == NULL)
1320 i = acpi_pst_freq2index(freq);
1324 acpi_pst_global_set_pstate(i);
1330 acpi_pst_check_csr_handler(netmsg_t msg)
1332 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1335 error = acpi_pst_md->pmd_check_csr(rmsg->ctrl, rmsg->status);
1336 lwkt_replymsg(&rmsg->base.lmsg, error);
1340 acpi_pst_check_csr(struct acpi_pst_softc *sc)
1342 struct netmsg_acpi_pst msg;
1344 if (acpi_pst_md == NULL)
1347 netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1348 MSGF_PRIORITY, acpi_pst_check_csr_handler);
1349 msg.ctrl = &sc->pst_creg;
1350 msg.status = &sc->pst_sreg;
1352 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1356 acpi_pst_check_pstates_handler(netmsg_t msg)
1360 error = acpi_pst_md->pmd_check_pstates(acpi_pstates, acpi_npstates);
1361 lwkt_replymsg(&msg->lmsg, error);
1365 acpi_pst_check_pstates(struct acpi_pst_softc *sc)
1367 struct netmsg_base msg;
1369 if (acpi_pst_md == NULL)
1372 netmsg_init(&msg, NULL, &curthread->td_msgport,
1373 MSGF_PRIORITY, acpi_pst_check_pstates_handler);
1375 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.lmsg, 0);
1379 acpi_pst_init_handler(netmsg_t msg)
1381 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1384 error = acpi_pst_md->pmd_init(rmsg->ctrl, rmsg->status);
1385 lwkt_replymsg(&rmsg->base.lmsg, error);
1389 acpi_pst_init(struct acpi_pst_softc *sc)
1391 struct netmsg_acpi_pst msg;
1393 if (acpi_pst_md == NULL)
1396 netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1397 MSGF_PRIORITY, acpi_pst_init_handler);
1398 msg.ctrl = &sc->pst_creg;
1399 msg.status = &sc->pst_sreg;
1401 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1405 acpi_pst_set_pstate_handler(netmsg_t msg)
1407 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1410 error = acpi_pst_md->pmd_set_pstate(rmsg->ctrl, rmsg->status,
1411 rmsg->base.lmsg.u.ms_resultp);
1412 lwkt_replymsg(&rmsg->base.lmsg, error);
1416 acpi_pst_set_pstate(struct acpi_pst_softc *sc, const struct acpi_pstate *pstate)
1418 struct netmsg_acpi_pst msg;
1420 KKASSERT(acpi_pst_md != NULL);
1422 netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1423 MSGF_PRIORITY, acpi_pst_set_pstate_handler);
1424 msg.base.lmsg.u.ms_resultp = __DECONST(void *, pstate);
1425 msg.ctrl = &sc->pst_creg;
1426 msg.status = &sc->pst_sreg;
1428 return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1432 acpi_pst_get_pstate_handler(netmsg_t msg)
1434 struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1435 const struct acpi_pstate *pstate;
1437 pstate = acpi_pst_md->pmd_get_pstate(rmsg->status, acpi_pstates,
1439 rmsg->base.lmsg.u.ms_resultp = __DECONST(void *, pstate);
1440 lwkt_replymsg(&rmsg->base.lmsg, 0);
1443 static const struct acpi_pstate *
1444 acpi_pst_get_pstate(struct acpi_pst_softc *sc)
1446 struct netmsg_acpi_pst msg;
1448 if (acpi_pst_md == NULL)
1451 netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1452 MSGF_PRIORITY, acpi_pst_get_pstate_handler);
1453 msg.status = &sc->pst_sreg;
1455 lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1456 return msg.base.lmsg.u.ms_resultp;
1460 acpi_pst_alloc_resource(device_t dev, ACPI_OBJECT *obj, int idx,
1461 struct acpi_pst_res *res)
1463 struct acpi_pst_softc *sc = device_get_softc(dev);
1467 error = acpi_PkgRawGas(obj, idx, &res->pr_gas);
1471 /* Allocate resource, if possible */
1472 res->pr_rid = sc->pst_parent->cpu_next_rid;
1473 acpi_bus_alloc_gas(dev, &type, &res->pr_rid, &res->pr_gas, &res->pr_res, 0);
1474 if (res->pr_res != NULL) {
1475 sc->pst_parent->cpu_next_rid++;
1476 res->pr_bt = rman_get_bustag(res->pr_res);
1477 res->pr_bh = rman_get_bushandle(res->pr_res);
1485 acpi_pst_domain_check_nproc(device_t dev, struct acpi_pst_domain *dom)
1487 struct acpi_pst_softc *pst;
1491 LIST_FOREACH(pst, &dom->pd_pstlist, pst_link)
1493 if (i == dom->pd_nproc) {
1495 * Some stupid BIOSes will set wrong "# of processors",
1496 * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
1499 device_printf(dev, "domain%u already contains %d "
1500 "P-States\n", dom->pd_dom, dom->pd_nproc);
1504 KKASSERT(i < dom->pd_nproc);
1508 acpi_pst_eval_ppc(struct acpi_pst_softc *sc, int *sstart)
1515 buf.Length = ACPI_ALLOCATE_BUFFER;
1516 status = AcpiEvaluateObject(sc->pst_handle, "_PPC", NULL, &buf);
1517 if (!ACPI_FAILURE(status)) {
1518 ACPI_OBJECT_LIST arglist;
1521 obj = (ACPI_OBJECT *)buf.Pointer;
1522 if (obj->Type == ACPI_TYPE_INTEGER) {
1523 if (obj->Integer.Value >= acpi_npstates) {
1524 device_printf(sc->pst_dev,
1525 "Invalid _PPC value\n");
1529 *sstart = obj->Integer.Value;
1531 device_printf(sc->pst_dev, "_PPC %d\n",
1535 device_printf(sc->pst_dev, "Invalid _PPC object\n");
1543 /* _PPC has been successfully processed */
1544 arglist.Pointer = arg;
1546 arg[0].Type = ACPI_TYPE_INTEGER;
1547 arg[0].Integer.Value = 0x80;
1548 arg[1].Type = ACPI_TYPE_INTEGER;
1549 arg[1].Integer.Value = 0;
1550 AcpiEvaluateObject(sc->pst_handle, "_OST", &arglist, NULL);
1558 acpi_pst_eval_pdl(struct acpi_pst_softc *sc, int *scount)
1565 buf.Length = ACPI_ALLOCATE_BUFFER;
1566 status = AcpiEvaluateObject(sc->pst_handle, "_PDL", NULL, &buf);
1567 if (!ACPI_FAILURE(status)) {
1568 obj = (ACPI_OBJECT *)buf.Pointer;
1569 if (obj->Type == ACPI_TYPE_INTEGER) {
1570 if (obj->Integer.Value >= acpi_npstates) {
1571 device_printf(sc->pst_dev,
1572 "Invalid _PDL value\n");
1576 if (obj->Integer.Value >= acpi_pstate_start) {
1577 *scount = obj->Integer.Value + 1;
1579 device_printf(sc->pst_dev, "_PDL %d\n",
1583 /* Prefer _PPC as stated in ACPI 5.1 8.4.4.6 */
1584 device_printf(sc->pst_dev, "conflict _PDL %ju "
1585 "and _PPC %d, ignore\n",
1586 (uintmax_t)obj->Integer.Value,
1590 device_printf(sc->pst_dev, "Invalid _PDL object\n");
1604 * Notify is serialized by acpi task thread.
1607 acpi_pst_notify(device_t dev)
1609 struct acpi_pst_softc *sc = device_get_softc(dev);
1610 boolean_t fixup = FALSE;
1614 * _PPC and _PDL evaluation order is critical. _PDL
1615 * evaluation depends on _PPC evaluation.
1617 if (sc->pst_flags & ACPI_PST_FLAG_PPC) {
1618 int sstart = acpi_pstate_start;
1620 acpi_pst_eval_ppc(sc, &sstart);
1621 if (acpi_pstate_start != sstart && sc->pst_cpuid == 0) {
1622 acpi_pstate_start = sstart;
1626 if (sc->pst_flags & ACPI_PST_FLAG_PDL) {
1627 int scount = acpi_pstate_count;
1629 acpi_pst_eval_pdl(sc, &scount);
1630 if (acpi_pstate_count != scount && sc->pst_cpuid == 0) {
1631 acpi_pstate_count = scount;
1636 if (fixup && acpi_pst_md != NULL &&
1637 acpi_pst_md->pmd_set_pstate != NULL)
1638 acpi_pst_global_fixup_pstate();