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