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