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