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