1 /* $OpenBSD: acpicpu.c,v 1.53 2009/02/24 13:20:02 deraadt Exp $ */ 2 /* 3 * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/proc.h> 20 #include <sys/signalvar.h> 21 #include <sys/sysctl.h> 22 #include <sys/systm.h> 23 #include <sys/device.h> 24 #include <sys/malloc.h> 25 #include <sys/queue.h> 26 27 #include <machine/bus.h> 28 #include <machine/cpu.h> 29 #include <machine/cpufunc.h> 30 #include <machine/specialreg.h> 31 32 #include <dev/acpi/acpireg.h> 33 #include <dev/acpi/acpivar.h> 34 #include <dev/acpi/acpidev.h> 35 #include <dev/acpi/amltypes.h> 36 #include <dev/acpi/dsdt.h> 37 38 #include <sys/sensors.h> 39 40 int acpicpu_match(struct device *, void *, void *); 41 void acpicpu_attach(struct device *, struct device *, void *); 42 int acpicpu_notify(struct aml_node *, int, void *); 43 void acpicpu_setperf(int); 44 45 #define ACPI_STATE_C0 0x00 46 #define ACPI_STATE_C1 0x01 47 #define ACPI_STATE_C2 0x02 48 #define ACPI_STATE_C3 0x03 49 50 #define FLAGS_NO_C2 0x01 51 #define FLAGS_NO_C3 0x02 52 #define FLAGS_BMCHECK 0x04 53 #define FLAGS_NOTHROTTLE 0x08 54 #define FLAGS_NOPSS 0x10 55 #define FLAGS_NOPCT 0x20 56 57 #define CPU_THT_EN (1L << 4) 58 #define CPU_MAXSTATE(sc) (1L << (sc)->sc_duty_wid) 59 #define CPU_STATE(sc,pct) ((pct * CPU_MAXSTATE(sc) / 100) << (sc)->sc_duty_off) 60 #define CPU_STATEMASK(sc) ((CPU_MAXSTATE(sc) - 1) << (sc)->sc_duty_off) 61 62 #define ACPI_MAX_C2_LATENCY 100 63 #define ACPI_MAX_C3_LATENCY 1000 64 65 /* Make sure throttling bits are valid,a=addr,o=offset,w=width */ 66 #define valid_throttle(o,w,a) (a && w && (o+w)<=31 && (o>4 || (o+w)<=4)) 67 68 struct acpi_cstate 69 { 70 int type; 71 int latency; 72 int power; 73 int address; 74 75 SLIST_ENTRY(acpi_cstate) link; 76 }; 77 78 struct acpicpu_softc { 79 struct device sc_dev; 80 int sc_cpu; 81 82 int sc_duty_wid; 83 int sc_duty_off; 84 int sc_pblk_addr; 85 int sc_pblk_len; 86 int sc_flags; 87 88 SLIST_HEAD(,acpi_cstate) sc_cstates; 89 90 bus_space_tag_t sc_iot; 91 bus_space_handle_t sc_ioh; 92 93 struct acpi_softc *sc_acpi; 94 struct aml_node *sc_devnode; 95 96 int sc_pss_len; 97 int sc_ppc; 98 int sc_level; 99 struct acpicpu_pss *sc_pss; 100 101 struct acpicpu_pct sc_pct; 102 /* save compensation for pct access for lying bios' */ 103 u_int32_t sc_pct_stat_as; 104 u_int32_t sc_pct_ctrl_as; 105 u_int32_t sc_pct_stat_len; 106 u_int32_t sc_pct_ctrl_len; 107 /* 108 * XXX: _PPC Change listener 109 * PPC changes can occur when for example a machine is disconnected 110 * from AC power and can no loger support the highest frequency or 111 * voltage when driven from the battery. 112 * Should probably be reimplemented as a list for now we assume only 113 * one listener 114 */ 115 void (*sc_notify)(struct acpicpu_pss *, int); 116 }; 117 118 void acpicpu_add_cstatepkg(struct aml_value *, void *); 119 int acpicpu_getppc(struct acpicpu_softc *); 120 int acpicpu_getpct(struct acpicpu_softc *); 121 int acpicpu_getpss(struct acpicpu_softc *); 122 struct acpi_cstate *acpicpu_add_cstate(struct acpicpu_softc *, int, int, int, 123 int); 124 #if 0 125 void acpicpu_set_throttle(struct acpicpu_softc *, int); 126 struct acpi_cstate *acpicpu_find_cstate(struct acpicpu_softc *, int); 127 #endif 128 129 struct cfattach acpicpu_ca = { 130 sizeof(struct acpicpu_softc), acpicpu_match, acpicpu_attach 131 }; 132 133 struct cfdriver acpicpu_cd = { 134 NULL, "acpicpu", DV_DULL 135 }; 136 137 extern int setperf_prio; 138 139 struct acpicpu_softc *acpicpu_sc[MAXCPUS]; 140 141 #if 0 142 void 143 acpicpu_set_throttle(struct acpicpu_softc *sc, int level) 144 { 145 uint32_t pbval; 146 147 if (sc->sc_flags & FLAGS_NOTHROTTLE) 148 return; 149 150 /* Disable throttling control */ 151 pbval = inl(sc->sc_pblk_addr); 152 outl(sc->sc_pblk_addr, pbval & ~CPU_THT_EN); 153 if (level < 100) { 154 pbval &= ~CPU_STATEMASK(sc); 155 pbval |= CPU_STATE(sc, level); 156 outl(sc->sc_pblk_addr, pbval & ~CPU_THT_EN); 157 outl(sc->sc_pblk_addr, pbval | CPU_THT_EN); 158 } 159 } 160 161 struct acpi_cstate * 162 acpicpu_find_cstate(struct acpicpu_softc *sc, int type) 163 { 164 struct acpi_cstate *cx; 165 166 SLIST_FOREACH(cx, &sc->sc_cstates, link) 167 if (cx->type == type) 168 return cx; 169 return (NULL); 170 } 171 #endif 172 173 struct acpi_cstate * 174 acpicpu_add_cstate(struct acpicpu_softc *sc, int type, int latency, int power, 175 int address) 176 { 177 struct acpi_cstate *cx; 178 179 dnprintf(10," C%d: latency:.%4x power:%.4x addr:%.8x\n", 180 type, latency, power, address); 181 182 switch (type) { 183 case ACPI_STATE_C2: 184 if (latency > ACPI_MAX_C2_LATENCY || !address || 185 (sc->sc_flags & FLAGS_NO_C2)) 186 goto bad; 187 break; 188 case ACPI_STATE_C3: 189 if (latency > ACPI_MAX_C3_LATENCY || !address || 190 (sc->sc_flags & FLAGS_NO_C3)) 191 goto bad; 192 break; 193 } 194 195 cx = malloc(sizeof(*cx), M_DEVBUF, M_WAITOK | M_ZERO); 196 197 cx->type = type; 198 cx->power = power; 199 cx->latency = latency; 200 cx->address = address; 201 202 SLIST_INSERT_HEAD(&sc->sc_cstates, cx, link); 203 204 return (cx); 205 bad: 206 dprintf("acpicpu%d: C%d not supported", sc->sc_cpu, type); 207 return (NULL); 208 } 209 210 /* Found a _CST object, add new cstate for each entry */ 211 void 212 acpicpu_add_cstatepkg(struct aml_value *val, void *arg) 213 { 214 struct acpicpu_softc *sc = arg; 215 216 #if defined(ACPI_DEBUG) && !defined(SMALL_KERNEL) 217 aml_showvalue(val, 0); 218 #endif 219 if (val->type != AML_OBJTYPE_PACKAGE || val->length != 4) 220 return; 221 222 acpicpu_add_cstate(sc, val->v_package[1]->v_integer, 223 val->v_package[2]->v_integer, 224 val->v_package[3]->v_integer, -1); 225 } 226 227 228 int 229 acpicpu_match(struct device *parent, void *match, void *aux) 230 { 231 struct acpi_attach_args *aa = aux; 232 struct cfdata *cf = match; 233 234 /* sanity */ 235 if (aa->aaa_name == NULL || 236 strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 || 237 aa->aaa_table != NULL) 238 return (0); 239 240 return (1); 241 } 242 243 void 244 acpicpu_attach(struct device *parent, struct device *self, void *aux) 245 { 246 struct acpicpu_softc *sc = (struct acpicpu_softc *)self; 247 struct acpi_attach_args *aa = aux; 248 struct aml_value res; 249 int i; 250 struct acpi_cstate *cx; 251 u_int32_t status = 0; 252 253 sc->sc_acpi = (struct acpi_softc *)parent; 254 sc->sc_devnode = aa->aaa_node; 255 acpicpu_sc[sc->sc_dev.dv_unit] = sc; 256 257 SLIST_INIT(&sc->sc_cstates); 258 259 sc->sc_pss = NULL; 260 261 if (aml_evalnode(sc->sc_acpi, sc->sc_devnode, 0, NULL, &res) == 0) { 262 if (res.type == AML_OBJTYPE_PROCESSOR) { 263 sc->sc_cpu = res.v_processor.proc_id; 264 sc->sc_pblk_addr = res.v_processor.proc_addr; 265 sc->sc_pblk_len = res.v_processor.proc_len; 266 } 267 aml_freevalue(&res); 268 } 269 sc->sc_duty_off = sc->sc_acpi->sc_fadt->duty_offset; 270 sc->sc_duty_wid = sc->sc_acpi->sc_fadt->duty_width; 271 if (!valid_throttle(sc->sc_duty_off, sc->sc_duty_wid, sc->sc_pblk_addr)) 272 sc->sc_flags |= FLAGS_NOTHROTTLE; 273 #ifdef ACPI_DEBUG 274 printf(": %s: ", sc->sc_devnode->name); 275 printf("\n: hdr:%x pblk:%x,%x duty:%x,%x pstate:%x (%d throttling states)\n", 276 sc->sc_acpi->sc_fadt->hdr_revision, 277 sc->sc_pblk_addr, sc->sc_pblk_len, 278 sc->sc_duty_off, sc->sc_duty_wid, 279 sc->sc_acpi->sc_fadt->pstate_cnt, 280 CPU_MAXSTATE(sc)); 281 #endif 282 283 /* Get C-States from _CST or FADT */ 284 if (!aml_evalname(sc->sc_acpi, sc->sc_devnode, "_CST", 0, NULL, &res)) { 285 aml_foreachpkg(&res, 1, acpicpu_add_cstatepkg, sc); 286 aml_freevalue(&res); 287 } 288 else { 289 /* Some systems don't export a full PBLK reduce functionality */ 290 if (sc->sc_pblk_len < 5) 291 sc->sc_flags |= FLAGS_NO_C2; 292 if (sc->sc_pblk_len < 6) 293 sc->sc_flags |= FLAGS_NO_C3; 294 acpicpu_add_cstate(sc, ACPI_STATE_C2, 295 sc->sc_acpi->sc_fadt->p_lvl2_lat, -1, 296 sc->sc_pblk_addr + 4); 297 acpicpu_add_cstate(sc, ACPI_STATE_C3, 298 sc->sc_acpi->sc_fadt->p_lvl3_lat, -1, 299 sc->sc_pblk_addr + 5); 300 } 301 if (acpicpu_getpss(sc)) { 302 sc->sc_flags |= FLAGS_NOPSS; 303 } else { 304 #ifdef ACPI_DEBUG 305 for (i = 0; i < sc->sc_pss_len; i++) { 306 dnprintf(20, "%d %d %d %d %d %d\n", 307 sc->sc_pss[i].pss_core_freq, 308 sc->sc_pss[i].pss_power, 309 sc->sc_pss[i].pss_trans_latency, 310 sc->sc_pss[i].pss_bus_latency, 311 sc->sc_pss[i].pss_ctrl, 312 sc->sc_pss[i].pss_status); 313 } 314 dnprintf(20, "\n"); 315 #endif 316 if (sc->sc_pss_len == 0) { 317 /* this should never happen */ 318 printf("%s: invalid _PSS length\n", DEVNAME(sc)); 319 sc->sc_flags |= FLAGS_NOPSS; 320 } 321 322 acpicpu_getppc(sc); 323 if (acpicpu_getpct(sc)) 324 sc->sc_flags |= FLAGS_NOPCT; 325 else { 326 327 /* Notify BIOS we are handing p-states */ 328 if (sc->sc_acpi->sc_fadt->pstate_cnt) 329 acpi_write_pmreg(sc->sc_acpi, ACPIREG_SMICMD, 0, 330 sc->sc_acpi->sc_fadt->pstate_cnt); 331 332 aml_register_notify(sc->sc_devnode, NULL, 333 acpicpu_notify, sc, ACPIDEV_NOPOLL); 334 335 acpi_gasio(sc->sc_acpi, ACPI_IOREAD, 336 sc->sc_pct.pct_status.grd_gas.address_space_id, 337 sc->sc_pct.pct_status.grd_gas.address, 338 sc->sc_pct_stat_as, sc->sc_pct_stat_as, &status); 339 sc->sc_level = (100 / sc->sc_pss_len) * 340 (sc->sc_pss_len - status); 341 dnprintf(20, "%s: cpu index %d, percentage %d\n", 342 DEVNAME(sc), status, sc->sc_level); 343 if (setperf_prio < 30) { 344 cpu_setperf = acpicpu_setperf; 345 setperf_prio = 30; 346 acpi_hasprocfvs = 1; 347 } 348 } 349 } 350 351 /* 352 * Nicely enumerate what power management capabilities 353 * ACPI CPU provides. 354 */ 355 if (!SLIST_EMPTY(&sc->sc_cstates)) { 356 printf(":"); 357 358 i = 0; 359 SLIST_FOREACH(cx, &sc->sc_cstates, link) { 360 if (i++) 361 printf(","); 362 switch (cx->type) { 363 case ACPI_STATE_C0: 364 printf(" C0"); 365 break; 366 case ACPI_STATE_C1: 367 printf(" C1"); 368 break; 369 case ACPI_STATE_C2: 370 printf(" C2"); 371 break; 372 case ACPI_STATE_C3: 373 printf(" C3"); 374 break; 375 } 376 } 377 } 378 379 if (!(sc->sc_flags & (FLAGS_NOPSS | FLAGS_NOPCT)) || 380 !(sc->sc_flags & FLAGS_NOPSS)) { 381 printf("%c ", SLIST_EMPTY(&sc->sc_cstates) ? ':' : ','); 382 383 /* 384 * If acpicpu is itself providing the capability to transition 385 * states, enumerate them in the fashion that est and powernow 386 * would. 387 */ 388 if (!(sc->sc_flags & (FLAGS_NOPSS | FLAGS_NOPCT))) { 389 printf("FVS, "); 390 for (i = 0; i < sc->sc_pss_len - 1; i++) 391 printf("%d, ", sc->sc_pss[i].pss_core_freq); 392 printf("%d MHz", sc->sc_pss[i].pss_core_freq); 393 } else 394 printf("PSS"); 395 } 396 397 printf("\n"); 398 } 399 400 int 401 acpicpu_getppc(struct acpicpu_softc *sc) 402 { 403 struct aml_value res; 404 405 sc->sc_ppc = 0; 406 407 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PPC", 0, NULL, &res)) { 408 dnprintf(10, "%s: no _PPC\n", DEVNAME(sc)); 409 return (1); 410 } 411 412 sc->sc_ppc = aml_val2int(&res); 413 dnprintf(10, "%s: _PPC: %d\n", DEVNAME(sc), sc->sc_ppc); 414 aml_freevalue(&res); 415 416 return (0); 417 } 418 419 int 420 acpicpu_getpct(struct acpicpu_softc *sc) 421 { 422 struct aml_value res; 423 int rv = 1; 424 425 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PCT", 0, NULL, &res)) { 426 dnprintf(20, "%s: no _PCT\n", DEVNAME(sc)); 427 return (1); 428 } 429 430 if (res.length != 2) { 431 dnprintf(20, "%s: %s: invalid _PCT length\n", DEVNAME(sc), 432 sc->sc_devnode->name); 433 return (1); 434 } 435 436 memcpy(&sc->sc_pct.pct_ctrl, res.v_package[0]->v_buffer, 437 sizeof sc->sc_pct.pct_ctrl); 438 if (sc->sc_pct.pct_ctrl.grd_gas.address_space_id == 439 GAS_FUNCTIONAL_FIXED) { 440 dnprintf(20, "CTRL GASIO is functional fixed hardware.\n"); 441 goto ffh; 442 } 443 444 memcpy(&sc->sc_pct.pct_status, res.v_package[1]->v_buffer, 445 sizeof sc->sc_pct.pct_status); 446 if (sc->sc_pct.pct_status.grd_gas.address_space_id == 447 GAS_FUNCTIONAL_FIXED) { 448 dnprintf(20, "CTRL GASIO is functional fixed hardware.\n"); 449 goto ffh; 450 } 451 452 dnprintf(10, "_PCT(ctrl) : %02x %04x %02x %02x %02x %02x %016x\n", 453 sc->sc_pct.pct_ctrl.grd_descriptor, 454 sc->sc_pct.pct_ctrl.grd_length, 455 sc->sc_pct.pct_ctrl.grd_gas.address_space_id, 456 sc->sc_pct.pct_ctrl.grd_gas.register_bit_width, 457 sc->sc_pct.pct_ctrl.grd_gas.register_bit_offset, 458 sc->sc_pct.pct_ctrl.grd_gas.access_size, 459 sc->sc_pct.pct_ctrl.grd_gas.address); 460 461 dnprintf(10, "_PCT(status): %02x %04x %02x %02x %02x %02x %016x\n", 462 sc->sc_pct.pct_status.grd_descriptor, 463 sc->sc_pct.pct_status.grd_length, 464 sc->sc_pct.pct_status.grd_gas.address_space_id, 465 sc->sc_pct.pct_status.grd_gas.register_bit_width, 466 sc->sc_pct.pct_status.grd_gas.register_bit_offset, 467 sc->sc_pct.pct_status.grd_gas.access_size, 468 sc->sc_pct.pct_status.grd_gas.address); 469 470 /* if not set assume single 32 bit access */ 471 sc->sc_pct_stat_as = sc->sc_pct.pct_status.grd_gas.register_bit_width 472 / 8; 473 if (sc->sc_pct_stat_as == 0) 474 sc->sc_pct_stat_as = 4; 475 sc->sc_pct_ctrl_as = sc->sc_pct.pct_ctrl.grd_gas.register_bit_width / 8; 476 if (sc->sc_pct_ctrl_as == 0) 477 sc->sc_pct_ctrl_as = 4; 478 sc->sc_pct_stat_len = sc->sc_pct.pct_status.grd_gas.access_size; 479 if (sc->sc_pct_stat_len == 0) 480 sc->sc_pct_stat_len = sc->sc_pct_stat_as; 481 sc->sc_pct_ctrl_len = sc->sc_pct.pct_ctrl.grd_gas.access_size; 482 if (sc->sc_pct_ctrl_len == 0) 483 sc->sc_pct_ctrl_len = sc->sc_pct_ctrl_as; 484 485 rv = 0; 486 ffh: 487 aml_freevalue(&res); 488 return (rv); 489 } 490 491 int 492 acpicpu_getpss(struct acpicpu_softc *sc) 493 { 494 struct aml_value res; 495 int i; 496 497 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSS", 0, NULL, &res)) { 498 dprintf("%s: no _PSS\n", DEVNAME(sc)); 499 return (1); 500 } 501 502 if (sc->sc_pss) 503 free(sc->sc_pss, M_DEVBUF); 504 505 sc->sc_pss = malloc(res.length * sizeof *sc->sc_pss, M_DEVBUF, 506 M_WAITOK | M_ZERO); 507 508 for (i = 0; i < res.length; i++) { 509 sc->sc_pss[i].pss_core_freq = aml_val2int( 510 res.v_package[i]->v_package[0]); 511 sc->sc_pss[i].pss_power = aml_val2int( 512 res.v_package[i]->v_package[1]); 513 sc->sc_pss[i].pss_trans_latency = aml_val2int( 514 res.v_package[i]->v_package[2]); 515 sc->sc_pss[i].pss_bus_latency = aml_val2int( 516 res.v_package[i]->v_package[3]); 517 sc->sc_pss[i].pss_ctrl = aml_val2int( 518 res.v_package[i]->v_package[4]); 519 sc->sc_pss[i].pss_status = aml_val2int( 520 res.v_package[i]->v_package[5]); 521 } 522 sc->sc_pss_len = res.length; 523 524 aml_freevalue(&res); 525 526 return (0); 527 } 528 529 int 530 acpicpu_fetch_pss(struct acpicpu_pss **pss) 531 { 532 struct acpicpu_softc *sc; 533 534 /* 535 * XXX: According to the ACPI spec in an SMP system all processors 536 * are supposed to support the same states. For now we pray 537 * the bios ensures this... 538 * XXX part deux: this needs to account for _PPC as well 539 * when AC is removed the nr of _PSS entries can go down 540 */ 541 542 sc = acpicpu_sc[0]; 543 if (!sc) 544 return 0; 545 *pss = sc->sc_pss; 546 547 return (sc->sc_pss_len); 548 } 549 550 int 551 acpicpu_notify(struct aml_node *node, int notify_type, void *arg) 552 { 553 struct acpicpu_softc *sc = arg; 554 555 dnprintf(10, "acpicpu_notify: %.2x %s\n", notify_type, 556 sc->sc_devnode->name); 557 558 switch (notify_type) { 559 case 0x80: /* _PPC changed, retrieve new values */ 560 acpicpu_getppc(sc); 561 acpicpu_getpss(sc); 562 if (sc->sc_notify) 563 sc->sc_notify(sc->sc_pss, sc->sc_pss_len); 564 565 /* reset performance to current percentage */ 566 /* XXX will fail for amd64 for now */ 567 cpu_setperf(sc->sc_level); 568 break; 569 default: 570 printf("%s: unhandled cpu event %x\n", DEVNAME(sc), 571 notify_type); 572 break; 573 } 574 575 return (0); 576 } 577 578 void 579 acpicpu_set_notify(void (*func)(struct acpicpu_pss *, int)) { 580 struct acpicpu_softc *sc; 581 582 sc = acpicpu_sc[0]; 583 if (sc != NULL) 584 sc->sc_notify = func; 585 } 586 587 void 588 acpicpu_setperf(int level) 589 { 590 struct acpicpu_softc *sc; 591 struct acpicpu_pss *pss = NULL; 592 int idx, len; 593 u_int32_t status = 0; 594 595 sc = acpicpu_sc[cpu_number()]; 596 597 dnprintf(10, "%s: acpicpu setperf level %d\n", 598 sc->sc_devnode->name, level); 599 600 if (level < 0 || level > 100) { 601 dnprintf(10, "%s: acpicpu setperf illegal percentage\n", 602 sc->sc_devnode->name); 603 return; 604 } 605 606 /* 607 * XXX this should be handled more gracefully and it needs to also do 608 * the duty cycle method instead of pss exclusively 609 */ 610 if (sc->sc_flags & FLAGS_NOPSS || sc->sc_flags & FLAGS_NOPCT) { 611 dnprintf(10, "%s: acpicpu no _PSS or _PCT\n", sc->sc_devnode->name); 612 return; 613 } 614 615 if (sc->sc_ppc) 616 len = sc->sc_ppc; 617 else 618 len = sc->sc_pss_len; 619 idx = (len - 1) - (level / (100 / len)); 620 if (idx < 0) 621 idx = 0; 622 623 if (sc->sc_ppc) 624 idx += sc->sc_pss_len - sc->sc_ppc; 625 626 if (idx > sc->sc_pss_len) 627 idx = sc->sc_pss_len - 1; 628 629 dnprintf(10, "%s: acpicpu setperf index %d pss_len %d ppc %d\n", 630 sc->sc_devnode->name, idx, sc->sc_pss_len, sc->sc_ppc); 631 632 pss = &sc->sc_pss[idx]; 633 634 #ifdef ACPI_DEBUG 635 /* keep this for now since we will need this for debug in the field */ 636 printf("0 status: %x %llx %u %u ctrl: %x %llx %u %u\n", 637 sc->sc_pct.pct_status.grd_gas.address_space_id, 638 sc->sc_pct.pct_status.grd_gas.address, 639 sc->sc_pct_stat_as, sc->sc_pct_stat_len, 640 sc->sc_pct.pct_ctrl.grd_gas.address_space_id, 641 sc->sc_pct.pct_ctrl.grd_gas.address, 642 sc->sc_pct_ctrl_as, sc->sc_pct_ctrl_len); 643 #endif 644 acpi_gasio(sc->sc_acpi, ACPI_IOREAD, 645 sc->sc_pct.pct_status.grd_gas.address_space_id, 646 sc->sc_pct.pct_status.grd_gas.address, sc->sc_pct_stat_as, 647 sc->sc_pct_stat_len, &status); 648 dnprintf(20, "1 status: %u <- %u\n", status, pss->pss_status); 649 650 /* Are we already at the requested frequency? */ 651 if (status == pss->pss_status) 652 return; 653 654 acpi_gasio(sc->sc_acpi, ACPI_IOWRITE, 655 sc->sc_pct.pct_ctrl.grd_gas.address_space_id, 656 sc->sc_pct.pct_ctrl.grd_gas.address, sc->sc_pct_ctrl_as, 657 sc->sc_pct_ctrl_len, &pss->pss_ctrl); 658 dnprintf(20, "pss_ctrl: %x\n", pss->pss_ctrl); 659 660 acpi_gasio(sc->sc_acpi, ACPI_IOREAD, 661 sc->sc_pct.pct_status.grd_gas.address_space_id, 662 sc->sc_pct.pct_status.grd_gas.address, sc->sc_pct_stat_as, 663 sc->sc_pct_stat_as, &status); 664 dnprintf(20, "2 status: %d\n", status); 665 666 /* Did the transition succeed? */ 667 if (status == pss->pss_status) { 668 cpuspeed = pss->pss_core_freq; 669 sc->sc_level = level; 670 } else 671 printf("%s: acpicpu setperf failed to alter frequency\n", 672 sc->sc_devnode->name); 673 } 674