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