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