1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * Copyright (c) 2009, Intel Corporation. 27 * All Rights Reserved. 28 */ 29 30 /* 31 * CPU Device driver. The driver is not DDI-compliant. 32 * 33 * The driver supports following features: 34 * - Power management. 35 */ 36 37 #include <sys/types.h> 38 #include <sys/param.h> 39 #include <sys/errno.h> 40 #include <sys/modctl.h> 41 #include <sys/kmem.h> 42 #include <sys/conf.h> 43 #include <sys/cmn_err.h> 44 #include <sys/stat.h> 45 #include <sys/debug.h> 46 #include <sys/systm.h> 47 #include <sys/ddi.h> 48 #include <sys/sunddi.h> 49 #include <sys/sdt.h> 50 #include <sys/epm.h> 51 #include <sys/machsystm.h> 52 #include <sys/x_call.h> 53 #include <sys/cpudrv_mach.h> 54 #include <sys/msacct.h> 55 56 /* 57 * CPU power management 58 * 59 * The supported power saving model is to slow down the CPU (on SPARC by 60 * dividing the CPU clock and on x86 by dropping down a P-state). 61 * Periodically we determine the amount of time the CPU is running 62 * idle thread and threads in user mode during the last quantum. If the idle 63 * thread was running less than its low water mark for current speed for 64 * number of consecutive sampling periods, or number of running threads in 65 * user mode are above its high water mark, we arrange to go to the higher 66 * speed. If the idle thread was running more than its high water mark without 67 * dropping a number of consecutive times below the mark, and number of threads 68 * running in user mode are below its low water mark, we arrange to go to the 69 * next lower speed. While going down, we go through all the speeds. While 70 * going up we go to the maximum speed to minimize impact on the user, but have 71 * provisions in the driver to go to other speeds. 72 * 73 * The driver does not have knowledge of a particular implementation of this 74 * scheme and will work with all CPUs supporting this model. On SPARC, the 75 * driver determines supported speeds by looking at 'clock-divisors' property 76 * created by OBP. On x86, the driver retrieves the supported speeds from 77 * ACPI. 78 */ 79 80 /* 81 * Configuration function prototypes and data structures 82 */ 83 static int cpudrv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 84 static int cpudrv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 85 static int cpudrv_power(dev_info_t *dip, int comp, int level); 86 87 struct dev_ops cpudrv_ops = { 88 DEVO_REV, /* rev */ 89 0, /* refcnt */ 90 nodev, /* getinfo */ 91 nulldev, /* identify */ 92 nulldev, /* probe */ 93 cpudrv_attach, /* attach */ 94 cpudrv_detach, /* detach */ 95 nodev, /* reset */ 96 (struct cb_ops *)NULL, /* cb_ops */ 97 (struct bus_ops *)NULL, /* bus_ops */ 98 cpudrv_power, /* power */ 99 ddi_quiesce_not_needed, /* quiesce */ 100 }; 101 102 static struct modldrv modldrv = { 103 &mod_driverops, /* modops */ 104 "CPU Driver", /* linkinfo */ 105 &cpudrv_ops, /* dev_ops */ 106 }; 107 108 static struct modlinkage modlinkage = { 109 MODREV_1, /* rev */ 110 &modldrv, /* linkage */ 111 NULL 112 }; 113 114 /* 115 * Function prototypes 116 */ 117 static int cpudrv_init(cpudrv_devstate_t *cpudsp); 118 static void cpudrv_free(cpudrv_devstate_t *cpudsp); 119 static int cpudrv_comp_create(cpudrv_devstate_t *cpudsp); 120 static void cpudrv_monitor_disp(void *arg); 121 static void cpudrv_monitor(void *arg); 122 123 /* 124 * Driver global variables 125 */ 126 uint_t cpudrv_debug = 0; 127 void *cpudrv_state; 128 static uint_t cpudrv_idle_hwm = CPUDRV_IDLE_HWM; 129 static uint_t cpudrv_idle_lwm = CPUDRV_IDLE_LWM; 130 static uint_t cpudrv_idle_buf_zone = CPUDRV_IDLE_BUF_ZONE; 131 static uint_t cpudrv_idle_bhwm_cnt_max = CPUDRV_IDLE_BHWM_CNT_MAX; 132 static uint_t cpudrv_idle_blwm_cnt_max = CPUDRV_IDLE_BLWM_CNT_MAX; 133 static uint_t cpudrv_user_hwm = CPUDRV_USER_HWM; 134 135 boolean_t cpudrv_enabled = B_TRUE; 136 137 /* 138 * cpudrv_direct_pm allows user applications to directly control the 139 * power state transitions (direct pm) without following the normal 140 * direct pm protocol. This is needed because the normal protocol 141 * requires that a device only be lowered when it is idle, and be 142 * brought up when it request to do so by calling pm_raise_power(). 143 * Ignoring this protocol is harmless for CPU (other than speed). 144 * Moreover it might be the case that CPU is never idle or wants 145 * to be at higher speed because of the addition CPU cycles required 146 * to run the user application. 147 * 148 * The driver will still report idle/busy status to the framework. Although 149 * framework will ignore this information for direct pm devices and not 150 * try to bring them down when idle, user applications can still use this 151 * information if they wants. 152 * 153 * In the future, provide an ioctl to control setting of this mode. In 154 * that case, this variable should move to the state structure and 155 * be protected by the lock in the state structure. 156 */ 157 int cpudrv_direct_pm = 0; 158 159 /* 160 * Arranges for the handler function to be called at the interval suitable 161 * for current speed. 162 */ 163 #define CPUDRV_MONITOR_INIT(cpudsp) { \ 164 if (cpudrv_is_enabled(cpudsp)) { \ 165 ASSERT(mutex_owned(&(cpudsp)->lock)); \ 166 (cpudsp)->cpudrv_pm.timeout_id = \ 167 timeout(cpudrv_monitor_disp, \ 168 (cpudsp), (((cpudsp)->cpudrv_pm.cur_spd == NULL) ? \ 169 CPUDRV_QUANT_CNT_OTHR : \ 170 (cpudsp)->cpudrv_pm.cur_spd->quant_cnt)); \ 171 } \ 172 } 173 174 /* 175 * Arranges for the handler function not to be called back. 176 */ 177 #define CPUDRV_MONITOR_FINI(cpudsp) { \ 178 timeout_id_t tmp_tid; \ 179 ASSERT(mutex_owned(&(cpudsp)->lock)); \ 180 tmp_tid = (cpudsp)->cpudrv_pm.timeout_id; \ 181 (cpudsp)->cpudrv_pm.timeout_id = 0; \ 182 mutex_exit(&(cpudsp)->lock); \ 183 if (tmp_tid != 0) { \ 184 (void) untimeout(tmp_tid); \ 185 mutex_enter(&(cpudsp)->cpudrv_pm.timeout_lock); \ 186 while ((cpudsp)->cpudrv_pm.timeout_count != 0) \ 187 cv_wait(&(cpudsp)->cpudrv_pm.timeout_cv, \ 188 &(cpudsp)->cpudrv_pm.timeout_lock); \ 189 mutex_exit(&(cpudsp)->cpudrv_pm.timeout_lock); \ 190 } \ 191 mutex_enter(&(cpudsp)->lock); \ 192 } 193 194 int 195 _init(void) 196 { 197 int error; 198 199 DPRINTF(D_INIT, (" _init: function called\n")); 200 if ((error = ddi_soft_state_init(&cpudrv_state, 201 sizeof (cpudrv_devstate_t), 0)) != 0) { 202 return (error); 203 } 204 205 if ((error = mod_install(&modlinkage)) != 0) { 206 ddi_soft_state_fini(&cpudrv_state); 207 } 208 209 /* 210 * Callbacks used by the PPM driver. 211 */ 212 CPUDRV_SET_PPM_CALLBACKS(); 213 return (error); 214 } 215 216 int 217 _fini(void) 218 { 219 int error; 220 221 DPRINTF(D_FINI, (" _fini: function called\n")); 222 if ((error = mod_remove(&modlinkage)) == 0) { 223 ddi_soft_state_fini(&cpudrv_state); 224 } 225 226 return (error); 227 } 228 229 int 230 _info(struct modinfo *modinfop) 231 { 232 return (mod_info(&modlinkage, modinfop)); 233 } 234 235 /* 236 * Driver attach(9e) entry point. 237 */ 238 static int 239 cpudrv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 240 { 241 int instance; 242 cpudrv_devstate_t *cpudsp; 243 244 instance = ddi_get_instance(dip); 245 246 switch (cmd) { 247 case DDI_ATTACH: 248 DPRINTF(D_ATTACH, ("cpudrv_attach: instance %d: " 249 "DDI_ATTACH called\n", instance)); 250 if (!cpudrv_is_enabled(NULL)) 251 return (DDI_FAILURE); 252 if (ddi_soft_state_zalloc(cpudrv_state, instance) != 253 DDI_SUCCESS) { 254 cmn_err(CE_WARN, "cpudrv_attach: instance %d: " 255 "can't allocate state", instance); 256 cpudrv_enabled = B_FALSE; 257 return (DDI_FAILURE); 258 } 259 if ((cpudsp = ddi_get_soft_state(cpudrv_state, instance)) == 260 NULL) { 261 cmn_err(CE_WARN, "cpudrv_attach: instance %d: " 262 "can't get state", instance); 263 ddi_soft_state_free(cpudrv_state, instance); 264 cpudrv_enabled = B_FALSE; 265 return (DDI_FAILURE); 266 } 267 cpudsp->dip = dip; 268 269 /* 270 * Find CPU number for this dev_info node. 271 */ 272 if (!cpudrv_get_cpu_id(dip, &(cpudsp->cpu_id))) { 273 cmn_err(CE_WARN, "cpudrv_attach: instance %d: " 274 "can't convert dip to cpu_id", instance); 275 ddi_soft_state_free(cpudrv_state, instance); 276 cpudrv_enabled = B_FALSE; 277 return (DDI_FAILURE); 278 } 279 280 mutex_enter(&cpu_lock); 281 cpudsp->cp = cpu_get(cpudsp->cpu_id); 282 mutex_exit(&cpu_lock); 283 if (cpudsp->cp == NULL) { 284 cmn_err(CE_WARN, "cpudrv_attach: instance %d: " 285 "can't get cpu_t", ddi_get_instance(cpudsp->dip)); 286 ddi_soft_state_free(cpudrv_state, instance); 287 cpudrv_enabled = B_FALSE; 288 return (DDI_FAILURE); 289 } 290 291 mutex_init(&cpudsp->lock, NULL, MUTEX_DRIVER, NULL); 292 if (cpudrv_is_enabled(cpudsp)) { 293 if (cpudrv_init(cpudsp) != DDI_SUCCESS) { 294 cpudrv_enabled = B_FALSE; 295 cpudrv_free(cpudsp); 296 ddi_soft_state_free(cpudrv_state, instance); 297 return (DDI_FAILURE); 298 } 299 if (cpudrv_comp_create(cpudsp) != DDI_SUCCESS) { 300 cpudrv_enabled = B_FALSE; 301 cpudrv_free(cpudsp); 302 ddi_soft_state_free(cpudrv_state, instance); 303 return (DDI_FAILURE); 304 } 305 if (ddi_prop_update_string(DDI_DEV_T_NONE, 306 dip, "pm-class", "CPU") != DDI_PROP_SUCCESS) { 307 cpudrv_enabled = B_FALSE; 308 cpudrv_free(cpudsp); 309 ddi_soft_state_free(cpudrv_state, instance); 310 return (DDI_FAILURE); 311 } 312 313 /* 314 * Taskq is used to dispatch routine to monitor CPU 315 * activities. 316 */ 317 cpudsp->cpudrv_pm.tq = ddi_taskq_create(dip, 318 "cpudrv_monitor", CPUDRV_TASKQ_THREADS, 319 TASKQ_DEFAULTPRI, 0); 320 321 mutex_init(&cpudsp->cpudrv_pm.timeout_lock, NULL, 322 MUTEX_DRIVER, NULL); 323 cv_init(&cpudsp->cpudrv_pm.timeout_cv, NULL, 324 CV_DEFAULT, NULL); 325 326 /* 327 * Driver needs to assume that CPU is running at 328 * unknown speed at DDI_ATTACH and switch it to the 329 * needed speed. We assume that initial needed speed 330 * is full speed for us. 331 */ 332 /* 333 * We need to take the lock because cpudrv_monitor() 334 * will start running in parallel with attach(). 335 */ 336 mutex_enter(&cpudsp->lock); 337 cpudsp->cpudrv_pm.cur_spd = NULL; 338 cpudsp->cpudrv_pm.pm_started = B_FALSE; 339 /* 340 * We don't call pm_raise_power() directly from attach 341 * because driver attach for a slave CPU node can 342 * happen before the CPU is even initialized. We just 343 * start the monitoring system which understands 344 * unknown speed and moves CPU to top speed when it 345 * has been initialized. 346 */ 347 CPUDRV_MONITOR_INIT(cpudsp); 348 mutex_exit(&cpudsp->lock); 349 350 } 351 352 if (!cpudrv_mach_init(cpudsp)) { 353 cmn_err(CE_WARN, "cpudrv_attach: instance %d: " 354 "cpudrv_mach_init failed", instance); 355 cpudrv_enabled = B_FALSE; 356 cpudrv_free(cpudsp); 357 ddi_soft_state_free(cpudrv_state, instance); 358 return (DDI_FAILURE); 359 } 360 361 CPUDRV_INSTALL_MAX_CHANGE_HANDLER(cpudsp); 362 363 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, 364 DDI_NO_AUTODETACH, 1); 365 ddi_report_dev(dip); 366 return (DDI_SUCCESS); 367 368 case DDI_RESUME: 369 DPRINTF(D_ATTACH, ("cpudrv_attach: instance %d: " 370 "DDI_RESUME called\n", instance)); 371 372 cpudsp = ddi_get_soft_state(cpudrv_state, instance); 373 ASSERT(cpudsp != NULL); 374 375 /* 376 * Nothing to do for resume, if not doing active PM. 377 */ 378 if (!cpudrv_is_enabled(cpudsp)) 379 return (DDI_SUCCESS); 380 381 mutex_enter(&cpudsp->lock); 382 /* 383 * Driver needs to assume that CPU is running at unknown speed 384 * at DDI_RESUME and switch it to the needed speed. We assume 385 * that the needed speed is full speed for us. 386 */ 387 cpudsp->cpudrv_pm.cur_spd = NULL; 388 CPUDRV_MONITOR_INIT(cpudsp); 389 mutex_exit(&cpudsp->lock); 390 CPUDRV_REDEFINE_TOPSPEED(dip); 391 return (DDI_SUCCESS); 392 393 default: 394 return (DDI_FAILURE); 395 } 396 } 397 398 /* 399 * Driver detach(9e) entry point. 400 */ 401 static int 402 cpudrv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 403 { 404 int instance; 405 cpudrv_devstate_t *cpudsp; 406 cpudrv_pm_t *cpupm; 407 408 instance = ddi_get_instance(dip); 409 410 switch (cmd) { 411 case DDI_DETACH: 412 DPRINTF(D_DETACH, ("cpudrv_detach: instance %d: " 413 "DDI_DETACH called\n", instance)); 414 415 #if defined(__x86) 416 cpudsp = ddi_get_soft_state(cpudrv_state, instance); 417 ASSERT(cpudsp != NULL); 418 419 /* 420 * Nothing to do for detach, if no doing active PM. 421 */ 422 if (!cpudrv_is_enabled(cpudsp)) 423 return (DDI_SUCCESS); 424 425 /* 426 * uninstall PPC/_TPC change notification handler 427 */ 428 CPUDRV_UNINSTALL_MAX_CHANGE_HANDLER(cpudsp); 429 430 /* 431 * destruct platform specific resource 432 */ 433 if (!cpudrv_mach_fini(cpudsp)) 434 return (DDI_FAILURE); 435 436 mutex_enter(&cpudsp->lock); 437 CPUDRV_MONITOR_FINI(cpudsp); 438 cv_destroy(&cpudsp->cpudrv_pm.timeout_cv); 439 mutex_destroy(&cpudsp->cpudrv_pm.timeout_lock); 440 ddi_taskq_destroy(cpudsp->cpudrv_pm.tq); 441 cpudrv_free(cpudsp); 442 mutex_exit(&cpudsp->lock); 443 mutex_destroy(&cpudsp->lock); 444 ddi_soft_state_free(cpudrv_state, instance); 445 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, 446 DDI_NO_AUTODETACH, 0); 447 return (DDI_SUCCESS); 448 449 #else 450 /* 451 * If the only thing supported by the driver is power 452 * management, we can in future enhance the driver and 453 * framework that loads it to unload the driver when 454 * user has disabled CPU power management. 455 */ 456 return (DDI_FAILURE); 457 #endif 458 459 case DDI_SUSPEND: 460 DPRINTF(D_DETACH, ("cpudrv_detach: instance %d: " 461 "DDI_SUSPEND called\n", instance)); 462 463 cpudsp = ddi_get_soft_state(cpudrv_state, instance); 464 ASSERT(cpudsp != NULL); 465 466 /* 467 * Nothing to do for suspend, if not doing active PM. 468 */ 469 if (!cpudrv_is_enabled(cpudsp)) 470 return (DDI_SUCCESS); 471 472 /* 473 * During a checkpoint-resume sequence, framework will 474 * stop interrupts to quiesce kernel activity. This will 475 * leave our monitoring system ineffective. Handle this 476 * by stopping our monitoring system and bringing CPU 477 * to full speed. In case we are in special direct pm 478 * mode, we leave the CPU at whatever speed it is. This 479 * is harmless other than speed. 480 */ 481 mutex_enter(&cpudsp->lock); 482 cpupm = &(cpudsp->cpudrv_pm); 483 484 DPRINTF(D_DETACH, ("cpudrv_detach: instance %d: DDI_SUSPEND - " 485 "cur_spd %d, topspeed %d\n", instance, 486 cpupm->cur_spd->pm_level, 487 CPUDRV_TOPSPEED(cpupm)->pm_level)); 488 489 CPUDRV_MONITOR_FINI(cpudsp); 490 491 if (!cpudrv_direct_pm && (cpupm->cur_spd != 492 CPUDRV_TOPSPEED(cpupm))) { 493 if (cpupm->pm_busycnt < 1) { 494 if ((pm_busy_component(dip, CPUDRV_COMP_NUM) 495 == DDI_SUCCESS)) { 496 cpupm->pm_busycnt++; 497 } else { 498 CPUDRV_MONITOR_INIT(cpudsp); 499 mutex_exit(&cpudsp->lock); 500 cmn_err(CE_WARN, "cpudrv_detach: " 501 "instance %d: can't busy CPU " 502 "component", instance); 503 return (DDI_FAILURE); 504 } 505 } 506 mutex_exit(&cpudsp->lock); 507 if (pm_raise_power(dip, CPUDRV_COMP_NUM, 508 CPUDRV_TOPSPEED(cpupm)->pm_level) != 509 DDI_SUCCESS) { 510 mutex_enter(&cpudsp->lock); 511 CPUDRV_MONITOR_INIT(cpudsp); 512 mutex_exit(&cpudsp->lock); 513 cmn_err(CE_WARN, "cpudrv_detach: instance %d: " 514 "can't raise CPU power level to %d", 515 instance, 516 CPUDRV_TOPSPEED(cpupm)->pm_level); 517 return (DDI_FAILURE); 518 } else { 519 return (DDI_SUCCESS); 520 } 521 } else { 522 mutex_exit(&cpudsp->lock); 523 return (DDI_SUCCESS); 524 } 525 526 default: 527 return (DDI_FAILURE); 528 } 529 } 530 531 /* 532 * Driver power(9e) entry point. 533 * 534 * Driver's notion of current power is set *only* in power(9e) entry point 535 * after actual power change operation has been successfully completed. 536 */ 537 /* ARGSUSED */ 538 static int 539 cpudrv_power(dev_info_t *dip, int comp, int level) 540 { 541 int instance; 542 cpudrv_devstate_t *cpudsp; 543 cpudrv_pm_t *cpudrvpm; 544 cpudrv_pm_spd_t *new_spd; 545 boolean_t is_ready; 546 int ret; 547 548 instance = ddi_get_instance(dip); 549 550 DPRINTF(D_POWER, ("cpudrv_power: instance %d: level %d\n", 551 instance, level)); 552 553 if ((cpudsp = ddi_get_soft_state(cpudrv_state, instance)) == NULL) { 554 cmn_err(CE_WARN, "cpudrv_power: instance %d: can't " 555 "get state", instance); 556 return (DDI_FAILURE); 557 } 558 559 mutex_enter(&cpudsp->lock); 560 cpudrvpm = &(cpudsp->cpudrv_pm); 561 562 /* 563 * In normal operation, we fail if we are busy and request is 564 * to lower the power level. We let this go through if the driver 565 * is in special direct pm mode. On x86, we also let this through 566 * if the change is due to a request to govern the max speed. 567 */ 568 if (!cpudrv_direct_pm && (cpudrvpm->pm_busycnt >= 1) && 569 !cpudrv_is_governor_thread(cpudrvpm)) { 570 if ((cpudrvpm->cur_spd != NULL) && 571 (level < cpudrvpm->cur_spd->pm_level)) { 572 mutex_exit(&cpudsp->lock); 573 return (DDI_FAILURE); 574 } 575 } 576 577 for (new_spd = cpudrvpm->head_spd; new_spd; new_spd = 578 new_spd->down_spd) { 579 if (new_spd->pm_level == level) 580 break; 581 } 582 if (!new_spd) { 583 CPUDRV_RESET_GOVERNOR_THREAD(cpudrvpm); 584 mutex_exit(&cpudsp->lock); 585 cmn_err(CE_WARN, "cpudrv_power: instance %d: " 586 "can't locate new CPU speed", instance); 587 return (DDI_FAILURE); 588 } 589 590 /* 591 * We currently refuse to power manage if the CPU is not ready to 592 * take cross calls (cross calls fail silently if CPU is not ready 593 * for it). 594 * 595 * Additionally, for x86 platforms we cannot power manage an instance, 596 * until it has been initialized. 597 */ 598 ASSERT(cpudsp->cp); 599 is_ready = CPUDRV_XCALL_IS_READY(cpudsp->cpu_id); 600 if (!is_ready) { 601 DPRINTF(D_POWER, ("cpudrv_power: instance %d: " 602 "CPU not ready for x-calls\n", instance)); 603 } else if (!(is_ready = cpudrv_power_ready(cpudsp->cp))) { 604 DPRINTF(D_POWER, ("cpudrv_power: instance %d: " 605 "waiting for all CPUs to be power manageable\n", 606 instance)); 607 } 608 if (!is_ready) { 609 CPUDRV_RESET_GOVERNOR_THREAD(cpudrvpm); 610 mutex_exit(&cpudsp->lock); 611 return (DDI_FAILURE); 612 } 613 614 /* 615 * Execute CPU specific routine on the requested CPU to 616 * change its speed to normal-speed/divisor. 617 */ 618 if ((ret = cpudrv_change_speed(cpudsp, new_spd)) != DDI_SUCCESS) { 619 cmn_err(CE_WARN, "cpudrv_power: " 620 "cpudrv_change_speed() return = %d", ret); 621 mutex_exit(&cpudsp->lock); 622 return (DDI_FAILURE); 623 } 624 625 /* 626 * Reset idle threshold time for the new power level. 627 */ 628 if ((cpudrvpm->cur_spd != NULL) && (level < 629 cpudrvpm->cur_spd->pm_level)) { 630 if (pm_idle_component(dip, CPUDRV_COMP_NUM) == 631 DDI_SUCCESS) { 632 if (cpudrvpm->pm_busycnt >= 1) 633 cpudrvpm->pm_busycnt--; 634 } else { 635 cmn_err(CE_WARN, "cpudrv_power: instance %d: " 636 "can't idle CPU component", 637 ddi_get_instance(dip)); 638 } 639 } 640 /* 641 * Reset various parameters because we are now running at new speed. 642 */ 643 cpudrvpm->lastquan_mstate[CMS_IDLE] = 0; 644 cpudrvpm->lastquan_mstate[CMS_SYSTEM] = 0; 645 cpudrvpm->lastquan_mstate[CMS_USER] = 0; 646 cpudrvpm->lastquan_ticks = 0; 647 cpudrvpm->cur_spd = new_spd; 648 CPUDRV_RESET_GOVERNOR_THREAD(cpudrvpm); 649 mutex_exit(&cpudsp->lock); 650 651 return (DDI_SUCCESS); 652 } 653 654 /* 655 * Initialize power management data. 656 */ 657 static int 658 cpudrv_init(cpudrv_devstate_t *cpudsp) 659 { 660 cpudrv_pm_t *cpupm = &(cpudsp->cpudrv_pm); 661 cpudrv_pm_spd_t *cur_spd; 662 cpudrv_pm_spd_t *prev_spd = NULL; 663 int *speeds; 664 uint_t nspeeds; 665 int idle_cnt_percent; 666 int user_cnt_percent; 667 int i; 668 669 CPUDRV_GET_SPEEDS(cpudsp, speeds, nspeeds); 670 if (nspeeds < 2) { 671 /* Need at least two speeds to power manage */ 672 CPUDRV_FREE_SPEEDS(speeds, nspeeds); 673 return (DDI_FAILURE); 674 } 675 cpupm->num_spd = nspeeds; 676 677 /* 678 * Calculate the watermarks and other parameters based on the 679 * supplied speeds. 680 * 681 * One of the basic assumption is that for X amount of CPU work, 682 * if CPU is slowed down by a factor of N, the time it takes to 683 * do the same work will be N * X. 684 * 685 * The driver declares that a CPU is idle and ready for slowed down, 686 * if amount of idle thread is more than the current speed idle_hwm 687 * without dropping below idle_hwm a number of consecutive sampling 688 * intervals and number of running threads in user mode are below 689 * user_lwm. We want to set the current user_lwm such that if we 690 * just switched to the next slower speed with no change in real work 691 * load, the amount of user threads at the slower speed will be such 692 * that it falls below the slower speed's user_hwm. If we didn't do 693 * that then we will just come back to the higher speed as soon as we 694 * go down even with no change in work load. 695 * The user_hwm is a fixed precentage and not calculated dynamically. 696 * 697 * We bring the CPU up if idle thread at current speed is less than 698 * the current speed idle_lwm for a number of consecutive sampling 699 * intervals or user threads are above the user_hwm for the current 700 * speed. 701 */ 702 for (i = 0; i < nspeeds; i++) { 703 cur_spd = kmem_zalloc(sizeof (cpudrv_pm_spd_t), KM_SLEEP); 704 cur_spd->speed = speeds[i]; 705 if (i == 0) { /* normal speed */ 706 cpupm->head_spd = cur_spd; 707 CPUDRV_TOPSPEED(cpupm) = cur_spd; 708 cur_spd->quant_cnt = CPUDRV_QUANT_CNT_NORMAL; 709 cur_spd->idle_hwm = 710 (cpudrv_idle_hwm * cur_spd->quant_cnt) / 100; 711 /* can't speed anymore */ 712 cur_spd->idle_lwm = 0; 713 cur_spd->user_hwm = UINT_MAX; 714 } else { 715 cur_spd->quant_cnt = CPUDRV_QUANT_CNT_OTHR; 716 ASSERT(prev_spd != NULL); 717 prev_spd->down_spd = cur_spd; 718 cur_spd->up_spd = cpupm->head_spd; 719 720 /* 721 * Let's assume CPU is considered idle at full speed 722 * when it is spending I% of time in running the idle 723 * thread. At full speed, CPU will be busy (100 - I) % 724 * of times. This % of busyness increases by factor of 725 * N as CPU slows down. CPU that is idle I% of times 726 * in full speed, it is idle (100 - ((100 - I) * N)) % 727 * of times in N speed. The idle_lwm is a fixed 728 * percentage. A large value of N may result in 729 * idle_hwm to go below idle_lwm. We need to make sure 730 * that there is at least a buffer zone seperation 731 * between the idle_lwm and idle_hwm values. 732 */ 733 idle_cnt_percent = CPUDRV_IDLE_CNT_PERCENT( 734 cpudrv_idle_hwm, speeds, i); 735 idle_cnt_percent = max(idle_cnt_percent, 736 (cpudrv_idle_lwm + cpudrv_idle_buf_zone)); 737 cur_spd->idle_hwm = 738 (idle_cnt_percent * cur_spd->quant_cnt) / 100; 739 cur_spd->idle_lwm = 740 (cpudrv_idle_lwm * cur_spd->quant_cnt) / 100; 741 742 /* 743 * The lwm for user threads are determined such that 744 * if CPU slows down, the load of work in the 745 * new speed would still keep the CPU at or below the 746 * user_hwm in the new speed. This is to prevent 747 * the quick jump back up to higher speed. 748 */ 749 cur_spd->user_hwm = (cpudrv_user_hwm * 750 cur_spd->quant_cnt) / 100; 751 user_cnt_percent = CPUDRV_USER_CNT_PERCENT( 752 cpudrv_user_hwm, speeds, i); 753 prev_spd->user_lwm = 754 (user_cnt_percent * prev_spd->quant_cnt) / 100; 755 } 756 prev_spd = cur_spd; 757 } 758 /* Slowest speed. Can't slow down anymore */ 759 cur_spd->idle_hwm = UINT_MAX; 760 cur_spd->user_lwm = -1; 761 #ifdef DEBUG 762 DPRINTF(D_PM_INIT, ("cpudrv_init: instance %d: head_spd spd %d, " 763 "num_spd %d\n", ddi_get_instance(cpudsp->dip), 764 cpupm->head_spd->speed, cpupm->num_spd)); 765 for (cur_spd = cpupm->head_spd; cur_spd; cur_spd = cur_spd->down_spd) { 766 DPRINTF(D_PM_INIT, ("cpudrv_init: instance %d: speed %d, " 767 "down_spd spd %d, idle_hwm %d, user_lwm %d, " 768 "up_spd spd %d, idle_lwm %d, user_hwm %d, " 769 "quant_cnt %d\n", ddi_get_instance(cpudsp->dip), 770 cur_spd->speed, 771 (cur_spd->down_spd ? cur_spd->down_spd->speed : 0), 772 cur_spd->idle_hwm, cur_spd->user_lwm, 773 (cur_spd->up_spd ? cur_spd->up_spd->speed : 0), 774 cur_spd->idle_lwm, cur_spd->user_hwm, 775 cur_spd->quant_cnt)); 776 } 777 #endif /* DEBUG */ 778 CPUDRV_FREE_SPEEDS(speeds, nspeeds); 779 return (DDI_SUCCESS); 780 } 781 782 /* 783 * Free CPU power management data. 784 */ 785 static void 786 cpudrv_free(cpudrv_devstate_t *cpudsp) 787 { 788 cpudrv_pm_t *cpupm = &(cpudsp->cpudrv_pm); 789 cpudrv_pm_spd_t *cur_spd, *next_spd; 790 791 cur_spd = cpupm->head_spd; 792 while (cur_spd) { 793 next_spd = cur_spd->down_spd; 794 kmem_free(cur_spd, sizeof (cpudrv_pm_spd_t)); 795 cur_spd = next_spd; 796 } 797 bzero(cpupm, sizeof (cpudrv_pm_t)); 798 } 799 800 /* 801 * Create pm-components property. 802 */ 803 static int 804 cpudrv_comp_create(cpudrv_devstate_t *cpudsp) 805 { 806 cpudrv_pm_t *cpupm = &(cpudsp->cpudrv_pm); 807 cpudrv_pm_spd_t *cur_spd; 808 char **pmc; 809 int size; 810 char name[] = "NAME=CPU Speed"; 811 int i, j; 812 uint_t comp_spd; 813 int result = DDI_FAILURE; 814 815 pmc = kmem_zalloc((cpupm->num_spd + 1) * sizeof (char *), KM_SLEEP); 816 size = CPUDRV_COMP_SIZE(); 817 if (cpupm->num_spd > CPUDRV_COMP_MAX_VAL) { 818 cmn_err(CE_WARN, "cpudrv_comp_create: instance %d: " 819 "number of speeds exceeded limits", 820 ddi_get_instance(cpudsp->dip)); 821 kmem_free(pmc, (cpupm->num_spd + 1) * sizeof (char *)); 822 return (result); 823 } 824 825 for (i = cpupm->num_spd, cur_spd = cpupm->head_spd; i > 0; 826 i--, cur_spd = cur_spd->down_spd) { 827 cur_spd->pm_level = i; 828 pmc[i] = kmem_zalloc((size * sizeof (char)), KM_SLEEP); 829 comp_spd = CPUDRV_COMP_SPEED(cpupm, cur_spd); 830 if (comp_spd > CPUDRV_COMP_MAX_VAL) { 831 cmn_err(CE_WARN, "cpudrv_comp_create: " 832 "instance %d: speed exceeded limits", 833 ddi_get_instance(cpudsp->dip)); 834 for (j = cpupm->num_spd; j >= i; j--) { 835 kmem_free(pmc[j], size * sizeof (char)); 836 } 837 kmem_free(pmc, (cpupm->num_spd + 1) * 838 sizeof (char *)); 839 return (result); 840 } 841 CPUDRV_COMP_SPRINT(pmc[i], cpupm, cur_spd, comp_spd) 842 DPRINTF(D_PM_COMP_CREATE, ("cpudrv_comp_create: " 843 "instance %d: pm-components power level %d string '%s'\n", 844 ddi_get_instance(cpudsp->dip), i, pmc[i])); 845 } 846 pmc[0] = kmem_zalloc(sizeof (name), KM_SLEEP); 847 (void) strcat(pmc[0], name); 848 DPRINTF(D_PM_COMP_CREATE, ("cpudrv_comp_create: instance %d: " 849 "pm-components component name '%s'\n", 850 ddi_get_instance(cpudsp->dip), pmc[0])); 851 852 if (ddi_prop_update_string_array(DDI_DEV_T_NONE, cpudsp->dip, 853 "pm-components", pmc, cpupm->num_spd + 1) == DDI_PROP_SUCCESS) { 854 result = DDI_SUCCESS; 855 } else { 856 cmn_err(CE_WARN, "cpudrv_comp_create: instance %d: " 857 "can't create pm-components property", 858 ddi_get_instance(cpudsp->dip)); 859 } 860 861 for (i = cpupm->num_spd; i > 0; i--) { 862 kmem_free(pmc[i], size * sizeof (char)); 863 } 864 kmem_free(pmc[0], sizeof (name)); 865 kmem_free(pmc, (cpupm->num_spd + 1) * sizeof (char *)); 866 return (result); 867 } 868 869 /* 870 * Mark a component idle. 871 */ 872 #define CPUDRV_MONITOR_PM_IDLE_COMP(dip, cpupm) { \ 873 if ((cpupm)->pm_busycnt >= 1) { \ 874 if (pm_idle_component((dip), CPUDRV_COMP_NUM) == \ 875 DDI_SUCCESS) { \ 876 DPRINTF(D_PM_MONITOR, ("cpudrv_monitor: " \ 877 "instance %d: pm_idle_component called\n", \ 878 ddi_get_instance((dip)))); \ 879 (cpupm)->pm_busycnt--; \ 880 } else { \ 881 cmn_err(CE_WARN, "cpudrv_monitor: instance %d: " \ 882 "can't idle CPU component", \ 883 ddi_get_instance((dip))); \ 884 } \ 885 } \ 886 } 887 888 /* 889 * Marks a component busy in both PM framework and driver state structure. 890 */ 891 #define CPUDRV_MONITOR_PM_BUSY_COMP(dip, cpupm) { \ 892 if ((cpupm)->pm_busycnt < 1) { \ 893 if (pm_busy_component((dip), CPUDRV_COMP_NUM) == \ 894 DDI_SUCCESS) { \ 895 DPRINTF(D_PM_MONITOR, ("cpudrv_monitor: " \ 896 "instance %d: pm_busy_component called\n", \ 897 ddi_get_instance((dip)))); \ 898 (cpupm)->pm_busycnt++; \ 899 } else { \ 900 cmn_err(CE_WARN, "cpudrv_monitor: instance %d: " \ 901 "can't busy CPU component", \ 902 ddi_get_instance((dip))); \ 903 } \ 904 } \ 905 } 906 907 /* 908 * Marks a component busy and calls pm_raise_power(). 909 */ 910 #define CPUDRV_MONITOR_PM_BUSY_AND_RAISE(dip, cpudsp, cpupm, new_spd) { \ 911 int ret; \ 912 /* \ 913 * Mark driver and PM framework busy first so framework doesn't try \ 914 * to bring CPU to lower speed when we need to be at higher speed. \ 915 */ \ 916 CPUDRV_MONITOR_PM_BUSY_COMP((dip), (cpupm)); \ 917 mutex_exit(&(cpudsp)->lock); \ 918 DPRINTF(D_PM_MONITOR, ("cpudrv_monitor: instance %d: " \ 919 "pm_raise_power called to %d\n", ddi_get_instance((dip)), \ 920 (new_spd->pm_level))); \ 921 ret = pm_raise_power((dip), CPUDRV_COMP_NUM, (new_spd->pm_level)); \ 922 if (ret != DDI_SUCCESS) { \ 923 cmn_err(CE_WARN, "cpudrv_monitor: instance %d: can't " \ 924 "raise CPU power level", ddi_get_instance((dip))); \ 925 } \ 926 mutex_enter(&(cpudsp)->lock); \ 927 if (ret == DDI_SUCCESS && cpudsp->cpudrv_pm.cur_spd == NULL) { \ 928 cpudsp->cpudrv_pm.cur_spd = new_spd; \ 929 } \ 930 } 931 932 /* 933 * In order to monitor a CPU, we need to hold cpu_lock to access CPU 934 * statistics. Holding cpu_lock is not allowed from a callout routine. 935 * We dispatch a taskq to do that job. 936 */ 937 static void 938 cpudrv_monitor_disp(void *arg) 939 { 940 cpudrv_devstate_t *cpudsp = (cpudrv_devstate_t *)arg; 941 942 /* 943 * We are here because the last task has scheduled a timeout. 944 * The queue should be empty at this time. 945 */ 946 mutex_enter(&cpudsp->cpudrv_pm.timeout_lock); 947 if ((ddi_taskq_dispatch(cpudsp->cpudrv_pm.tq, cpudrv_monitor, arg, 948 DDI_NOSLEEP)) != DDI_SUCCESS) { 949 mutex_exit(&cpudsp->cpudrv_pm.timeout_lock); 950 DPRINTF(D_PM_MONITOR, ("cpudrv_monitor_disp: failed to " 951 "dispatch the cpudrv_monitor taskq\n")); 952 mutex_enter(&cpudsp->lock); 953 CPUDRV_MONITOR_INIT(cpudsp); 954 mutex_exit(&cpudsp->lock); 955 return; 956 } 957 cpudsp->cpudrv_pm.timeout_count++; 958 mutex_exit(&cpudsp->cpudrv_pm.timeout_lock); 959 } 960 961 /* 962 * Monitors each CPU for the amount of time idle thread was running in the 963 * last quantum and arranges for the CPU to go to the lower or higher speed. 964 * Called at the time interval appropriate for the current speed. The 965 * time interval for normal speed is CPUDRV_QUANT_CNT_NORMAL. The time 966 * interval for other speeds (including unknown speed) is 967 * CPUDRV_QUANT_CNT_OTHR. 968 */ 969 static void 970 cpudrv_monitor(void *arg) 971 { 972 cpudrv_devstate_t *cpudsp = (cpudrv_devstate_t *)arg; 973 cpudrv_pm_t *cpupm; 974 cpudrv_pm_spd_t *cur_spd, *new_spd; 975 dev_info_t *dip; 976 uint_t idle_cnt, user_cnt, system_cnt; 977 clock_t ticks; 978 uint_t tick_cnt; 979 hrtime_t msnsecs[NCMSTATES]; 980 boolean_t is_ready; 981 982 #define GET_CPU_MSTATE_CNT(state, cnt) \ 983 msnsecs[state] = NSEC_TO_TICK(msnsecs[state]); \ 984 if (cpupm->lastquan_mstate[state] > msnsecs[state]) \ 985 msnsecs[state] = cpupm->lastquan_mstate[state]; \ 986 cnt = msnsecs[state] - cpupm->lastquan_mstate[state]; \ 987 cpupm->lastquan_mstate[state] = msnsecs[state] 988 989 mutex_enter(&cpudsp->lock); 990 cpupm = &(cpudsp->cpudrv_pm); 991 if (cpupm->timeout_id == 0) { 992 mutex_exit(&cpudsp->lock); 993 goto do_return; 994 } 995 cur_spd = cpupm->cur_spd; 996 dip = cpudsp->dip; 997 998 /* 999 * We assume that a CPU is initialized and has a valid cpu_t 1000 * structure, if it is ready for cross calls. If this changes, 1001 * additional checks might be needed. 1002 * 1003 * Additionally, for x86 platforms we cannot power manage an 1004 * instance, until it has been initialized. 1005 */ 1006 ASSERT(cpudsp->cp); 1007 is_ready = CPUDRV_XCALL_IS_READY(cpudsp->cpu_id); 1008 if (!is_ready) { 1009 DPRINTF(D_PM_MONITOR, ("cpudrv_monitor: instance %d: " 1010 "CPU not ready for x-calls\n", ddi_get_instance(dip))); 1011 } else if (!(is_ready = cpudrv_power_ready(cpudsp->cp))) { 1012 DPRINTF(D_PM_MONITOR, ("cpudrv_monitor: instance %d: " 1013 "waiting for all CPUs to be power manageable\n", 1014 ddi_get_instance(dip))); 1015 } 1016 if (!is_ready) { 1017 /* 1018 * Make sure that we are busy so that framework doesn't 1019 * try to bring us down in this situation. 1020 */ 1021 CPUDRV_MONITOR_PM_BUSY_COMP(dip, cpupm); 1022 CPUDRV_MONITOR_INIT(cpudsp); 1023 mutex_exit(&cpudsp->lock); 1024 goto do_return; 1025 } 1026 1027 /* 1028 * Make sure that we are still not at unknown power level. 1029 */ 1030 if (cur_spd == NULL) { 1031 DPRINTF(D_PM_MONITOR, ("cpudrv_monitor: instance %d: " 1032 "cur_spd is unknown\n", ddi_get_instance(dip))); 1033 CPUDRV_MONITOR_PM_BUSY_AND_RAISE(dip, cpudsp, cpupm, 1034 CPUDRV_TOPSPEED(cpupm)); 1035 /* 1036 * We just changed the speed. Wait till at least next 1037 * call to this routine before proceeding ahead. 1038 */ 1039 CPUDRV_MONITOR_INIT(cpudsp); 1040 mutex_exit(&cpudsp->lock); 1041 goto do_return; 1042 } 1043 1044 mutex_enter(&cpu_lock); 1045 if (cpudsp->cp == NULL && 1046 (cpudsp->cp = cpu_get(cpudsp->cpu_id)) == NULL) { 1047 mutex_exit(&cpu_lock); 1048 CPUDRV_MONITOR_INIT(cpudsp); 1049 mutex_exit(&cpudsp->lock); 1050 cmn_err(CE_WARN, "cpudrv_monitor: instance %d: can't get " 1051 "cpu_t", ddi_get_instance(dip)); 1052 goto do_return; 1053 } 1054 1055 if (!cpupm->pm_started) { 1056 cpupm->pm_started = B_TRUE; 1057 cpudrv_set_supp_freqs(cpudsp); 1058 } 1059 1060 get_cpu_mstate(cpudsp->cp, msnsecs); 1061 GET_CPU_MSTATE_CNT(CMS_IDLE, idle_cnt); 1062 GET_CPU_MSTATE_CNT(CMS_USER, user_cnt); 1063 GET_CPU_MSTATE_CNT(CMS_SYSTEM, system_cnt); 1064 1065 /* 1066 * We can't do anything when we have just switched to a state 1067 * because there is no valid timestamp. 1068 */ 1069 if (cpupm->lastquan_ticks == 0) { 1070 cpupm->lastquan_ticks = NSEC_TO_TICK(gethrtime()); 1071 mutex_exit(&cpu_lock); 1072 CPUDRV_MONITOR_INIT(cpudsp); 1073 mutex_exit(&cpudsp->lock); 1074 goto do_return; 1075 } 1076 1077 /* 1078 * Various watermarks are based on this routine being called back 1079 * exactly at the requested period. This is not guaranteed 1080 * because this routine is called from a taskq that is dispatched 1081 * from a timeout routine. Handle this by finding out how many 1082 * ticks have elapsed since the last call and adjusting 1083 * the idle_cnt based on the delay added to the requested period 1084 * by timeout and taskq. 1085 */ 1086 ticks = NSEC_TO_TICK(gethrtime()); 1087 tick_cnt = ticks - cpupm->lastquan_ticks; 1088 ASSERT(tick_cnt != 0); 1089 cpupm->lastquan_ticks = ticks; 1090 mutex_exit(&cpu_lock); 1091 /* 1092 * Time taken between recording the current counts and 1093 * arranging the next call of this routine is an error in our 1094 * calculation. We minimize the error by calling 1095 * CPUDRV_MONITOR_INIT() here instead of end of this routine. 1096 */ 1097 CPUDRV_MONITOR_INIT(cpudsp); 1098 DPRINTF(D_PM_MONITOR_VERBOSE, ("cpudrv_monitor: instance %d: " 1099 "idle count %d, user count %d, system count %d, pm_level %d, " 1100 "pm_busycnt %d\n", ddi_get_instance(dip), idle_cnt, user_cnt, 1101 system_cnt, cur_spd->pm_level, cpupm->pm_busycnt)); 1102 1103 #ifdef DEBUG 1104 /* 1105 * Notify that timeout and taskq has caused delays and we need to 1106 * scale our parameters accordingly. 1107 * 1108 * To get accurate result, don't turn on other DPRINTFs with 1109 * the following DPRINTF. PROM calls generated by other 1110 * DPRINTFs changes the timing. 1111 */ 1112 if (tick_cnt > cur_spd->quant_cnt) { 1113 DPRINTF(D_PM_MONITOR_DELAY, ("cpudrv_monitor: instance %d: " 1114 "tick count %d > quantum_count %u\n", 1115 ddi_get_instance(dip), tick_cnt, cur_spd->quant_cnt)); 1116 } 1117 #endif /* DEBUG */ 1118 1119 /* 1120 * Adjust counts based on the delay added by timeout and taskq. 1121 */ 1122 idle_cnt = (idle_cnt * cur_spd->quant_cnt) / tick_cnt; 1123 user_cnt = (user_cnt * cur_spd->quant_cnt) / tick_cnt; 1124 1125 if ((user_cnt > cur_spd->user_hwm) || (idle_cnt < cur_spd->idle_lwm && 1126 cur_spd->idle_blwm_cnt >= cpudrv_idle_blwm_cnt_max)) { 1127 cur_spd->idle_blwm_cnt = 0; 1128 cur_spd->idle_bhwm_cnt = 0; 1129 /* 1130 * In normal situation, arrange to go to next higher speed. 1131 * If we are running in special direct pm mode, we just stay 1132 * at the current speed. 1133 */ 1134 if (cur_spd == cur_spd->up_spd || cpudrv_direct_pm) { 1135 CPUDRV_MONITOR_PM_BUSY_COMP(dip, cpupm); 1136 } else { 1137 new_spd = cur_spd->up_spd; 1138 CPUDRV_MONITOR_PM_BUSY_AND_RAISE(dip, cpudsp, cpupm, 1139 new_spd); 1140 } 1141 } else if ((user_cnt <= cur_spd->user_lwm) && 1142 (idle_cnt >= cur_spd->idle_hwm) || !CPU_ACTIVE(cpudsp->cp)) { 1143 cur_spd->idle_blwm_cnt = 0; 1144 cur_spd->idle_bhwm_cnt = 0; 1145 /* 1146 * Arrange to go to next lower speed by informing our idle 1147 * status to the power management framework. 1148 */ 1149 CPUDRV_MONITOR_PM_IDLE_COMP(dip, cpupm); 1150 } else { 1151 /* 1152 * If we are between the idle water marks and have not 1153 * been here enough consecutive times to be considered 1154 * busy, just increment the count and return. 1155 */ 1156 if ((idle_cnt < cur_spd->idle_hwm) && 1157 (idle_cnt >= cur_spd->idle_lwm) && 1158 (cur_spd->idle_bhwm_cnt < cpudrv_idle_bhwm_cnt_max)) { 1159 cur_spd->idle_blwm_cnt = 0; 1160 cur_spd->idle_bhwm_cnt++; 1161 mutex_exit(&cpudsp->lock); 1162 goto do_return; 1163 } 1164 if (idle_cnt < cur_spd->idle_lwm) { 1165 cur_spd->idle_blwm_cnt++; 1166 cur_spd->idle_bhwm_cnt = 0; 1167 } 1168 /* 1169 * Arranges to stay at the current speed. 1170 */ 1171 CPUDRV_MONITOR_PM_BUSY_COMP(dip, cpupm); 1172 } 1173 mutex_exit(&cpudsp->lock); 1174 do_return: 1175 mutex_enter(&cpupm->timeout_lock); 1176 ASSERT(cpupm->timeout_count > 0); 1177 cpupm->timeout_count--; 1178 cv_signal(&cpupm->timeout_cv); 1179 mutex_exit(&cpupm->timeout_lock); 1180 } 1181