kernel: Remove some unused variables in network drivers.
[dragonfly.git] / sys / dev / acpica5 / 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
46 #include <net/netisr.h>
47 #include <net/netmsg2.h>
48 #include <net/if_var.h>
49
50 #include "acpi.h"
51 #include "acpivar.h"
52 #include "acpi_cpu.h"
53 #include "acpi_cpu_pstate.h"
54
55 #define ACPI_NPSTATE_MAX        16
56
57 #define ACPI_PSS_PX_NENTRY      6
58
59 #define ACPI_PSD_COORD_SWALL    0xfc
60 #define ACPI_PSD_COORD_SWANY    0xfd
61 #define ACPI_PSD_COORD_HWALL    0xfe
62 #define ACPI_PSD_COORD_VALID(coord) \
63         ((coord) == ACPI_PSD_COORD_SWALL || \
64          (coord) == ACPI_PSD_COORD_SWANY || \
65          (coord) == ACPI_PSD_COORD_HWALL)
66
67 struct acpi_pst_softc;
68 LIST_HEAD(acpi_pst_list, acpi_pst_softc);
69
70 struct netmsg_acpi_pst {
71         struct netmsg_base base;
72         const struct acpi_pst_res *ctrl;
73         const struct acpi_pst_res *status;
74 };
75
76 struct acpi_pst_domain {
77         uint32_t                pd_dom;
78         uint32_t                pd_coord;
79         uint32_t                pd_nproc;
80         LIST_ENTRY(acpi_pst_domain) pd_link;
81
82         uint32_t                pd_flags;
83
84         int                     pd_state;
85         int                     pd_sstart;
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_cpux_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_sstart;
106         int                     pst_cpuid;
107
108         ACPI_HANDLE             pst_handle;
109
110         LIST_ENTRY(acpi_pst_softc) pst_link;
111 };
112
113 static int      acpi_pst_probe(device_t dev);
114 static int      acpi_pst_attach(device_t dev);
115
116 static void     acpi_pst_postattach(void *);
117 static struct acpi_pst_domain *
118                 acpi_pst_domain_create_int(device_t, uint32_t);
119 static struct acpi_pst_domain *
120                 acpi_pst_domain_create_pkg(device_t, ACPI_OBJECT *);
121 static struct acpi_pst_domain *
122                 acpi_pst_domain_find(uint32_t);
123 static struct acpi_pst_domain *
124                 acpi_pst_domain_alloc(uint32_t, uint32_t, uint32_t);
125 static int      acpi_pst_domain_set_pstate(struct acpi_pst_domain *, int);
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_members(SYSCTL_HANDLER_ARGS);
146 static int      acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS);
147 static int      acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS);
148
149 static struct acpi_pst_domlist  acpi_pst_domains =
150         LIST_HEAD_INITIALIZER(acpi_pst_domains);
151 static int                      acpi_pst_domain_id;
152
153 static int                      acpi_pst_global_state;
154
155 static int                      acpi_npstates;
156 static struct acpi_pstate       *acpi_pstates;
157
158 static const struct acpi_pst_md *acpi_pst_md;
159
160 static device_method_t acpi_pst_methods[] = {
161         /* Device interface */
162         DEVMETHOD(device_probe,                 acpi_pst_probe),
163         DEVMETHOD(device_attach,                acpi_pst_attach),
164         DEVMETHOD(device_detach,                bus_generic_detach),
165         DEVMETHOD(device_shutdown,              bus_generic_shutdown),
166         DEVMETHOD(device_suspend,               bus_generic_suspend),
167         DEVMETHOD(device_resume,                bus_generic_resume),
168
169         /* Bus interface */
170         DEVMETHOD(bus_add_child,                bus_generic_add_child),
171         DEVMETHOD(bus_print_child,              bus_generic_print_child),
172         DEVMETHOD(bus_read_ivar,                bus_generic_read_ivar),
173         DEVMETHOD(bus_write_ivar,               bus_generic_write_ivar),
174         DEVMETHOD(bus_get_resource_list,        bus_generic_get_resource_list),
175         DEVMETHOD(bus_set_resource,             bus_generic_rl_set_resource),
176         DEVMETHOD(bus_get_resource,             bus_generic_rl_get_resource),
177         DEVMETHOD(bus_alloc_resource,           bus_generic_alloc_resource),
178         DEVMETHOD(bus_release_resource,         bus_generic_release_resource),
179         DEVMETHOD(bus_driver_added,             bus_generic_driver_added),
180         DEVMETHOD(bus_activate_resource,        bus_generic_activate_resource),
181         DEVMETHOD(bus_deactivate_resource,      bus_generic_deactivate_resource),
182         DEVMETHOD(bus_setup_intr,               bus_generic_setup_intr),
183         DEVMETHOD(bus_teardown_intr,            bus_generic_teardown_intr),
184
185         { 0, 0 }
186 };
187
188 static driver_t acpi_pst_driver = {
189         "cpu_pst",
190         acpi_pst_methods,
191         sizeof(struct acpi_pst_softc)
192 };
193
194 static devclass_t acpi_pst_devclass;
195 DRIVER_MODULE(cpu_pst, cpu, acpi_pst_driver, acpi_pst_devclass, NULL, NULL);
196 MODULE_DEPEND(cpu_pst, acpi, 1, 1, 1);
197
198 static __inline int
199 acpi_pst_freq2index(int freq)
200 {
201         int i;
202
203         for (i = 0; i < acpi_npstates; ++i) {
204                 if (acpi_pstates[i].st_freq == freq)
205                         return i;
206         }
207         return -1;
208 }
209
210 static int
211 acpi_pst_probe(device_t dev)
212 {
213         ACPI_BUFFER buf;
214         ACPI_HANDLE handle;
215         ACPI_STATUS status;
216         ACPI_OBJECT *obj;
217
218         if (acpi_disabled("cpu_pst") ||
219             acpi_get_type(dev) != ACPI_TYPE_PROCESSOR)
220                 return ENXIO;
221
222         if (acpi_pst_md == NULL)
223                 acpi_pst_md = acpi_pst_md_probe();
224
225         handle = acpi_get_handle(dev);
226
227         /*
228          * Check _PCT package
229          */
230         buf.Pointer = NULL;
231         buf.Length = ACPI_ALLOCATE_BUFFER;
232         status = AcpiEvaluateObject(handle, "_PCT", NULL, &buf);
233         if (ACPI_FAILURE(status)) {
234                 if (bootverbose) {
235                         device_printf(dev, "Can't get _PCT package - %s\n",
236                                       AcpiFormatException(status));
237                 }
238                 return ENXIO;
239         }
240
241         obj = (ACPI_OBJECT *)buf.Pointer;
242         if (!ACPI_PKG_VALID_EQ(obj, 2)) {
243                 device_printf(dev, "Invalid _PCT package\n");
244                 AcpiOsFree(obj);
245                 return ENXIO;
246         }
247         AcpiOsFree(obj);
248
249         /*
250          * Check _PSS package
251          */
252         buf.Pointer = NULL;
253         buf.Length = ACPI_ALLOCATE_BUFFER;
254         status = AcpiEvaluateObject(handle, "_PSS", NULL, &buf);
255         if (ACPI_FAILURE(status)) {
256                 device_printf(dev, "Can't get _PSS package - %s\n",
257                               AcpiFormatException(status));
258                 return ENXIO;
259         }
260
261         obj = (ACPI_OBJECT *)buf.Pointer;
262         if (!ACPI_PKG_VALID(obj, 1)) {
263                 device_printf(dev, "Invalid _PSS package\n");
264                 AcpiOsFree(obj);
265                 return ENXIO;
266         }
267         AcpiOsFree(obj);
268
269         device_set_desc(dev, "ACPI CPU P-State");
270         return 0;
271 }
272
273 static int
274 acpi_pst_attach(device_t dev)
275 {
276         struct acpi_pst_softc *sc = device_get_softc(dev), *pst;
277         struct acpi_pst_domain *dom = NULL;
278         ACPI_BUFFER buf;
279         ACPI_STATUS status;
280         ACPI_OBJECT *obj;
281         struct acpi_pstate *pstate, *p;
282         int i, npstate, error;
283
284         sc->pst_dev = dev;
285         sc->pst_parent = device_get_softc(device_get_parent(dev));
286         sc->pst_handle = acpi_get_handle(dev);
287         sc->pst_cpuid = acpi_get_magic(dev);
288
289         /*
290          * If there is a _PSD, then we create procossor domain
291          * accordingly.  If there is no _PSD, we just fake a
292          * default processor domain0.
293          */
294         buf.Pointer = NULL;
295         buf.Length = ACPI_ALLOCATE_BUFFER;
296         status = AcpiEvaluateObject(sc->pst_handle, "_PSD", NULL, &buf);
297         if (!ACPI_FAILURE(status)) {
298                 obj = (ACPI_OBJECT *)buf.Pointer;
299
300                 if (acpi_pst_domain_id > 0) {
301                         device_printf(dev, "Missing _PSD for certain CPUs\n");
302                         AcpiOsFree(obj);
303                         return ENXIO;
304                 }
305                 acpi_pst_domain_id = -1;
306
307                 if (ACPI_PKG_VALID_EQ(obj, 1)) {
308                         dom = acpi_pst_domain_create_pkg(dev,
309                                 &obj->Package.Elements[0]);
310                         if (dom == NULL) {
311                                 AcpiOsFree(obj);
312                                 return ENXIO;
313                         }
314                 } else {
315                         if (obj->Type != ACPI_TYPE_INTEGER) {
316                                 device_printf(dev,
317                                     "Invalid _PSD package, Type 0x%x\n",
318                                     obj->Type);
319                                 AcpiOsFree(obj);
320                                 return ENXIO;
321                         } else {
322                                 device_printf(dev, "Integer _PSD %ju\n",
323                                     (uintmax_t)obj->Integer.Value);
324                                 dom = acpi_pst_domain_create_int(dev,
325                                     obj->Integer.Value);
326                                 if (dom == NULL) {
327                                         AcpiOsFree(obj);
328                                         return ENXIO;
329                                 }
330                         }
331                 }
332
333                 /* Free _PSD */
334                 AcpiOsFree(buf.Pointer);
335         } else {
336                 if (acpi_pst_domain_id < 0) {
337                         device_printf(dev, "Missing _PSD for cpu%d\n",
338                             sc->pst_cpuid);
339                         return ENXIO;
340                 }
341
342                 /*
343                  * Create a stub one processor domain for each processor
344                  */
345                 dom = acpi_pst_domain_alloc(acpi_pst_domain_id,
346                         ACPI_PSD_COORD_SWANY, 1);
347                 dom->pd_flags |= ACPI_PSTDOM_FLAG_STUB;
348
349                 ++acpi_pst_domain_id;
350         }
351
352         /* Make sure that adding us will not overflow our domain */
353         i = 0;
354         LIST_FOREACH(pst, &dom->pd_pstlist, pst_link)
355                 ++i;
356         if (i == dom->pd_nproc) {
357                 device_printf(dev, "Domain%u already contains %d P-States, "
358                               "invalid _PSD package\n",
359                               dom->pd_dom, dom->pd_nproc);
360 #if 0
361                 /*
362                  * Some stupid BIOSes will set wrong "# of processors",
363                  * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
364                  */
365                 return ENXIO;
366 #else
367                 dom->pd_nproc++;
368 #endif
369         }
370         KKASSERT(i < dom->pd_nproc);
371
372         /*
373          * Get control/status registers from _PCT
374          */
375         buf.Pointer = NULL;
376         buf.Length = ACPI_ALLOCATE_BUFFER;
377         status = AcpiEvaluateObject(sc->pst_handle, "_PCT", NULL, &buf);
378         if (ACPI_FAILURE(status)) {
379                 device_printf(dev, "Can't get _PCT package - %s\n",
380                               AcpiFormatException(status));
381                 return ENXIO;
382         }
383
384         obj = (ACPI_OBJECT *)buf.Pointer;
385         if (!ACPI_PKG_VALID_EQ(obj, 2)) {
386                 device_printf(dev, "Invalid _PCT package\n");
387                 AcpiOsFree(obj);
388                 return ENXIO;
389         }
390
391         /* Save and try allocating control register */
392         error = acpi_pst_alloc_resource(dev, obj, 0, &sc->pst_creg);
393         if (error) {
394                 AcpiOsFree(obj);
395                 return error;
396         }
397         if (bootverbose) {
398                 device_printf(dev, "control reg %d %jx\n",
399                               sc->pst_creg.pr_gas.SpaceId,
400                               (uintmax_t)sc->pst_creg.pr_gas.Address);
401         }
402
403         /* Save and try allocating status register */
404         error = acpi_pst_alloc_resource(dev, obj, 1, &sc->pst_sreg);
405         if (error) {
406                 AcpiOsFree(obj);
407                 return error;
408         }
409         if (bootverbose) {
410                 device_printf(dev, "status reg %d %jx\n",
411                               sc->pst_sreg.pr_gas.SpaceId,
412                               (uintmax_t)sc->pst_sreg.pr_gas.Address);
413         }
414
415         /* Free _PCT */
416         AcpiOsFree(obj);
417
418         /*
419          * Create P-State table according to _PSS
420          */
421         buf.Pointer = NULL;
422         buf.Length = ACPI_ALLOCATE_BUFFER;
423         status = AcpiEvaluateObject(sc->pst_handle, "_PSS", NULL, &buf);
424         if (ACPI_FAILURE(status)) {
425                 device_printf(dev, "Can't get _PSS package - %s\n",
426                               AcpiFormatException(status));
427                 return ENXIO;
428         }
429
430         obj = (ACPI_OBJECT *)buf.Pointer;
431         if (!ACPI_PKG_VALID(obj, 1)) {
432                 device_printf(dev, "Invalid _PSS package\n");
433                 AcpiOsFree(obj);
434                 return ENXIO;
435         }
436
437         /* Don't create too many P-States */
438         npstate = obj->Package.Count;
439         if (npstate > ACPI_NPSTATE_MAX) {
440                 device_printf(dev, "Too many P-States, %d->%d\n",
441                               npstate, ACPI_NPSTATE_MAX);
442                 npstate = ACPI_NPSTATE_MAX;
443         }
444
445         /*
446          * If we have already created P-State table,
447          * we must make sure that number of entries
448          * is consistent.
449          */
450         if (acpi_pstates != NULL && acpi_npstates != npstate) {
451                 device_printf(dev, "Inconsistent # of P-States "
452                               "cross Processor objects\n");
453                 AcpiOsFree(obj);
454                 return ENXIO;
455         }
456
457         /*
458          * Create a temporary P-State table
459          */
460         pstate = kmalloc(sizeof(*pstate) * npstate, M_TEMP, M_WAITOK);
461         for (i = 0, p = pstate; i < npstate; ++i, ++p) {
462                 ACPI_OBJECT *pkg;
463                 uint32_t *ptr[ACPI_PSS_PX_NENTRY] = {
464                         &p->st_freq, &p->st_power, &p->st_xsit_lat,
465                         &p->st_bm_lat, &p->st_cval, &p->st_sval
466                 };
467                 int j;
468
469                 pkg = &obj->Package.Elements[i];
470                 if (!ACPI_PKG_VALID(pkg, ACPI_PSS_PX_NENTRY)) {
471                         device_printf(dev, "Invalud _PSS P%d\n", i);
472                         AcpiOsFree(obj);
473                         kfree(pstate, M_TEMP);
474                         return ENXIO;
475                 }
476                 for (j = 0; j < ACPI_PSS_PX_NENTRY; ++j) {
477                         if (acpi_PkgInt32(pkg, j, ptr[j]) != 0) {
478                                 device_printf(dev, "Can't extract "
479                                               "_PSS P%d %dth entry\n", i, j);
480                                 AcpiOsFree(obj);
481                                 kfree(pstate, M_TEMP);
482                                 return ENXIO;
483                         }
484                 }
485         }
486
487         /* Free _PSS */
488         AcpiOsFree(obj);
489
490         if (acpi_pstates == NULL) {
491                 /*
492                  * If no P-State table is created yet,
493                  * save the temporary one we just created.
494                  */
495                 acpi_pstates = pstate;
496                 acpi_npstates = npstate;
497                 pstate = NULL;
498
499                 if (bootverbose) {
500                         for (i = 0; i < acpi_npstates; ++i) {
501                                 device_printf(dev,
502                                 "freq %u, pwr %u, xlat %u, blat %u, "
503                                 "cv %08x, sv %08x\n",
504                                 acpi_pstates[i].st_freq,
505                                 acpi_pstates[i].st_power,
506                                 acpi_pstates[i].st_xsit_lat,
507                                 acpi_pstates[i].st_bm_lat,
508                                 acpi_pstates[i].st_cval,
509                                 acpi_pstates[i].st_sval);
510                         }
511                 }
512         } else {
513                 /*
514                  * Make sure that P-State tables are same
515                  * for all processors.
516                  */
517                 if (memcmp(pstate, acpi_pstates,
518                            sizeof(*pstate) * npstate) != 0) {
519                         device_printf(dev, "Inconsistent _PSS "
520                                       "cross Processor objects\n");
521                         kfree(pstate, M_TEMP);
522                         return ENXIO;
523                 }
524                 kfree(pstate, M_TEMP);
525         }
526
527         /* By default, we start from P-State table's first entry */
528         sc->pst_sstart = 0;
529
530         /*
531          * Adjust the usable first entry of P-State table,
532          * if there is _PPC object.
533          */
534         buf.Pointer = NULL;
535         buf.Length = ACPI_ALLOCATE_BUFFER;
536         status = AcpiEvaluateObject(sc->pst_handle, "_PPC", NULL, &buf);
537         if (!ACPI_FAILURE(status)) {
538                 obj = (ACPI_OBJECT *)buf.Pointer;
539                 if (obj->Type == ACPI_TYPE_INTEGER) {
540                         if (obj->Integer.Value >= acpi_npstates) {
541                                 device_printf(dev, "Invalid _PPC value\n");
542                                 AcpiOsFree(obj);
543                                 return ENXIO;
544                         }
545                         sc->pst_sstart = obj->Integer.Value;
546                         if (bootverbose)
547                                 device_printf(dev, "_PPC %d\n", sc->pst_sstart);
548
549                         /* TODO: Install notifiy handler */
550                 } else {
551                         device_printf(dev, "Invalid _PPC object\n");
552                         AcpiOsFree(obj);
553                         return ENXIO;
554                 }
555
556                 /* Free _PPC */
557                 AcpiOsFree(obj);
558         }
559
560         sc->pst_state = sc->pst_sstart;
561
562         /* Link us with the domain */
563         sc->pst_domain = dom;
564         LIST_INSERT_HEAD(&dom->pd_pstlist, sc, pst_link);
565
566         if (device_get_unit(dev) == 0)
567                 AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_pst_postattach, NULL);
568
569         return 0;
570 }
571
572 static struct acpi_pst_domain *
573 acpi_pst_domain_create_pkg(device_t dev, ACPI_OBJECT *obj)
574 {
575         struct acpi_pst_domain *dom;
576         uint32_t val, domain, coord, nproc;
577
578         if (!ACPI_PKG_VALID_EQ(obj, 5)) {
579                 device_printf(dev, "Invalid _PSD package\n");
580                 return NULL;
581         }
582
583         /* NumberOfEntries */
584         if (acpi_PkgInt32(obj, 0, &val) != 0 || val != 5) {
585                 device_printf(dev, "Invalid _PSD NumberOfEntries\n");
586                 return NULL;
587         }
588
589         /* Revision */
590         if (acpi_PkgInt32(obj, 1, &val) != 0 || val != 0) {
591                 device_printf(dev, "Invalid _PSD Revision\n");
592                 return NULL;
593         }
594
595         if (acpi_PkgInt32(obj, 2, &domain) != 0 ||
596             acpi_PkgInt32(obj, 3, &coord) != 0 ||
597             acpi_PkgInt32(obj, 4, &nproc) != 0) {
598                 device_printf(dev, "Can't extract _PSD package\n");
599                 return NULL;
600         }
601
602         if (!ACPI_PSD_COORD_VALID(coord)) {
603                 device_printf(dev, "Invalid _PSD CoordType (%#x)\n", coord);
604                 return NULL;
605         }
606
607         if (nproc > MAXCPU) {
608                 /*
609                  * If NumProcessors is greater than MAXCPU
610                  * and domain's coordination is SWALL, then
611                  * we will never be able to start all CPUs
612                  * within this domain, and power state
613                  * transition will never be completed, so we
614                  * just bail out here.
615                  */
616                 if (coord == ACPI_PSD_COORD_SWALL) {
617                         device_printf(dev, "Unsupported _PSD NumProcessors "
618                                       "(%d)\n", nproc);
619                         return NULL;
620                 }
621         } else if (nproc == 0) {
622                 device_printf(dev, "_PSD NumProcessors are zero\n");
623                 return NULL;
624         }
625
626         dom = acpi_pst_domain_find(domain);
627         if (dom != NULL) {
628                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_INT) {
629                         device_printf(dev, "Mixed Integer _PSD and "
630                             "Package _PSD\n");
631                         return NULL;
632                 }
633                 if (dom->pd_coord != coord) {
634                         device_printf(dev, "Inconsistent _PSD coord "
635                             "information cross Processor objects\n");
636                         return NULL;
637                 }
638                 if (dom->pd_nproc != nproc) {
639                         device_printf(dev, "Inconsistent _PSD nproc "
640                             "information cross Processor objects\n");
641                         /*
642                          * Some stupid BIOSes will set wrong "# of processors",
643                          * e.g. 1 for CPU w/ hyperthreading; Be lenient here.
644                          */
645                 }
646                 return dom;
647         }
648
649         dom = acpi_pst_domain_alloc(domain, coord, nproc);
650         if (bootverbose) {
651                 device_printf(dev, "create pkg domain%u, coord %#x\n",
652                     dom->pd_dom, dom->pd_coord);
653         }
654
655         return dom;
656 }
657
658 static struct acpi_pst_domain *
659 acpi_pst_domain_create_int(device_t dev, uint32_t domain)
660 {
661         struct acpi_pst_domain *dom;
662
663         dom = acpi_pst_domain_find(domain);
664         if (dom != NULL) {
665                 if ((dom->pd_flags & ACPI_PSTDOM_FLAG_INT) == 0) {
666                         device_printf(dev, "Mixed Package _PSD and "
667                             "Integer _PSD\n");
668                         return NULL;
669                 }
670                 KKASSERT(dom->pd_coord == ACPI_PSD_COORD_SWALL);
671
672                 dom->pd_nproc++;
673                 return dom;
674         }
675
676         dom = acpi_pst_domain_alloc(domain, ACPI_PSD_COORD_SWALL, 1);
677         dom->pd_flags |= ACPI_PSTDOM_FLAG_INT;
678
679         if (bootverbose)
680                 device_printf(dev, "create int domain%u\n", dom->pd_dom);
681
682         return dom;
683 }
684
685 static struct acpi_pst_domain *
686 acpi_pst_domain_find(uint32_t domain)
687 {
688         struct acpi_pst_domain *dom;
689
690         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
691                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_STUB)
692                         continue;
693                 if (dom->pd_dom == domain)
694                         return dom;
695         }
696         return NULL;
697 }
698
699 static struct acpi_pst_domain *
700 acpi_pst_domain_alloc(uint32_t domain, uint32_t coord, uint32_t nproc)
701 {
702         struct acpi_pst_domain *dom;
703
704         dom = kmalloc(sizeof(*dom), M_DEVBUF, M_WAITOK | M_ZERO);
705         dom->pd_dom = domain;
706         dom->pd_coord = coord;
707         dom->pd_nproc = nproc;
708         dom->pd_state = 0; /* XXX */
709         dom->pd_sstart = 0; /* XXX */
710         LIST_INIT(&dom->pd_pstlist);
711
712         LIST_INSERT_HEAD(&acpi_pst_domains, dom, pd_link);
713
714         return dom;
715 }
716
717 static int
718 acpi_pst_domain_set_pstate(struct acpi_pst_domain *dom, int i)
719 {
720         const struct acpi_pstate *pstate;
721         struct acpi_pst_softc *sc;
722         int done, error;
723
724         KKASSERT(i >= 0 && i < acpi_npstates);
725         pstate = &acpi_pstates[i];
726
727         done = 0;
728         LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
729                 if (!done) {
730                         error = acpi_pst_set_pstate(sc, pstate);
731                         if (error) {
732                                 device_printf(sc->pst_dev, "can't set "
733                                               "freq %d\n", pstate->st_freq);
734                                 /* XXX error cleanup? */
735                         }
736                         if (dom->pd_coord == ACPI_PSD_COORD_SWANY)
737                                 done = 1;
738                 }
739                 sc->pst_state = i;
740         }
741         dom->pd_state = i;
742
743         return 0;
744 }
745
746 static int
747 acpi_pst_global_set_pstate(int i)
748 {
749         struct acpi_pst_domain *dom;
750
751         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
752                 /* Skip dead domain */
753                 if (dom->pd_flags & ACPI_PSTDOM_FLAG_DEAD)
754                         continue;
755                 acpi_pst_domain_set_pstate(dom, i);
756         }
757         acpi_pst_global_state = i;
758
759         return 0;
760 }
761
762 static void
763 acpi_pst_postattach(void *arg __unused)
764 {
765         struct acpi_pst_domain *dom;
766         struct acpi_cpux_softc *cpux;
767         device_t *devices;
768         int i, ndevices, error, has_domain, sstate;
769
770         devices = NULL;
771         ndevices = 0;
772         error = devclass_get_devices(acpi_pst_devclass, &devices, &ndevices);
773         if (error)
774                 return;
775
776         if (ndevices == 0)
777                 return;
778
779         cpux = NULL;
780         for (i = 0; i < ndevices; ++i) {
781                 cpux = device_get_softc(device_get_parent(devices[i]));
782                 if (cpux->glob_sysctl_tree != NULL)
783                         break;
784         }
785         kfree(devices, M_TEMP);
786         KKASSERT(cpux != NULL);
787
788         if (acpi_pst_md == NULL)
789                 kprintf("ACPI: no P-State CPU driver\n");
790
791         sstate = 0x7fffffff;
792         has_domain = 0;
793         LIST_FOREACH(dom, &acpi_pst_domains, pd_link) {
794                 struct acpi_pst_softc *sc;
795                 char buf[32];
796
797                 /*
798                  * Make sure that all processors belonging to this
799                  * domain are located.
800                  */
801                 i = 0;
802                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link)
803                         ++i;
804                 if (i != dom->pd_nproc) {
805                         KKASSERT(i < dom->pd_nproc);
806
807                         kprintf("ACPI: domain%u misses processors, "
808                                 "should be %d, got %d\n", dom->pd_dom,
809                                 dom->pd_nproc, i);
810                         if (dom->pd_coord == ACPI_PSD_COORD_SWALL) {
811                                 /*
812                                  * If this domain's coordination is
813                                  * SWALL and we don't see all of the
814                                  * member CPUs of this domain, then
815                                  * the P-State transition will never
816                                  * be completed, so just leave this
817                                  * domain out.
818                                  */
819                                 dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
820                                 continue;
821                         }
822                         dom->pd_nproc = i;
823                 }
824
825                 /*
826                  * Validate P-State configurations for this domain
827                  */
828                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
829                         error = acpi_pst_check_csr(sc);
830                         if (error)
831                                 break;
832
833                         error = acpi_pst_check_pstates(sc);
834                         if (error)
835                                 break;
836                 }
837                 if (sc != NULL) {
838                         kprintf("ACPI: domain%u P-State configuration "
839                                 "check failed\n", dom->pd_dom);
840                         dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
841                         continue;
842                 }
843
844                 /*
845                  * Do necssary P-State initialization
846                  */
847                 LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
848                         error = acpi_pst_init(sc);
849                         if (error)
850                                 break;
851                 }
852                 if (sc != NULL) {
853                         kprintf("ACPI: domain%u P-State initialization "
854                                 "check failed\n", dom->pd_dom);
855                         dom->pd_flags |= ACPI_PSTDOM_FLAG_DEAD;
856                         continue;
857                 }
858
859                 has_domain = 1;
860
861                 ksnprintf(buf, sizeof(buf), "px_dom%u", dom->pd_dom);
862
863                 sysctl_ctx_init(&dom->pd_sysctl_ctx);
864                 dom->pd_sysctl_tree =
865                 SYSCTL_ADD_NODE(&dom->pd_sysctl_ctx,
866                         SYSCTL_CHILDREN(cpux->glob_sysctl_tree),
867                         OID_AUTO, buf, CTLFLAG_RD, 0,
868                         "P-State domain");
869                 if (dom->pd_sysctl_tree == NULL) {
870                         kprintf("ACPI: Can't create sysctl tree for domain%u",
871                                 dom->pd_dom);
872                         continue;
873                 }
874
875                 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
876                                 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
877                                 OID_AUTO, "available",
878                                 CTLTYPE_STRING | CTLFLAG_RD,
879                                 dom, 0, acpi_pst_sysctl_freqs, "A",
880                                 "available frequencies");
881
882                 SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
883                                 SYSCTL_CHILDREN(dom->pd_sysctl_tree),
884                                 OID_AUTO, "members",
885                                 CTLTYPE_STRING | CTLFLAG_RD,
886                                 dom, 0, acpi_pst_sysctl_members, "A",
887                                 "member cpus");
888
889                 if (acpi_pst_md != NULL &&
890                     acpi_pst_md->pmd_set_pstate != NULL) {
891                         SYSCTL_ADD_PROC(&dom->pd_sysctl_ctx,
892                                         SYSCTL_CHILDREN(dom->pd_sysctl_tree),
893                                         OID_AUTO, "select",
894                                         CTLTYPE_UINT | CTLFLAG_RW,
895                                         dom, 0, acpi_pst_sysctl_select,
896                                         "IU", "select freq");
897                 }
898
899                 if (dom->pd_state < sstate)
900                         sstate = dom->pd_state;
901         }
902
903         if (has_domain && acpi_pst_md != NULL &&
904             acpi_pst_md->pmd_set_pstate != NULL) {
905                 SYSCTL_ADD_PROC(&cpux->glob_sysctl_ctx,
906                                 SYSCTL_CHILDREN(cpux->glob_sysctl_tree),
907                                 OID_AUTO, "px_global",
908                                 CTLTYPE_UINT | CTLFLAG_RW,
909                                 NULL, 0, acpi_pst_sysctl_global,
910                                 "IU", "select freq for all domains");
911
912                 acpi_pst_global_set_pstate(sstate);
913         }
914 }
915
916 static int
917 acpi_pst_sysctl_freqs(SYSCTL_HANDLER_ARGS)
918 {
919         struct acpi_pst_domain *dom = arg1;
920         int i, error;
921
922         error = 0;
923         for (i = 0; i < acpi_npstates; ++i) {
924                 if (error == 0 && i)
925                         error = SYSCTL_OUT(req, " ", 1);
926                 if (error == 0) {
927                         const char *pat;
928                         char buf[32];
929
930                         if (i < dom->pd_sstart)
931                                 pat = "(%u)";
932                         else
933                                 pat = "%u";
934
935                         ksnprintf(buf, sizeof(buf), pat,
936                                   acpi_pstates[i].st_freq);
937                         error = SYSCTL_OUT(req, buf, strlen(buf));
938                 }
939         }
940         return error;
941 }
942
943 static int
944 acpi_pst_sysctl_members(SYSCTL_HANDLER_ARGS)
945 {
946         struct acpi_pst_domain *dom = arg1;
947         struct acpi_pst_softc *sc;
948         int loop, error;
949
950         loop = error = 0;
951         LIST_FOREACH(sc, &dom->pd_pstlist, pst_link) {
952                 char buf[32];
953
954                 if (error == 0 && loop)
955                         error = SYSCTL_OUT(req, " ", 1);
956                 if (error == 0) {
957                         ksnprintf(buf, sizeof(buf), "cpu%d", sc->pst_cpuid);
958                         error = SYSCTL_OUT(req, buf, strlen(buf));
959                 }
960
961                 if (error == 0 && acpi_pst_md && acpi_pst_md->pmd_get_pstate) {
962                         const struct acpi_pstate *pstate;
963                         const char *str;
964
965                         pstate = acpi_pst_get_pstate(sc);
966                         if (pstate == NULL) {
967                                 str = "(*)";
968                         } else {
969                                 ksnprintf(buf, sizeof(buf), "(%d)",
970                                           pstate->st_freq);
971                                 str = buf;
972                         }
973                         error = SYSCTL_OUT(req, str, strlen(str));
974                 }
975                 ++loop;
976         }
977         return error;
978 }
979
980 static int
981 acpi_pst_sysctl_select(SYSCTL_HANDLER_ARGS)
982 {
983         struct acpi_pst_domain *dom = arg1;
984         int error, i, freq;
985
986         KKASSERT(dom->pd_state >= 0 && dom->pd_state < acpi_npstates);
987
988         freq = acpi_pstates[dom->pd_state].st_freq;
989
990         error = sysctl_handle_int(oidp, &freq, 0, req);
991         if (error || req->newptr == NULL)
992                 return error;
993
994         i = acpi_pst_freq2index(freq);
995         if (i < 0)
996                 return EINVAL;
997
998         acpi_pst_domain_set_pstate(dom, i);
999         return 0;
1000 }
1001
1002 static int
1003 acpi_pst_sysctl_global(SYSCTL_HANDLER_ARGS)
1004 {
1005         int error, i, freq;
1006
1007         KKASSERT(acpi_pst_global_state >= 0 &&
1008                  acpi_pst_global_state < acpi_npstates);
1009
1010         freq = acpi_pstates[acpi_pst_global_state].st_freq;
1011
1012         error = sysctl_handle_int(oidp, &freq, 0, req);
1013         if (error || req->newptr == NULL)
1014                 return error;
1015
1016         i = acpi_pst_freq2index(freq);
1017         if (i < 0)
1018                 return EINVAL;
1019
1020         acpi_pst_global_set_pstate(i);
1021
1022         return 0;
1023 }
1024
1025 static void
1026 acpi_pst_check_csr_handler(netmsg_t msg)
1027 {
1028         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1029         int error;
1030
1031         error = acpi_pst_md->pmd_check_csr(rmsg->ctrl, rmsg->status);
1032         lwkt_replymsg(&rmsg->base.lmsg, error);
1033 }
1034
1035 static int
1036 acpi_pst_check_csr(struct acpi_pst_softc *sc)
1037 {
1038         struct netmsg_acpi_pst msg;
1039
1040         if (acpi_pst_md == NULL)
1041                 return 0;
1042
1043         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1044                     MSGF_PRIORITY, acpi_pst_check_csr_handler);
1045         msg.ctrl = &sc->pst_creg;
1046         msg.status = &sc->pst_sreg;
1047
1048         return lwkt_domsg(netisr_portfn(sc->pst_cpuid), &msg.base.lmsg, 0);
1049 }
1050
1051 static void
1052 acpi_pst_check_pstates_handler(netmsg_t msg)
1053 {
1054         int error;
1055
1056         error = acpi_pst_md->pmd_check_pstates(acpi_pstates, acpi_npstates);
1057         lwkt_replymsg(&msg->lmsg, error);
1058 }
1059
1060 static int
1061 acpi_pst_check_pstates(struct acpi_pst_softc *sc)
1062 {
1063         struct netmsg_base msg;
1064
1065         if (acpi_pst_md == NULL)
1066                 return 0;
1067
1068         netmsg_init(&msg, NULL, &curthread->td_msgport,
1069                     MSGF_PRIORITY, acpi_pst_check_pstates_handler);
1070
1071         return lwkt_domsg(netisr_portfn(sc->pst_cpuid), &msg.lmsg, 0);
1072 }
1073
1074 static void
1075 acpi_pst_init_handler(netmsg_t msg)
1076 {
1077         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1078         int error;
1079
1080         error = acpi_pst_md->pmd_init(rmsg->ctrl, rmsg->status);
1081         lwkt_replymsg(&rmsg->base.lmsg, error);
1082 }
1083
1084 static int
1085 acpi_pst_init(struct acpi_pst_softc *sc)
1086 {
1087         struct netmsg_acpi_pst msg;
1088
1089         if (acpi_pst_md == NULL)
1090                 return 0;
1091
1092         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1093                     MSGF_PRIORITY, acpi_pst_init_handler);
1094         msg.ctrl = &sc->pst_creg;
1095         msg.status = &sc->pst_sreg;
1096
1097         return lwkt_domsg(netisr_portfn(sc->pst_cpuid), &msg.base.lmsg, 0);
1098 }
1099
1100 static void
1101 acpi_pst_set_pstate_handler(netmsg_t msg)
1102 {
1103         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1104         int error;
1105
1106         error = acpi_pst_md->pmd_set_pstate(rmsg->ctrl, rmsg->status,
1107                                             rmsg->base.lmsg.u.ms_resultp);
1108         lwkt_replymsg(&rmsg->base.lmsg, error);
1109 }
1110
1111 static int
1112 acpi_pst_set_pstate(struct acpi_pst_softc *sc, const struct acpi_pstate *pstate)
1113 {
1114         struct netmsg_acpi_pst msg;
1115
1116         KKASSERT(acpi_pst_md != NULL);
1117
1118         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1119                     MSGF_PRIORITY, acpi_pst_set_pstate_handler);
1120         msg.base.lmsg.u.ms_resultp = __DECONST(void *, pstate);
1121         msg.ctrl = &sc->pst_creg;
1122         msg.status = &sc->pst_sreg;
1123
1124         return lwkt_domsg(netisr_portfn(sc->pst_cpuid), &msg.base.lmsg, 0);
1125 }
1126
1127 static void
1128 acpi_pst_get_pstate_handler(netmsg_t msg)
1129 {
1130         struct netmsg_acpi_pst *rmsg = (struct netmsg_acpi_pst *)msg;
1131         const struct acpi_pstate *pstate;
1132
1133         pstate = acpi_pst_md->pmd_get_pstate(rmsg->status, acpi_pstates,
1134                                              acpi_npstates);
1135         rmsg->base.lmsg.u.ms_resultp = __DECONST(void *, pstate);
1136         lwkt_replymsg(&rmsg->base.lmsg, 0);
1137 }
1138
1139 static const struct acpi_pstate *
1140 acpi_pst_get_pstate(struct acpi_pst_softc *sc)
1141 {
1142         struct netmsg_acpi_pst msg;
1143
1144         if (acpi_pst_md == NULL)
1145                 return 0;
1146
1147         netmsg_init(&msg.base, NULL, &curthread->td_msgport,
1148                     MSGF_PRIORITY, acpi_pst_get_pstate_handler);
1149         msg.status = &sc->pst_sreg;
1150
1151         lwkt_domsg(netisr_portfn(sc->pst_cpuid), &msg.base.lmsg, 0);
1152         return msg.base.lmsg.u.ms_resultp;
1153 }
1154
1155 static int
1156 acpi_pst_alloc_resource(device_t dev, ACPI_OBJECT *obj, int idx,
1157                         struct acpi_pst_res *res)
1158 {
1159         struct acpi_pst_softc *sc = device_get_softc(dev);
1160         int error, type;
1161
1162         /* Save GAS */
1163         error = acpi_PkgRawGas(obj, idx, &res->pr_gas);
1164         if (error)
1165                 return error;
1166
1167         /* Allocate resource, if possible */
1168         res->pr_rid = sc->pst_parent->cpux_next_rid;
1169         acpi_bus_alloc_gas(dev, &type, &res->pr_rid, &res->pr_gas, &res->pr_res, 0);
1170         if (res->pr_res != NULL) {
1171                 sc->pst_parent->cpux_next_rid++;
1172                 res->pr_bt = rman_get_bustag(res->pr_res);
1173                 res->pr_bh = rman_get_bushandle(res->pr_res);
1174         } else {
1175                 res->pr_rid = 0;
1176         }
1177         return 0;
1178 }