xref: /dragonfly/sys/dev/acpica/acpi_cpu_pstate.c (revision 3170ffd7)
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/netisr2.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 	DEVMETHOD_END
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_cpuport(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_cpuport(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_cpuport(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_cpuport(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_cpuport(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 }
1179