45b1a1104212f442a656563bb01c130b58b631ad
[dragonfly.git] / sys / dev / acpica / acpi_cpu_pstate.c
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:
10  * 
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.
20  * 
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.
33  */
34
35 #include "opt_acpi.h"
36
37 #include <sys/param.h>
38 #include <sys/bus.h>
39 #include <sys/kernel.h>
40 #include <sys/malloc.h>
41 #include <sys/queue.h>
42 #include <sys/rman.h>
43 #include <sys/sysctl.h>
44 #include <sys/msgport2.h>
45 #include <sys/cpu_topology.h>
46
47 #include <net/netisr2.h>
48 #include <net/netmsg2.h>
49 #include <net/if_var.h>
50
51 #include "acpi.h"
52 #include "acpivar.h"
53 #include "acpi_cpu.h"
54 #include "acpi_cpu_pstate.h"
55
56 #define ACPI_NPSTATE_MAX        16
57
58 #define ACPI_PSS_PX_NENTRY      6
59
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)
67
68 struct acpi_pst_softc;
69 LIST_HEAD(acpi_pst_list, acpi_pst_softc);
70
71 struct netmsg_acpi_pst {
72         struct netmsg_base base;
73         const struct acpi_pst_res *ctrl;
74         const struct acpi_pst_res *status;
75 };
76
77 struct acpi_pst_domain {
78         uint32_t                pd_dom;
79         uint32_t                pd_coord;
80         uint32_t                pd_nproc;
81         LIST_ENTRY(acpi_pst_domain) pd_link;
82
83         uint32_t                pd_flags;
84
85         int                     pd_state;
86         struct acpi_pst_list    pd_pstlist;
87
88         struct sysctl_ctx_list  pd_sysctl_ctx;
89         struct sysctl_oid       *pd_sysctl_tree;
90 };
91 LIST_HEAD(acpi_pst_domlist, acpi_pst_domain);
92
93 #define ACPI_PSTDOM_FLAG_STUB   0x1     /* stub domain, no _PSD */
94 #define ACPI_PSTDOM_FLAG_DEAD   0x2     /* domain can't be started */
95 #define ACPI_PSTDOM_FLAG_INT    0x4     /* domain created from Integer _PSD */
96
97 struct acpi_pst_softc {
98         device_t                pst_dev;
99         struct acpi_cpu_softc   *pst_parent;
100         struct acpi_pst_domain  *pst_domain;
101         struct acpi_pst_res     pst_creg;
102         struct acpi_pst_res     pst_sreg;
103
104         int                     pst_state;
105         int                     pst_cpuid;
106
107         ACPI_HANDLE             pst_handle;
108
109         LIST_ENTRY(acpi_pst_softc) pst_link;
110 };
111
112 static int      acpi_pst_probe(device_t dev);
113 static int      acpi_pst_attach(device_t dev);
114
115 static void     acpi_pst_postattach(void *);
116 static struct acpi_pst_domain *
117                 acpi_pst_domain_create_int(device_t, uint32_t);
118 static struct acpi_pst_domain *
119                 acpi_pst_domain_create_pkg(device_t, ACPI_OBJECT *);
120 static struct acpi_pst_domain *
121                 acpi_pst_domain_find(uint32_t);
122 static struct acpi_pst_domain *
123                 acpi_pst_domain_alloc(uint32_t, uint32_t, uint32_t);
124 static int      acpi_pst_domain_set_pstate(struct acpi_pst_domain *, int);
125 static void     acpi_pst_domain_check_nproc(device_t, struct acpi_pst_domain *);
126 static int      acpi_pst_global_set_pstate(int);
127
128 static int      acpi_pst_check_csr(struct acpi_pst_softc *);
129 static int      acpi_pst_check_pstates(struct acpi_pst_softc *);
130 static int      acpi_pst_init(struct acpi_pst_softc *);
131 static int      acpi_pst_set_pstate(struct acpi_pst_softc *,
132                     const struct acpi_pstate *);
133 static const struct acpi_pstate *
134                 acpi_pst_get_pstate(struct acpi_pst_softc *);
135 static int      acpi_pst_alloc_resource(device_t, ACPI_OBJECT *, int,
136                     struct acpi_pst_res *);
137
138 static void     acpi_pst_check_csr_handler(netmsg_t);
139 static void     acpi_pst_check_pstates_handler(netmsg_t);
140 static void     acpi_pst_init_handler(netmsg_t);
141 static void     acpi_pst_set_pstate_handler(netmsg_t);
142 static void     acpi_pst_get_pstate_handler(netmsg_t);
143
144 static int      acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS);
145 static int      acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS);
146 static int      acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS);
147 static int      acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS);
148 static int      acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS);
149
150 static struct acpi_pst_domlist  acpi_pst_domains =
151         LIST_HEAD_INITIALIZER(acpi_pst_domains);
152 static int                      acpi_pst_domain_id;
153
154 static int                      acpi_pst_global_state;
155
156 static int                      acpi_pstate_start = -1;
157 static int                      acpi_pstate_count;
158 static int                      acpi_npstates;
159 static struct acpi_pstate       *acpi_pstates;
160
161 static const struct acpi_pst_md *acpi_pst_md;
162
163 static int                      acpi_pst_ht_reuse_domain = 1;
164 TUNABLE_INT("hw.acpi.cpu.pst.ht_reuse_domain", &acpi_pst_ht_reuse_domain);
165
166 static int                      acpi_pst_force_pkg_domain = 0;
167 TUNABLE_INT("hw.acpi.cpu.pst.force_pkg_domain", &acpi_pst_force_pkg_domain);
168
169 static device_method_t acpi_pst_methods[] = {
170         /* Device interface */
171         DEVMETHOD(device_probe,                 acpi_pst_probe),
172         DEVMETHOD(device_attach,                acpi_pst_attach),
173         DEVMETHOD(device_detach,                bus_generic_detach),
174         DEVMETHOD(device_shutdown,              bus_generic_shutdown),
175         DEVMETHOD(device_suspend,               bus_generic_suspend),
176         DEVMETHOD(device_resume,                bus_generic_resume),
177
178         /* Bus interface */
179         DEVMETHOD(bus_add_child,                bus_generic_add_child),
180         DEVMETHOD(bus_print_child,              bus_generic_print_child),
181         DEVMETHOD(bus_read_ivar,                bus_generic_read_ivar),
182         DEVMETHOD(bus_write_ivar,               bus_generic_write_ivar),
183         DEVMETHOD(bus_get_resource_list,        bus_generic_get_resource_list),
184         DEVMETHOD(bus_set_resource,             bus_generic_rl_set_resource),
185         DEVMETHOD(bus_get_resource,             bus_generic_rl_get_resource),
186         DEVMETHOD(bus_alloc_resource,           bus_generic_alloc_resource),
187         DEVMETHOD(bus_release_resource,         bus_generic_release_resource),
188         DEVMETHOD(bus_driver_added,             bus_generic_driver_added),
189         DEVMETHOD(bus_activate_resource,        bus_generic_activate_resource),
190         DEVMETHOD(bus_deactivate_resource,      bus_generic_deactivate_resource),
191         DEVMETHOD(bus_setup_intr,               bus_generic_setup_intr),
192         DEVMETHOD(bus_teardown_intr,            bus_generic_teardown_intr),
193
194         DEVMETHOD_END
195 };
196
197 static driver_t acpi_pst_driver = {
198         "cpu_pst",
199         acpi_pst_methods,
200         sizeof(struct acpi_pst_softc)
201 };
202
203 static devclass_t acpi_pst_devclass;
204 DRIVER_MODULE(cpu_pst, cpu, acpi_pst_driver, acpi_pst_devclass, NULL, NULL);
205 MODULE_DEPEND(cpu_pst, acpi, 1, 1, 1);
206
207 static __inline int
208 acpi_pst_freq2index(int freq)
209 {
210         int i;
211
212         for (i = 0; i < acpi_npstates; ++i) {
213                 if (acpi_pstates[i].st_freq == freq)
214                         return i;
215         }
216         return -1;
217 }
218
219 static int
220 acpi_pst_probe(device_t dev)
221 {
222         ACPI_BUFFER buf;
223         ACPI_HANDLE handle;
224         ACPI_STATUS status;
225         ACPI_OBJECT *obj;
226
227         if (acpi_disabled("cpu_pst") ||
228             acpi_get_type(dev) != ACPI_TYPE_PROCESSOR)
229                 return ENXIO;
230
231         if (acpi_pst_md == NULL)
232                 acpi_pst_md = acpi_pst_md_probe();
233
234         handle = acpi_get_handle(dev);
235
236         /*
237          * Check _PSD package
238          *
239          * NOTE:
240          * Some BIOSes do not expose _PCT for the second thread of
241          * CPU cores.  In this case, _PSD should be enough to get the
242          * P-state of the second thread working, since it must have
243          * the same _PCT and _PSS as the first thread in the same
244          * core.
245          */
246         buf.Pointer = NULL;
247         buf.Length = ACPI_ALLOCATE_BUFFER;
248         status = AcpiEvaluateObject(handle, "_PSD", NULL, &buf);
249         if (!ACPI_FAILURE(status)) {
250                 AcpiOsFree((ACPI_OBJECT *)buf.Pointer);
251                 goto done;
252         }
253
254         /*
255          * Check _PCT package
256          */
257         buf.Pointer = NULL;
258         buf.Length = ACPI_ALLOCATE_BUFFER;
259         status = AcpiEvaluateObject(handle, "_PCT", NULL, &buf);
260         if (ACPI_FAILURE(status)) {
261                 if (bootverbose) {
262                         device_printf(dev, "Can't get _PCT package - %s\n",
263                                       AcpiFormatException(status));
264                 }
265                 return ENXIO;
266         }
267
268         obj = (ACPI_OBJECT *)buf.Pointer;
269         if (!ACPI_PKG_VALID_EQ(obj, 2)) {
270                 device_printf(dev, "Invalid _PCT package\n");
271                 AcpiOsFree(obj);
272                 return ENXIO;
273         }
274         AcpiOsFree(obj);
275
276         /*
277          * Check _PSS package
278          */
279         buf.Pointer = NULL;
280         buf.Length = ACPI_ALLOCATE_BUFFER;
281         status = AcpiEvaluateObject(handle, "_PSS", NULL, &buf);
282         if (ACPI_FAILURE(status)) {
283                 device_printf(dev, "Can't get _PSS package - %s\n",
284                               AcpiFormatException(status));
285                 return ENXIO;
286         }
287
288         obj = (ACPI_OBJECT *)buf.Pointer;
289         if (!ACPI_PKG_VALID(obj, 1)) {
290                 device_printf(dev, "Invalid _PSS package\n");
291                 AcpiOsFree(obj);
292                 return ENXIO;
293         }
294         AcpiOsFree(obj);
295
296 done:
297         device_set_desc(dev, "ACPI CPU P-State");
298         return 0;
299 }
300
301 static int
302 acpi_pst_attach(device_t dev)
303 {
304         struct acpi_pst_softc *sc = device_get_softc(dev);
305         struct acpi_pst_domain *dom = NULL;
306         ACPI_BUFFER buf;
307         ACPI_STATUS status;
308         ACPI_OBJECT *obj;
309         struct acpi_pstate *pstate, *p;
310         int i, npstate, error, sstart, scount;
311
312         sc->pst_dev = dev;
313         sc->pst_parent = device_get_softc(device_get_parent(dev));
314         sc->pst_handle = acpi_get_handle(dev);
315         sc->pst_cpuid = acpi_get_magic(dev);
316
317         /*
318          * If there is a _PSD, then we create procossor domain
319          * accordingly.  If there is no _PSD, we just fake a
320          * default processor domain0.
321          */
322         buf.Pointer = NULL;
323         buf.Length = ACPI_ALLOCATE_BUFFER;
324         status = AcpiEvaluateObject(sc->pst_handle, "_PSD", NULL, &buf);
325         if (!ACPI_FAILURE(status)) {
326                 obj = (ACPI_OBJECT *)buf.Pointer;
327
328                 if (acpi_pst_domain_id > 0) {
329                         device_printf(dev, "Missing _PSD for certain CPUs\n");
330                         AcpiOsFree(obj);
331                         return ENXIO;
332                 }
333                 acpi_pst_domain_id = -1;
334
335                 if (ACPI_PKG_VALID_EQ(obj, 1)) {
336                         dom = acpi_pst_domain_create_pkg(dev,
337                                 &obj->Package.Elements[0]);
338                         if (dom == NULL) {
339                                 AcpiOsFree(obj);
340                                 return ENXIO;
341                         }
342                 } else {
343                         if (obj->Type != ACPI_TYPE_INTEGER) {
344                                 device_printf(dev,
345                                     "Invalid _PSD package, Type 0x%x\n",
346                                     obj->Type);
347                                 AcpiOsFree(obj);
348                                 return ENXIO;
349                         } else {
350                                 device_printf(dev, "Integer _PSD %ju\n",
351                                     (uintmax_t)obj->Integer.Value);
352                                 dom = acpi_pst_domain_create_int(dev,
353                                     obj->Integer.Value);
354                                 if (dom == NULL) {
355                                         AcpiOsFree(obj);
356                                         return ENXIO;
357                                 }
358                         }
359                 }
360
361                 /* Free _PSD */
362                 AcpiOsFree(buf.Pointer);
363         } else {
364                 if (acpi_pst_domain_id < 0) {
365                         device_printf(dev, "Missing _PSD for cpu%d\n",
366                             sc->pst_cpuid);
367                         return ENXIO;
368                 }
369
370                 /*
371                  * Create a stub one processor domain for each processor
372                  */
373                 dom = acpi_pst_domain_alloc(acpi_pst_domain_id,
374                         ACPI_PSD_COORD_SWANY, 1);
375                 dom->pd_flags |= ACPI_PSTDOM_FLAG_STUB;
376
377                 ++acpi_pst_domain_id;
378         }
379
380         /* Make sure that adding us will not overflow our domain */
381         acpi_pst_domain_check_nproc(dev, dom);
382
383         /*
384          * Get control/status registers from _PCT
385          */
386         buf.Pointer = NULL;
387         buf.Length = ACPI_ALLOCATE_BUFFER;
388         status = AcpiEvaluateObject(sc->pst_handle, "_PCT", NULL, &buf);
389         if (ACPI_FAILURE(status)) {
390                 struct acpi_pst_softc *pst;
391
392                 /*
393                  * No _PCT.  See the comment in acpi_pst_probe() near
394                  * _PSD check.
395                  *
396                  * Use control/status registers of another CPU in the
397                  * same domain, or in the same core, if the type of
398                  * these registers are "Fixed Hardware", e.g. on most
399                  * of the model Intel CPUs.
400                  */
401                 pst = LIST_FIRST(&dom->pd_pstlist);
402                 if (pst == NULL) {
403                         cpumask_t mask;
404
405                         mask = get_cpumask_from_level(sc->pst_cpuid,
406                             CORE_LEVEL);
407                         if (CPUMASK_TESTNZERO(mask)) {
408                                 struct acpi_pst_domain *dom1;
409
410                                 LIST_FOREACH(dom1, &acpi_pst_domains, pd_link) {
411                                         LIST_FOREACH(pst, &dom1->pd_pstlist,
412                                             pst_link) {
413                                                 if (CPUMASK_TESTBIT(mask,
414                                                     pst->pst_cpuid))
415                                                         break;
416                                         }
417                                         if (pst != NULL)
418                                                 break;
419                                 }
420                                 if (pst != NULL && acpi_pst_ht_reuse_domain) {
421                                         /*
422                                          * Use the same domain for CPUs in the
423                                          * same core.
424                                          */
425                                         device_printf(dev, "Destroy domain%u, "
426                                             "reuse domain%u\n",
427                                             dom->pd_dom, dom1->pd_dom);
428                                         LIST_REMOVE(dom, pd_link);
429                                         kfree(dom, M_DEVBUF);
430                                         dom = dom1;
431                                         /*
432                                          * Make sure that adding us will not
433                                          * overflow the domain containing
434                                          * siblings in the same core.
435                                          */
436                                         acpi_pst_domain_check_nproc(dev, dom);
437                                 }
438                         }
439                 }
440                 if (pst != NULL &&
441                     pst->pst_creg.pr_res == NULL &&
442                     pst->pst_creg.pr_rid == 0 &&
443                     pst->pst_creg.pr_gas.SpaceId ==
444                     ACPI_ADR_SPACE_FIXED_HARDWARE &&
445                     pst->pst_sreg.pr_res == NULL &&
446                     pst->pst_sreg.pr_rid == 0 &&
447                     pst->pst_sreg.pr_gas.SpaceId ==
448                     ACPI_ADR_SPACE_FIXED_HARDWARE) {
449                         sc->pst_creg = pst->pst_creg;
450                         sc->pst_sreg = pst->pst_sreg;
451                         device_printf(dev,
452                             "No _PCT; reuse %s control/status regs\n",
453                             device_get_nameunit(pst->pst_dev));
454                         goto fetch_pss;
455                 }
456                 device_printf(dev, "Can't get _PCT package - %s\n",
457                               AcpiFormatException(status));
458                 return ENXIO;
459         }
460
461         obj = (ACPI_OBJECT *)buf.Pointer;
462         if (!ACPI_PKG_VALID_EQ(obj, 2)) {
463                 device_printf(dev, "Invalid _PCT package\n");
464                 AcpiOsFree(obj);
465                 return ENXIO;
466         }
467
468         /* Save and try allocating control register */
469         error = acpi_pst_alloc_resource(dev, obj, 0, &sc->pst_creg);
470         if (error) {
471                 AcpiOsFree(obj);
472                 return error;
473         }
474         if (bootverbose) {
475                 device_printf(dev, "control reg %d %jx\n",
476                               sc->pst_creg.pr_gas.SpaceId,
477                               (uintmax_t)sc->pst_creg.pr_gas.Address);
478         }
479
480         /* Save and try allocating status register */
481         error = acpi_pst_alloc_resource(dev, obj, 1, &sc->pst_sreg);
482         if (error) {
483                 AcpiOsFree(obj);
484                 return error;
485         }
486         if (bootverbose) {
487                 device_printf(dev, "status reg %d %jx\n",
488                               sc->pst_sreg.pr_gas.SpaceId,
489                               (uintmax_t)sc->pst_sreg.pr_gas.Address);
490         }
491
492         /* Free _PCT */
493         AcpiOsFree(obj);
494
495 fetch_pss:
496         /*
497          * Create P-State table according to _PSS
498          */
499         buf.Pointer = NULL;
500         buf.Length = ACPI_ALLOCATE_BUFFER;
501         status = AcpiEvaluateObject(sc->pst_handle, "_PSS", NULL, &buf);
502         if (ACPI_FAILURE(status)) {
503                 /*
504                  * No _PSS.  See the comment in acpi_pst_probe() near
505                  * _PSD check.
506                  *
507                  * Assume _PSS are same across all CPUs; well, they
508                  * should/have to be so.
509                  */
510                 if (acpi_npstates > 0 && acpi_pstates != NULL) {
511                         device_printf(dev, "No _PSS\n");
512                         goto fetch_ppc;
513                 }
514                 device_printf(dev, "Can't get _PSS package - %s\n",
515                               AcpiFormatException(status));
516                 return ENXIO;
517         }
518
519         obj = (ACPI_OBJECT *)buf.Pointer;
520         if (!ACPI_PKG_VALID(obj, 1)) {
521                 device_printf(dev, "Invalid _PSS package\n");
522                 AcpiOsFree(obj);
523                 return ENXIO;
524         }
525
526         /* Don't create too many P-States */
527         npstate = obj->Package.Count;
528         if (npstate > ACPI_NPSTATE_MAX) {
529                 device_printf(dev, "Too many P-States, %d->%d\n",
530                               npstate, ACPI_NPSTATE_MAX);
531                 npstate = ACPI_NPSTATE_MAX;
532         }
533
534         /*
535          * If we have already created P-State table,
536          * we must make sure that number of entries
537          * is consistent.
538          */
539         if (acpi_pstates != NULL && acpi_npstates != npstate) {
540                 device_printf(dev, "Inconsistent # of P-States "
541                               "cross Processor objects\n");
542                 AcpiOsFree(obj);
543                 return ENXIO;
544         }
545
546         /*
547          * Create a temporary P-State table
548          */
549         pstate = kmalloc(sizeof(*pstate) * npstate, M_TEMP, M_WAITOK);
550         for (i = 0, p = pstate; i < npstate; ++i, ++p) {
551                 ACPI_OBJECT *pkg;
552                 uint32_t *ptr[ACPI_PSS_PX_NENTRY] = {
553                         &p->st_freq, &p->st_power, &p->st_xsit_lat,
554                         &p->st_bm_lat, &p->st_cval, &p->st_sval
555                 };
556                 int j;
557
558                 pkg = &obj->Package.Elements[i];
559                 if (!ACPI_PKG_VALID(pkg, ACPI_PSS_PX_NENTRY)) {
560                         device_printf(dev, "Invalud _PSS P%d\n", i);
561                         AcpiOsFree(obj);
562                         kfree(pstate, M_TEMP);
563                         return ENXIO;
564                 }
565                 for (j = 0; j < ACPI_PSS_PX_NENTRY; ++j) {
566                         if (acpi_PkgInt32(pkg, j, ptr[j]) != 0) {
567                                 device_printf(dev, "Can't extract "
568                                               "_PSS P%d %dth entry\n", i, j);
569                                 AcpiOsFree(obj);
570                                 kfree(pstate, M_TEMP);
571                                 return ENXIO;
572                         }
573                 }
574         }
575
576         /* Free _PSS */
577         AcpiOsFree(obj);
578
579         if (acpi_pstates == NULL) {
580                 /*
581                  * If no P-State table is created yet,
582                  * save the temporary one we just created.
583                  */
584                 acpi_pstates = pstate;
585                 acpi_npstates = npstate;
586                 pstate = NULL;
587
588                 if (bootverbose) {
589                         for (i = 0; i < acpi_npstates; ++i) {
590                                 device_printf(dev,
591                                 "freq %u, pwr %u, xlat %u, blat %u, "
592                                 "cv %08x, sv %08x\n",
593                                 acpi_pstates[i].st_freq,
594                                 acpi_pstates[i].st_power,
595                                 acpi_pstates[i].st_xsit_lat,
596                                 acpi_pstates[i].st_bm_lat,
597                                 acpi_pstates[i].st_cval,
598                                 acpi_pstates[i].st_sval);
599                         }
600                 }
601         } else {
602                 /*
603                  * Make sure that P-State tables are same
604                  * for all processors.
605                  */
606                 if (memcmp(pstate, acpi_pstates,
607                            sizeof(*pstate) * npstate) != 0) {
608                         device_printf(dev, "Inconsistent _PSS "
609                                       "cross Processor objects\n");
610 #if 0
611                         /*
612                          * Some BIOSes create different P-State tables;
613                          * just trust the one from the BSP and move on.
614                          */
615                         kfree(pstate, M_TEMP);
616                         return ENXIO;
617 #endif
618                 }
619                 kfree(pstate, M_TEMP);
620         }
621
622 fetch_ppc:
623         /* By default, we start from P-State table's first entry */
624         sstart = 0;
625
626         /*
627          * Adjust the usable first entry of P-State table,
628          * if there is _PPC object.
629          */
630         buf.Pointer = NULL;
631         buf.Length = ACPI_ALLOCATE_BUFFER;
632         status = AcpiEvaluateObject(sc->pst_handle, "_PPC", NULL, &buf);
633         if (!ACPI_FAILURE(status)) {
634                 ACPI_OBJECT_LIST arglist;
635                 ACPI_OBJECT arg[2];
636
637                 obj = (ACPI_OBJECT *)buf.Pointer;
638                 if (obj->Type == ACPI_TYPE_INTEGER) {
639                         if (obj->Integer.Value >= acpi_npstates) {
640                                 device_printf(dev, "Invalid _PPC value\n");
641                                 AcpiOsFree(obj);
642                                 return ENXIO;
643                         }
644                         sstart = obj->Integer.Value;
645                         if (bootverbose)
646                                 device_printf(dev, "_PPC %d\n", sstart);
647
648                         /* TODO: Install notifiy handler */
649                 } else {
650                         device_printf(dev, "Invalid _PPC object\n");
651                         AcpiOsFree(obj);
652                         return ENXIO;
653                 }
654
655                 /* Free _PPC */
656                 AcpiOsFree(obj);
657
658                 /* _PPC has been successfully processed */
659                 arglist.Pointer = arg;
660                 arglist.Count = 2;
661                 arg[0].Type = ACPI_TYPE_INTEGER;
662                 arg[0].Integer.Value = 0x80;
663                 arg[1].Type = ACPI_TYPE_INTEGER;
664                 arg[1].Integer.Value = 0;
665                 AcpiEvaluateObject(sc->pst_handle, "_OST", &arglist, NULL);
666         }
667         if (acpi_pstate_start < 0) {
668                 acpi_pstate_start = sstart;
669         } else if (acpi_pstate_start != sstart) {
670                 device_printf(dev, "_PPC mismatch, was %d, now %d\n",
671                     acpi_pstate_start, sstart);
672                 if (acpi_pstate_start < sstart) {
673                         device_printf(dev, "_PPC %d -> %d\n",
674                             acpi_pstate_start, sstart);
675                         acpi_pstate_start = sstart;
676                 }
677         }
678
679         /*
680          * By default, we assume number of usable P-States is same as
681          * number of P-States.
682          */
683         scount = acpi_npstates;
684
685         /*
686          * Adjust the number of usable entries in P-State table,
687          * if there is _PDL object.
688          */
689         buf.Pointer = NULL;
690         buf.Length = ACPI_ALLOCATE_BUFFER;
691         status = AcpiEvaluateObject(sc->pst_handle, "_PDL", NULL, &buf);
692         if (!ACPI_FAILURE(status)) {
693                 obj = (ACPI_OBJECT *)buf.Pointer;
694                 if (obj->Type == ACPI_TYPE_INTEGER) {
695                         if (obj->Integer.Value >= acpi_npstates) {
696                                 device_printf(dev, "Invalid _PDL value\n");
697                                 AcpiOsFree(obj);
698                                 return ENXIO;
699                         }
700                         if (obj->Integer.Value >= acpi_pstate_start) {
701                                 scount = obj->Integer.Value + 1;
702                                 if (bootverbose)
703                                         device_printf(dev, "_PDL %d\n", scount);
704                         } else {
705                                 /* Prefer _PPC as stated in ACPI 5.1 8.4.4.6 */
706                                 device_printf(dev, "conflict _PDL %ju and "
707                                     "_PPC %d, ignore\n",
708                                     (uintmax_t)obj->Integer.Value,
709                                     acpi_pstate_start);
710                         }
711
712                         /* TODO: Install notifiy handler */
713                 } else {
714                         device_printf(dev, "Invalid _PDL object\n");
715                         AcpiOsFree(obj);
716                         return ENXIO;
717                 }
718
719                 /* Free _PDL */
720                 AcpiOsFree(obj);
721         }
722         if (acpi_pstate_count == 0) {
723                 acpi_pstate_count = scount;
724         } else if (acpi_pstate_count != scount) {
725                 device_printf(dev, "_PDL mismatch, was %d, now %d\n",
726                     acpi_pstate_count, scount);
727                 if (acpi_pstate_count > scount) {
728                         device_printf(dev, "_PDL %d -> %d\n",
729                             acpi_pstate_count, scount);
730                         acpi_pstate_count = scount;
731                 }
732         }
733
734         /*
735          * Some CPUs only have package P-states, but some BIOSes put each
736          * hyperthread to its own P-state domain; allow user to override.
737          */
738         if (LIST_EMPTY(&dom->pd_pstlist) && acpi_pst_force_pkg_domain) {
739                 cpumask_t mask;
740
741                 mask = get_cpumask_from_level(sc->pst_cpuid, CHIP_LEVEL);
742                 if (CPUMASK_TESTNZERO(mask)) {
743                         struct acpi_pst_softc *pst = NULL;
744                         struct acpi_pst_domain *dom1;
745
746                         LIST_FOREACH(dom1, &acpi_pst_domains, pd_link) {
747                                 LIST_FOREACH(pst, &dom1->pd_pstlist,
748                                     pst_link) {
749                                         if (CPUMASK_TESTBIT(mask,
750                                             pst->pst_cpuid))
751                                                 break;
752                                 }
753                                 if (pst != NULL)
754                                         break;
755                         }
756                         if (pst != NULL &&
757                             memcmp(&pst->pst_creg, &sc->pst_creg,
758                                 sizeof(sc->pst_creg)) == 0 &&
759                             memcmp(&pst->pst_sreg, &sc->pst_sreg,
760                                 sizeof(sc->pst_sreg)) == 0) {
761                                 /*
762                                  * Use the same domain for CPUs in the
763                                  * same package.
764                                  */
765                                 device_printf(dev, "Destroy domain%u, "
766                                     "force pkg domain%u\n",
767                                     dom->pd_dom, dom1->pd_dom);
768                                 LIST_REMOVE(dom, pd_link);
769                                 kfree(dom, M_DEVBUF);
770                                 dom = dom1;
771                                 /*
772                                  * Make sure that adding us will not
773                                  * overflow the domain containing
774                                  * siblings in the same package.
775                                  */
776                                 acpi_pst_domain_check_nproc(dev, dom);
777                         }
778                 }
779         }
780
781         /* Link us with the domain */
782         sc->pst_domain = dom;
783         LIST_INSERT_HEAD(&dom->pd_pstlist, sc, pst_link);
784
785         if (device_get_unit(dev) == 0)
786                 AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_pst_postattach, NULL);
787
788         return 0;
789 }
790
791 static struct acpi_pst_domain *
792 acpi_pst_domain_create_pkg(device_t dev, ACPI_OBJECT *obj)
793 {
794         struct acpi_pst_domain *dom;
795         uint32_t val, domain, coord, nproc;
796
797         if (!ACPI_PKG_VALID_EQ(obj, 5)) {
798                 device_printf(dev, "Invalid _PSD package\n");
799                 return NULL;
800         }
801
802         /* NumberOfEntries */
803         if (acpi_PkgInt32(obj, 0, &val) != 0 || val != 5) {
804                 device_printf(dev, "Invalid _PSD NumberOfEntries\n");
805                 return NULL;
806         }
807
808         /* Revision */
809         if (acpi_PkgInt32(obj, 1, &val) != 0 || val != 0) {
810                 device_printf(dev, "Invalid _PSD Revision\n");
811                 return NULL;
812         }
813
814         if (acpi_PkgInt32(obj, 2, &domain) != 0 ||
815             acpi_PkgInt32(obj, 3, &coord) != 0 ||
816             acpi_PkgInt32(obj, 4, &nproc) != 0) {
817                 device_printf(dev, "Can't extract _PSD package\n");
818                 return NULL;
819         }
820
821         if (!ACPI_PSD_COORD_VALID(coord)) {
822                 device_printf(dev, "Invalid _PSD CoordType (%#x)\n", coord);
823                 return NULL;
824         }
825
826         if (nproc > MAXCPU) {
827                 /*
828                  * If NumProcessors is greater than MAXCPU
829                  * and domain's coordination is SWALL, then
830                  * we will never be able to start all CPUs
831                  * within this domain, and power state
832                  * transition will never be completed, so we
833                  * just bail out here.
834                  */
835                 if (coord == ACPI_PSD_COORD_SWALL) {
836                         device_printf(dev, "Unsupported _PSD NumProcessors "
837                                       "(%d)\n", nproc);
838                         return NULL;
839                 }
840         } else if (nproc == 0) {
841                 device_printf(dev, "_PSD NumProcessors are zero\n");
842                 return NULL;
843         }
844
845         dom = acpi_pst_domain_find(domain);
846         if (dom != NULL) {
847                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_INT) {
848                         device_printf(dev, "Mixed Integer _PSD and "
849                             "Package _PSD\n");
850                         return NULL;
851                 }
852                 if (dom->pd_coord != coord) {
853                         device_printf(dev, "Inconsistent _PSD coord "
854                             "information cross Processor objects\n");
855                         return NULL;
856                 }
857                 if (dom->pd_nproc != nproc) {
858                         device_printf(dev, "Inconsistent _PSD nproc "
859                             "information cross Processor objects\n");
860                         /*
861                          * Some stupid BIOSes will set wrong "# of processors",
862                          * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
863                          */
864                 }
865                 return dom;
866         }
867
868         dom = acpi_pst_domain_alloc(domain, coord, nproc);
869         if (bootverbose) {
870                 device_printf(dev, "create pkg domain%u, coord %#x\n",
871                     dom->pd_dom, dom->pd_coord);
872         }
873
874         return dom;
875 }
876
877 static struct acpi_pst_domain *
878 acpi_pst_domain_create_int(device_t dev, uint32_t domain)
879 {
880         struct acpi_pst_domain *dom;
881
882         dom = acpi_pst_domain_find(domain);
883         if (dom != NULL) {
884                 if ((dom->pd_flags & ACPI_PSTDOM_FLAG_INT) == 0) {
885                         device_printf(dev, "Mixed Package _PSD and "
886                             "Integer _PSD\n");
887                         return NULL;
888                 }
889                 KKASSERT(dom->pd_coord == ACPI_PSD_COORD_SWALL);
890
891                 dom->pd_nproc++;
892                 return dom;
893         }
894
895         dom = acpi_pst_domain_alloc(domain, ACPI_PSD_COORD_SWALL, 1);
896         dom->pd_flags |= ACPI_PSTDOM_FLAG_INT;
897
898         if (bootverbose)
899                 device_printf(dev, "create int domain%u\n", dom->pd_dom);
900
901         return dom;
902 }
903
904 static struct acpi_pst_domain *
905 acpi_pst_domain_find(uint32_t domain)
906 {
907         struct acpi_pst_domain *dom;
908
909         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
910                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_STUB)
911                         continue;
912                 if (dom->pd_dom == domain)
913                         return dom;
914         }
915         return NULL;
916 }
917
918 static struct acpi_pst_domain *
919 acpi_pst_domain_alloc(uint32_t domain, uint32_t coord, uint32_t nproc)
920 {
921         struct acpi_pst_domain *dom;
922
923         dom = kmalloc(sizeof(*dom), M_DEVBUF, M_WAITOK | M_ZERO);
924         dom->pd_dom = domain;
925         dom->pd_coord = coord;
926         dom->pd_nproc = nproc;
927         LIST_INIT(&dom->pd_pstlist);
928
929         LIST_INSERT_HEAD(&acpi_pst_domains, dom, pd_link);
930
931         return dom;
932 }
933
934 static int
935 acpi_pst_domain_set_pstate(struct acpi_pst_domain *dom, int i)
936 {
937         const struct acpi_pstate *pstate;
938         struct acpi_pst_softc *sc;
939         int done, error;
940
941         KKASSERT(i >= 0 && i < acpi_npstates);
942         pstate = &acpi_pstates[i];
943
944         done = 0;
945         LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
946                 if (!done) {
947                         error = acpi_pst_set_pstate(sc, pstate);
948                         if (error) {
949                                 device_printf(sc->pst_dev, "can't set "
950                                               "freq %d\n", pstate->st_freq);
951                                 /* XXX error cleanup? */
952                         }
953                         if (dom->pd_coord == ACPI_PSD_COORD_SWANY)
954                                 done = 1;
955                 }
956                 sc->pst_state = i;
957         }
958         dom->pd_state = i;
959
960         return 0;
961 }
962
963 static int
964 acpi_pst_global_set_pstate(int i)
965 {
966         struct acpi_pst_domain *dom;
967
968         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
969                 /* Skip dead domain */
970                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD)
971                         continue;
972                 acpi_pst_domain_set_pstate(dom, i);
973         }
974         acpi_pst_global_state = i;
975
976         return 0;
977 }
978
979 static void
980 acpi_pst_postattach(void *arg __unused)
981 {
982         struct acpi_pst_domain *dom;
983         struct acpi_cpu_softc *cpu;
984         device_t *devices;
985         int i, ndevices, error, has_domain;
986
987         devices = NULL;
988         ndevices = 0;
989         error = devclass_get_devices(acpi_pst_devclass, &devices, &ndevices);
990         if (error)
991                 return;
992
993         if (ndevices == 0)
994                 return;
995
996         cpu = NULL;
997         for (i = 0; i < ndevices; ++i) {
998                 cpu = device_get_softc(device_get_parent(devices[i]));
999                 if (cpu->glob_sysctl_tree != NULL)
1000                         break;
1001         }
1002         kfree(devices, M_TEMP);
1003         KKASSERT(cpu != NULL);
1004
1005         if (acpi_pst_md == NULL)
1006                 kprintf("ACPI: no P-State CPU driver\n");
1007
1008         has_domain = 0;
1009         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
1010                 struct acpi_pst_softc *sc;
1011                 char buf[32];
1012
1013                 dom->pd_state = acpi_pstate_start;
1014
1015                 /*
1016                  * Make sure that all processors belonging to this
1017                  * domain are located.
1018                  */
1019                 i = 0;
1020                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1021                         sc->pst_state = acpi_pstate_start;
1022                         ++i;
1023                 }
1024                 if (i != dom->pd_nproc) {
1025                         KKASSERT(i < dom->pd_nproc);
1026
1027                         kprintf("ACPI: domain%u misses processors, "
1028                                 "should be %d, got %d\n", dom->pd_dom,
1029                                 dom->pd_nproc, i);
1030                         if (dom->pd_coord == ACPI_PSD_COORD_SWALL) {
1031                                 /*
1032                                  * If this domain's coordination is
1033                                  * SWALL and we don't see all of the
1034                                  * member CPUs of this domain, then
1035                                  * the P-State transition will never
1036                                  * be completed, so just leave this
1037                                  * domain out.
1038                                  */
1039                                 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1040                                 continue;
1041                         }
1042                         dom->pd_nproc = i;
1043                 }
1044
1045                 /*
1046                  * Validate P-State configurations for this domain
1047                  */
1048                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1049                         error = acpi_pst_check_csr(sc);
1050                         if (error)
1051                                 break;
1052
1053                         error = acpi_pst_check_pstates(sc);
1054                         if (error)
1055                                 break;
1056                 }
1057                 if (sc != NULL) {
1058                         kprintf("ACPI: domain%u P-State configuration "
1059                                 "check failed\n", dom->pd_dom);
1060                         dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1061                         continue;
1062                 }
1063
1064                 /*
1065                  * Do necssary P-State initialization
1066                  */
1067                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1068                         error = acpi_pst_init(sc);
1069                         if (error)
1070                                 break;
1071                 }
1072                 if (sc != NULL) {
1073                         kprintf("ACPI: domain%u P-State initialization "
1074                                 "check failed\n", dom->pd_dom);
1075                         dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
1076                         continue;
1077                 }
1078
1079                 has_domain = 1;
1080
1081                 ksnprintf(buf, sizeof(buf), "px_dom%u", dom->pd_dom);
1082
1083                 sysctl_ctx_init(&dom->pd_sysctl_ctx);
1084                 dom->pd_sysctl_tree =
1085                 SYSCTL_ADD_NODE(&dom->pd_sysctl_ctx,
1086                         SYSCTL_CHILDREN(cpu->glob_sysctl_tree),
1087                         OID_AUTO, buf, CTLFLAG_RD, 0,
1088                         "P-State domain");
1089                 if (dom->pd_sysctl_tree == NULL) {
1090                         kprintf("ACPI: Can't create sysctl tree for domain%u",
1091                                 dom->pd_dom);
1092                         continue;
1093                 }
1094
1095                 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1096                                 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1097                                 OID_AUTO, "available",
1098                                 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_SKIP,
1099                                 dom, 0, acpi_pst_sysctl_freqs, "A",
1100                                 "available frequencies");
1101
1102                 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1103                                 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1104                                 OID_AUTO, "avail",
1105                                 CTLTYPE_OPAQUE | CTLFLAG_RD,
1106                                 dom, 0, acpi_pst_sysctl_freqs_bin, "IU",
1107                                 "available frequencies");
1108
1109                 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1110                                 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1111                                 OID_AUTO, "members",
1112                                 CTLTYPE_STRING | CTLFLAG_RD,
1113                                 dom, 0, acpi_pst_sysctl_members, "A",
1114                                 "member cpus");
1115
1116                 if (acpi_pst_md != NULL &&
1117                     acpi_pst_md->pmd_set_pstate != NULL) {
1118                         SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
1119                                         SYSCTL_CHILDREN(dom->pd_sysctl_tree),
1120                                         OID_AUTO, "select",
1121                                         CTLTYPE_UINT | CTLFLAG_RW,
1122                                         dom, 0, acpi_pst_sysctl_select,
1123                                         "IU", "select freq");
1124                 }
1125         }
1126
1127         if (has_domain && acpi_pst_md != NULL &&
1128             acpi_pst_md->pmd_set_pstate != NULL) {
1129                 SYSCTL_ADD_PROC(&cpu->glob_sysctl_ctx,
1130                                 SYSCTL_CHILDREN(cpu->glob_sysctl_tree),
1131                                 OID_AUTO, "px_global",
1132                                 CTLTYPE_UINT | CTLFLAG_RW,
1133                                 NULL, 0, acpi_pst_sysctl_global,
1134                                 "IU", "select freq for all domains");
1135
1136                 acpi_pst_global_set_pstate(acpi_pstate_start);
1137         }
1138 }
1139
1140 static int
1141 acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS)
1142 {
1143         int i, error;
1144
1145         error = 0;
1146         for (i = 0; i < acpi_npstates; ++i) {
1147                 if (error == 0 && i)
1148                         error = SYSCTL_OUT(req, " ", 1);
1149                 if (error == 0) {
1150                         const char *pat;
1151                         char buf[32];
1152
1153                         if (i < acpi_pstate_start || i >= acpi_pstate_count)
1154                                 pat = "(%u)";
1155                         else
1156                                 pat = "%u";
1157
1158                         ksnprintf(buf, sizeof(buf), pat,
1159                                   acpi_pstates[i].st_freq);
1160                         error = SYSCTL_OUT(req, buf, strlen(buf));
1161                 }
1162         }
1163         return error;
1164 }
1165
1166 static int
1167 acpi_pst_sysctl_freqs_bin(SYSCTL_HANDLER_ARGS)
1168 {
1169         uint32_t freqs[ACPI_NPSTATE_MAX];
1170         int cnt, i;
1171
1172         cnt = acpi_pstate_count - acpi_pstate_start;
1173         for (i = 0; i < cnt; ++i)
1174                 freqs[i] = acpi_pstates[acpi_pstate_start + i].st_freq;
1175
1176         return sysctl_handle_opaque(oidp, freqs, cnt * sizeof(freqs[0]), req);
1177 }
1178
1179 static int
1180 acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS)
1181 {
1182         struct acpi_pst_domain *dom = arg1;
1183         struct acpi_pst_softc *sc;
1184         int loop, error;
1185
1186         loop = error = 0;
1187         LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
1188                 char buf[32];
1189
1190                 if (error == 0 && loop)
1191                         error = SYSCTL_OUT(req, " ", 1);
1192                 if (error == 0) {
1193                         ksnprintf(buf, sizeof(buf), "cpu%d", sc->pst_cpuid);
1194                         error = SYSCTL_OUT(req, buf, strlen(buf));
1195                 }
1196
1197                 if (error == 0 && acpi_pst_md && acpi_pst_md->pmd_get_pstate) {
1198                         const struct acpi_pstate *pstate;
1199                         const char *str;
1200
1201                         pstate = acpi_pst_get_pstate(sc);
1202                         if (pstate == NULL) {
1203                                 str = "(*)";
1204                         } else {
1205                                 ksnprintf(buf, sizeof(buf), "(%d)",
1206                                           pstate->st_freq);
1207                                 str = buf;
1208                         }
1209                         error = SYSCTL_OUT(req, str, strlen(str));
1210                 }
1211                 ++loop;
1212         }
1213         return error;
1214 }
1215
1216 static int
1217 acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS)
1218 {
1219         struct acpi_pst_domain *dom = arg1;
1220         int error, i, freq;
1221
1222         KKASSERT(dom->pd_state >= 0 && dom->pd_state < acpi_npstates);
1223
1224         freq = acpi_pstates[dom->pd_state].st_freq;
1225
1226         error = sysctl_handle_int(oidp, &freq, 0, req);
1227         if (error || req->newptr == NULL)
1228                 return error;
1229
1230         i = acpi_pst_freq2index(freq);
1231         if (i < 0)
1232                 return EINVAL;
1233
1234         acpi_pst_domain_set_pstate(dom, i);
1235         return 0;
1236 }
1237
1238 static int
1239 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS)
1240 {
1241         int error, i, freq;
1242
1243         KKASSERT(acpi_pst_global_state >= 0 &&
1244                  acpi_pst_global_state < acpi_npstates);
1245
1246         freq = acpi_pstates[acpi_pst_global_state].st_freq;
1247
1248         error = sysctl_handle_int(oidp, &freq, 0, req);
1249         if (error || req->newptr == NULL)
1250                 return error;
1251
1252         i = acpi_pst_freq2index(freq);
1253         if (i < 0)
1254                 return EINVAL;
1255
1256         acpi_pst_global_set_pstate(i);
1257
1258         return 0;
1259 }
1260
1261 static void
1262 acpi_pst_check_csr_handler(netmsg_t msg)
1263 {
1264         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1265         int error;
1266
1267         error = acpi_pst_md->pmd_check_csr(rmsg->ctrl, rmsg->status);
1268         lwkt_replymsg(&rmsg->base.lmsg, error);
1269 }
1270
1271 static int
1272 acpi_pst_check_csr(struct acpi_pst_softc *sc)
1273 {
1274         struct netmsg_acpi_pst msg;
1275
1276         if (acpi_pst_md == NULL)
1277                 return 0;
1278
1279         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1280                     MSGF_PRIORITY, acpi_pst_check_csr_handler);
1281         msg.ctrl = &sc->pst_creg;
1282         msg.status = &sc->pst_sreg;
1283
1284         return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1285 }
1286
1287 static void
1288 acpi_pst_check_pstates_handler(netmsg_t msg)
1289 {
1290         int error;
1291
1292         error = acpi_pst_md->pmd_check_pstates(acpi_pstates, acpi_npstates);
1293         lwkt_replymsg(&msg->lmsg, error);
1294 }
1295
1296 static int
1297 acpi_pst_check_pstates(struct acpi_pst_softc *sc)
1298 {
1299         struct netmsg_base msg;
1300
1301         if (acpi_pst_md == NULL)
1302                 return 0;
1303
1304         netmsg_init(&msg, NULL, &curthread->td_msgport,
1305                     MSGF_PRIORITY, acpi_pst_check_pstates_handler);
1306
1307         return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.lmsg, 0);
1308 }
1309
1310 static void
1311 acpi_pst_init_handler(netmsg_t msg)
1312 {
1313         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1314         int error;
1315
1316         error = acpi_pst_md->pmd_init(rmsg->ctrl, rmsg->status);
1317         lwkt_replymsg(&rmsg->base.lmsg, error);
1318 }
1319
1320 static int
1321 acpi_pst_init(struct acpi_pst_softc *sc)
1322 {
1323         struct netmsg_acpi_pst msg;
1324
1325         if (acpi_pst_md == NULL)
1326                 return 0;
1327
1328         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1329                     MSGF_PRIORITY, acpi_pst_init_handler);
1330         msg.ctrl = &sc->pst_creg;
1331         msg.status = &sc->pst_sreg;
1332
1333         return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1334 }
1335
1336 static void
1337 acpi_pst_set_pstate_handler(netmsg_t msg)
1338 {
1339         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1340         int error;
1341
1342         error = acpi_pst_md->pmd_set_pstate(rmsg->ctrl, rmsg->status,
1343                                             rmsg->base.lmsg.u.ms_resultp);
1344         lwkt_replymsg(&rmsg->base.lmsg, error);
1345 }
1346
1347 static int
1348 acpi_pst_set_pstate(struct acpi_pst_softc *sc, const struct acpi_pstate *pstate)
1349 {
1350         struct netmsg_acpi_pst msg;
1351
1352         KKASSERT(acpi_pst_md != NULL);
1353
1354         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1355                     MSGF_PRIORITY, acpi_pst_set_pstate_handler);
1356         msg.base.lmsg.u.ms_resultp = __DECONST(void *, pstate);
1357         msg.ctrl = &sc->pst_creg;
1358         msg.status = &sc->pst_sreg;
1359
1360         return lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1361 }
1362
1363 static void
1364 acpi_pst_get_pstate_handler(netmsg_t msg)
1365 {
1366         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1367         const struct acpi_pstate *pstate;
1368
1369         pstate = acpi_pst_md->pmd_get_pstate(rmsg->status, acpi_pstates,
1370                                              acpi_npstates);
1371         rmsg->base.lmsg.u.ms_resultp = __DECONST(void *, pstate);
1372         lwkt_replymsg(&rmsg->base.lmsg, 0);
1373 }
1374
1375 static const struct acpi_pstate *
1376 acpi_pst_get_pstate(struct acpi_pst_softc *sc)
1377 {
1378         struct netmsg_acpi_pst msg;
1379
1380         if (acpi_pst_md == NULL)
1381                 return 0;
1382
1383         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1384                     MSGF_PRIORITY, acpi_pst_get_pstate_handler);
1385         msg.status = &sc->pst_sreg;
1386
1387         lwkt_domsg(netisr_cpuport(sc->pst_cpuid), &msg.base.lmsg, 0);
1388         return msg.base.lmsg.u.ms_resultp;
1389 }
1390
1391 static int
1392 acpi_pst_alloc_resource(device_t dev, ACPI_OBJECT *obj, int idx,
1393                         struct acpi_pst_res *res)
1394 {
1395         struct acpi_pst_softc *sc = device_get_softc(dev);
1396         int error, type;
1397
1398         /* Save GAS */
1399         error = acpi_PkgRawGas(obj, idx, &res->pr_gas);
1400         if (error)
1401                 return error;
1402
1403         /* Allocate resource, if possible */
1404         res->pr_rid = sc->pst_parent->cpu_next_rid;
1405         acpi_bus_alloc_gas(dev, &type, &res->pr_rid, &res->pr_gas, &res->pr_res, 0);
1406         if (res->pr_res != NULL) {
1407                 sc->pst_parent->cpu_next_rid++;
1408                 res->pr_bt = rman_get_bustag(res->pr_res);
1409                 res->pr_bh = rman_get_bushandle(res->pr_res);
1410         } else {
1411                 res->pr_rid = 0;
1412         }
1413         return 0;
1414 }
1415
1416 static void
1417 acpi_pst_domain_check_nproc(device_t dev, struct acpi_pst_domain *dom)
1418 {
1419         struct acpi_pst_softc *pst;
1420         int i;
1421
1422         i = 0;
1423         LIST_FOREACH(pst, &dom->pd_pstlist, pst_link)
1424                 ++i;
1425         if (i == dom->pd_nproc) {
1426                 /*
1427                  * Some stupid BIOSes will set wrong "# of processors",
1428                  * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
1429                  */
1430                 if (bootverbose) {
1431                         device_printf(dev, "domain%u already contains %d "
1432                             "P-States\n", dom->pd_dom, dom->pd_nproc);
1433                 }
1434                 dom->pd_nproc++;
1435         }
1436         KKASSERT(i < dom->pd_nproc);
1437 }