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