1/* 2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29//#undef IOASSERT 30//#define IOASSERT 1 31 32#include <IOKit/assert.h> 33#include <IOKit/IOKitDebug.h> 34#include <IOKit/IOLib.h> 35#include <IOKit/IOMessage.h> 36#include <IOKit/IOPlatformExpert.h> 37#include <IOKit/IOService.h> 38#include <IOKit/IOEventSource.h> 39#include <IOKit/IOWorkLoop.h> 40#include <IOKit/IOCommand.h> 41#include <IOKit/IOTimeStamp.h> 42 43#include <IOKit/pwr_mgt/IOPMlog.h> 44#include <IOKit/pwr_mgt/IOPMinformee.h> 45#include <IOKit/pwr_mgt/IOPMinformeeList.h> 46#include <IOKit/pwr_mgt/IOPowerConnection.h> 47#include <IOKit/pwr_mgt/RootDomain.h> 48#include <IOKit/pwr_mgt/IOPMPrivate.h> 49 50#include <sys/proc.h> 51#include <sys/proc_internal.h> 52#include <libkern/OSDebug.h> 53 54// Required for notification instrumentation 55#include "IOServicePrivate.h" 56#include "IOServicePMPrivate.h" 57#include "IOKitKernelInternal.h" 58 59static void settle_timer_expired(thread_call_param_t, thread_call_param_t); 60static void idle_timer_expired(thread_call_param_t, thread_call_param_t); 61static void tellKernelClientApplier(OSObject * object, void * arg); 62static void tellAppClientApplier(OSObject * object, void * arg); 63 64static uint64_t computeTimeDeltaNS( const AbsoluteTime * start ) 65{ 66 AbsoluteTime now; 67 uint64_t nsec; 68 69 clock_get_uptime(&now); 70 SUB_ABSOLUTETIME(&now, start); 71 absolutetime_to_nanoseconds(now, &nsec); 72 return nsec; 73} 74 75#if PM_VARS_SUPPORT 76OSDefineMetaClassAndStructors(IOPMprot, OSObject) 77#endif 78 79// Container class for recording system power events 80OSDefineMetaClassAndStructors( PMEventDetails, OSObject ); 81 82//****************************************************************************** 83// Globals 84//****************************************************************************** 85 86static bool gIOPMInitialized = false; 87static uint32_t gIOPMBusyCount = 0; 88static uint32_t gIOPMWorkCount = 0; 89static IOWorkLoop * gIOPMWorkLoop = 0; 90static IOPMRequestQueue * gIOPMRequestQueue = 0; 91static IOPMRequestQueue * gIOPMReplyQueue = 0; 92static IOPMWorkQueue * gIOPMWorkQueue = 0; 93static IOPMCompletionQueue * gIOPMFreeQueue = 0; 94static IOPMRequest * gIOPMRequest = 0; 95static IOService * gIOPMRootNode = 0; 96static IOPlatformExpert * gPlatform = 0; 97 98static const OSSymbol * gIOPMPowerClientDevice = 0; 99static const OSSymbol * gIOPMPowerClientDriver = 0; 100static const OSSymbol * gIOPMPowerClientChildProxy = 0; 101static const OSSymbol * gIOPMPowerClientChildren = 0; 102 103static const OSSymbol * gIOPMPowerClientAdvisoryTickle = 0; 104static bool gIOPMAdvisoryTickleEnabled = true; 105 106static uint32_t getPMRequestType( void ) 107{ 108 uint32_t type = kIOPMRequestTypeInvalid; 109 if (gIOPMRequest) 110 type = gIOPMRequest->getType(); 111 return type; 112} 113 114//****************************************************************************** 115// Macros 116//****************************************************************************** 117 118#define PM_ERROR(x...) do { kprintf(x); IOLog(x); } while (false) 119#define PM_LOG(x...) do { kprintf(x); } while (false) 120 121#define PM_LOG1(x...) do { \ 122 if (kIOLogDebugPower & gIOKitDebug) \ 123 kprintf(x); } while (false) 124 125#define PM_LOG2(x...) do { \ 126 if (kIOLogDebugPower & gIOKitDebug) \ 127 kprintf(x); } while (false) 128 129#if 0 130#define PM_LOG3(x...) do { kprintf(x); } while (false) 131#else 132#define PM_LOG3(x...) 133#endif 134 135#define RD_LOG(x...) do { \ 136 if ((kIOLogPMRootDomain & gIOKitDebug) && \ 137 (getPMRootDomain() == this)) \ 138 kprintf("PMRD: " x); } while (false) 139 140#define PM_ASSERT_IN_GATE(x) \ 141do { \ 142 assert(gIOPMWorkLoop->inGate()); \ 143} while(false) 144 145#define PM_LOCK() IOLockLock(fPMLock) 146#define PM_UNLOCK() IOLockUnlock(fPMLock) 147#define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT) 148#define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false) 149 150#define ns_per_us 1000 151#define k30Seconds (30*1000000) 152#define kMinAckTimeoutTicks (10*1000000) 153#define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState" 154#define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange" 155#define kPwrMgtKey "IOPowerManagement" 156 157#define OUR_PMLog(t, a, b) do { \ 158 if (gIOKitDebug & kIOLogPower) \ 159 pwrMgt->pmPrint(t, a, b); \ 160 if (gIOKitTrace & kIOTracePowerMgmt) \ 161 pwrMgt->pmTrace(t, a, b); \ 162 } while(0) 163 164#define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL)) 165#define NS_TO_US(nsec) ((int)((nsec) / 1000ULL)) 166 167#if CONFIG_EMBEDDED 168#define SUPPORT_IDLE_CANCEL 1 169#endif 170 171#define kIOPMPowerStateMax 0xFFFFFFFF 172#define kInvalidTicklePowerState (-1) 173 174#define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL) 175 176#define IS_PM_ROOT (this == gIOPMRootNode) 177#define IS_ROOT_DOMAIN (getPMRootDomain() == this) 178#define IS_POWER_DROP (fHeadNotePowerState < fCurrentPowerState) 179#define IS_POWER_RISE (fHeadNotePowerState > fCurrentPowerState) 180 181// log setPowerStates longer than (ns): 182#define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL) 183// log app responses longer than (ns): 184#define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL) 185// use message tracer to log messages longer than (ns): 186#define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL) 187 188enum { 189 kReserveDomainPower = 1 190}; 191 192#define MS_PUSH(n) \ 193 do { assert(kIOPM_BadMachineState == fSavedMachineState); \ 194 assert(kIOPM_BadMachineState != n); \ 195 fSavedMachineState = n; } while (false) 196 197#define MS_POP() \ 198 do { assert(kIOPM_BadMachineState != fSavedMachineState); \ 199 fMachineState = fSavedMachineState; \ 200 fSavedMachineState = kIOPM_BadMachineState; } while (false) 201 202#define PM_ACTION_0(a) \ 203 do { if (fPMActions.a) { \ 204 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \ 205 } while (false) 206 207#define PM_ACTION_2(a, x, y) \ 208 do { if (fPMActions.a) { \ 209 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y); } \ 210 } while (false) 211 212static OSNumber * copyClientIDForNotification( 213 OSObject *object, 214 IOPMInterestContext *context); 215 216static void logClientIDForNotification( 217 OSObject *object, 218 IOPMInterestContext *context, 219 const char *logString); 220 221//********************************************************************************* 222// PM machine states 223// 224// Check kgmacros after modifying machine states. 225//********************************************************************************* 226 227enum { 228 kIOPM_Finished = 0, 229 230 kIOPM_OurChangeTellClientsPowerDown = 1, 231 kIOPM_OurChangeTellPriorityClientsPowerDown = 2, 232 kIOPM_OurChangeNotifyInterestedDriversWillChange = 3, 233 kIOPM_OurChangeSetPowerState = 4, 234 kIOPM_OurChangeWaitForPowerSettle = 5, 235 kIOPM_OurChangeNotifyInterestedDriversDidChange = 6, 236 kIOPM_OurChangeTellCapabilityDidChange = 7, 237 kIOPM_OurChangeFinish = 8, 238 239 kIOPM_ParentChangeTellPriorityClientsPowerDown = 10, 240 kIOPM_ParentChangeNotifyInterestedDriversWillChange = 11, 241 kIOPM_ParentChangeSetPowerState = 12, 242 kIOPM_ParentChangeWaitForPowerSettle = 13, 243 kIOPM_ParentChangeNotifyInterestedDriversDidChange = 14, 244 kIOPM_ParentChangeTellCapabilityDidChange = 15, 245 kIOPM_ParentChangeAcknowledgePowerChange = 16, 246 247 kIOPM_NotifyChildrenStart = 17, 248 kIOPM_NotifyChildrenOrdered = 18, 249 kIOPM_NotifyChildrenDelayed = 19, 250 kIOPM_SyncTellClientsPowerDown = 20, 251 kIOPM_SyncTellPriorityClientsPowerDown = 21, 252 kIOPM_SyncNotifyWillChange = 22, 253 kIOPM_SyncNotifyDidChange = 23, 254 kIOPM_SyncTellCapabilityDidChange = 24, 255 kIOPM_SyncFinish = 25, 256 kIOPM_TellCapabilityChangeDone = 26, 257 kIOPM_DriverThreadCallDone = 27, 258 259 kIOPM_BadMachineState = 0xFFFFFFFF 260}; 261 262 263 /* 264 Power Management defines a few roles that drivers can play in their own, 265 and other drivers', power management. We briefly define those here. 266 267 Many drivers implement their policy maker and power controller within the same 268 IOService object, but that is not required. 269 270== Policy Maker == 271 * Virtual IOService PM methods a "policy maker" may implement 272 * maxCapabilityForDomainState() 273 * initialPowerStateForDomainState() 274 * powerStateForDomainState() 275 276 * Virtual IOService PM methods a "policy maker" may CALL 277 * PMinit() 278 279== Power Controller == 280 * Virtual IOService PM methods a "power controller" may implement 281 * setPowerState() 282 283 * Virtual IOService PM methods a "power controller" may CALL 284 * joinPMtree() 285 * registerPowerDriver() 286 287======================= 288 There are two different kinds of power state changes. 289 * One is initiated by a subclassed device object which has either decided 290 to change power state, or its controlling driver has suggested it, or 291 some other driver wants to use the idle device and has asked it to become 292 usable. 293 * The second kind of power state change is initiated by the power domain 294 parent. 295 The two are handled through different code paths. 296 297 We maintain a queue of "change notifications," or change notes. 298 * Usually the queue is empty. 299 * When it isn't, usually there is one change note in it 300 * It's possible to have more than one power state change pending at one 301 time, so a queue is implemented. 302 Example: 303 * The subclass device decides it's idle and initiates a change to a lower 304 power state. This causes interested parties to be notified, but they 305 don't all acknowledge right away. This causes the change note to sit 306 in the queue until all the acks are received. During this time, the 307 device decides it isn't idle anymore and wants to raise power back up 308 again. This change can't be started, however, because the previous one 309 isn't complete yet, so the second one waits in the queue. During this 310 time, the parent decides to lower or raise the power state of the entire 311 power domain and notifies the device, and that notification goes into 312 the queue, too, and can't be actioned until the others are. 313 314 == SelfInitiated == 315 This is how a power change initiated by the subclass device is handled: 316 -> First, all interested parties are notified of the change via their 317 powerStateWillChangeTo method. If they all don't acknowledge via return 318 code, then we have to wait. If they do, or when they finally all 319 acknowledge via our acknowledgePowerChange method, then we can continue. 320 -> We call the controlling driver, instructing it to change to the new state 321 -> Then we wait for power to settle. If there is no settling-time, or after 322 it has passed, 323 -> we notify interested parties again, this time via their 324 powerStateDidChangeTo methods. 325 -> When they have all acked, we're done. 326 If we lowered power and don't need the power domain to be in its current power 327 state, we suggest to the parent that it lower the power domain state. 328 329 == PowerDomainDownInitiated == 330How a change to a lower power domain state initiated by the parent is handled: 331 -> First, we figure out what power state we will be in when the new domain 332 state is reached. 333 -> Then all interested parties are notified that we are moving to that new 334 state. 335 -> When they have acknowledged, we call the controlling driver to assume 336 that state and we wait for power to settle. 337 -> Then we acknowledge our preparedness to our parent. When all its 338 interested parties have acknowledged, 339 -> it lowers power and then notifies its interested parties again. 340 -> When we get this call, we notify our interested parties that the power 341 state has changed, and when they have all acknowledged, we're done. 342 343 == PowerDomainUpInitiated == 344How a change to a higher power domain state initiated by the parent is handled: 345 -> We figure out what power state we will be in when the new domain state is 346 reached. 347 -> If it is different from our current state we acknowledge the parent. 348 -> When all the parent's interested parties have acknowledged, it raises 349 power in the domain and waits for power to settle. 350 -> Then it notifies everyone that the new state has been reached. 351 -> When we get this call, we call the controlling driver, instructing it to 352 assume the new state, and wait for power to settle. 353 -> Then we notify our interested parties. When they all acknowledge we are 354 done. 355 356 In either of the two power domain state cases above, it is possible that we 357 will not be changing state even though the domain is. 358 Examples: 359 * A change to a lower domain state may not affect us because we are already 360 in a low enough state, 361 * We will not take advantage of a change to a higher domain state, because 362 we have no need of the higher power. In such cases, there is nothing to 363 do but acknowledge the parent. So when the parent calls our 364 powerDomainWillChange method, and we decide that we will not be changing 365 state, we merely acknowledge the parent, via return code, and wait. 366 When the parent subsequently calls powerStateDidChange, we acknowledge again 367 via return code, and the change is complete. 368 369 == 4 Paths Through State Machine == 370 Power state changes are processed in a state machine, and since there are four 371 varieties of power state changes, there are four major paths through the state 372 machine. 373 374 == 5. No Need To change == 375 The fourth is nearly trivial. In this path, the parent is changing the domain 376 state, but we are not changing the device state. The change starts when the 377 parent calls powerDomainWillChange. All we do is acknowledge the parent. When 378 the parent calls powerStateDidChange, we acknowledge the parent again, and 379 we're done. 380 381 == 1. OurChange Down == XXX gvdl 382 The first is fairly simple. It starts: 383 * when a power domain child calls requestPowerDomainState and we decide to 384 change power states to accomodate the child, 385 * or if our power-controlling driver calls changePowerStateTo, 386 * or if some other driver which is using our device calls makeUsable, 387 * or if a subclassed object calls changePowerStateToPriv. 388 These are all power changes initiated by us, not forced upon us by the parent. 389 390 -> We start by notifying interested parties. 391 -> If they all acknowledge via return code, we can go on to state 392 "msSetPowerState". 393 -> Otherwise, we start the ack timer and wait for the stragglers to 394 acknowlege by calling acknowledgePowerChange. 395 -> We move on to state "msSetPowerState" when all the 396 stragglers have acknowledged, or when the ack timer expires on 397 all those which didn't acknowledge. 398 In "msSetPowerState" we call the power-controlling driver to change the 399 power state of the hardware. 400 -> If it returns saying it has done so, we go on to state 401 "msWaitForPowerSettle". 402 -> Otherwise, we have to wait for it, so we set the ack timer and wait. 403 -> When it calls acknowledgeSetPowerState, or when the ack timer 404 expires, we go on. 405 In "msWaitForPowerSettle", we look in the power state array to see if 406 there is any settle time required when changing from our current state to the 407 new state. 408 -> If not, we go right away to "msNotifyInterestedDriversDidChange". 409 -> Otherwise, we set the settle timer and wait. When it expires, we move on. 410 In "msNotifyInterestedDriversDidChange" state, we notify all our 411 interested parties via their powerStateDidChange methods that we have finished 412 changing power state. 413 -> If they all acknowledge via return code, we move on to "msFinish". 414 -> Otherwise we set the ack timer and wait. When they have all 415 acknowledged, or when the ack timer has expired for those that didn't, 416 we move on to "msFinish". 417 In "msFinish" we remove the used change note from the head of the queue 418 and start the next one if one exists. 419 420 == 2. Parent Change Down == 421 Start at Stage 2 of OurChange Down XXX gvdl 422 423 == 3. Change Up == 424 Start at Stage 4 of OurChange Down XXX gvdl 425 426Note all parent requested changes need to acknowledge the power has changed to the parent when done. 427 */ 428 429//********************************************************************************* 430// [public] PMinit 431// 432// Initialize power management. 433//********************************************************************************* 434 435void IOService::PMinit ( void ) 436{ 437 if ( !initialized ) 438 { 439 if ( !gIOPMInitialized ) 440 { 441 gPlatform = getPlatform(); 442 gIOPMWorkLoop = IOWorkLoop::workLoop(); 443 if (gIOPMWorkLoop) 444 { 445 gIOPMRequestQueue = IOPMRequestQueue::create( 446 this, OSMemberFunctionCast(IOPMRequestQueue::Action, 447 this, &IOService::servicePMRequestQueue)); 448 449 gIOPMReplyQueue = IOPMRequestQueue::create( 450 this, OSMemberFunctionCast(IOPMRequestQueue::Action, 451 this, &IOService::servicePMReplyQueue)); 452 453 gIOPMWorkQueue = IOPMWorkQueue::create( 454 this, 455 OSMemberFunctionCast(IOPMWorkQueue::Action, this, 456 &IOService::servicePMRequest), 457 OSMemberFunctionCast(IOPMWorkQueue::Action, this, 458 &IOService::retirePMRequest)); 459 460 gIOPMFreeQueue = IOPMCompletionQueue::create( 461 this, OSMemberFunctionCast(IOPMCompletionQueue::Action, 462 this, &IOService::servicePMFreeQueue)); 463 464 if (gIOPMWorkLoop->addEventSource(gIOPMRequestQueue) != 465 kIOReturnSuccess) 466 { 467 gIOPMRequestQueue->release(); 468 gIOPMRequestQueue = 0; 469 } 470 471 if (gIOPMWorkLoop->addEventSource(gIOPMReplyQueue) != 472 kIOReturnSuccess) 473 { 474 gIOPMReplyQueue->release(); 475 gIOPMReplyQueue = 0; 476 } 477 478 if (gIOPMWorkLoop->addEventSource(gIOPMWorkQueue) != 479 kIOReturnSuccess) 480 { 481 gIOPMWorkQueue->release(); 482 gIOPMWorkQueue = 0; 483 } 484 485 if (gIOPMWorkLoop->addEventSource(gIOPMFreeQueue) != 486 kIOReturnSuccess) 487 { 488 gIOPMFreeQueue->release(); 489 gIOPMFreeQueue = 0; 490 } 491 492 gIOPMPowerClientDevice = 493 OSSymbol::withCStringNoCopy( "DevicePowerState" ); 494 495 gIOPMPowerClientDriver = 496 OSSymbol::withCStringNoCopy( "DriverPowerState" ); 497 498 gIOPMPowerClientChildProxy = 499 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" ); 500 501 gIOPMPowerClientChildren = 502 OSSymbol::withCStringNoCopy( "ChildrenPowerState" ); 503 504 gIOPMPowerClientAdvisoryTickle = 505 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" ); 506 } 507 508 if (gIOPMRequestQueue && gIOPMReplyQueue && gIOPMFreeQueue) 509 gIOPMInitialized = true; 510 } 511 if (!gIOPMInitialized) 512 return; 513 514 pwrMgt = new IOServicePM; 515 pwrMgt->init(); 516 setProperty(kPwrMgtKey, pwrMgt); 517 518 queue_init(&pwrMgt->WorkChain); 519 queue_init(&pwrMgt->RequestHead); 520 queue_init(&pwrMgt->PMDriverCallQueue); 521 522 fOwner = this; 523 fPMLock = IOLockAlloc(); 524 fInterestedDrivers = new IOPMinformeeList; 525 fInterestedDrivers->initialize(); 526 fDesiredPowerState = 0; 527 fDeviceDesire = 0; 528 fInitialPowerChange = true; 529 fInitialSetPowerState = true; 530 fPreviousRequestPowerFlags = 0; 531 fDeviceOverrideEnabled = false; 532 fMachineState = kIOPM_Finished; 533 fSavedMachineState = kIOPM_BadMachineState; 534 fIdleTimerMinPowerState = 0; 535 fActivityLock = IOLockAlloc(); 536 fStrictTreeOrder = false; 537 fActivityTicklePowerState = kInvalidTicklePowerState; 538 fAdvisoryTicklePowerState = kInvalidTicklePowerState; 539 fControllingDriver = NULL; 540 fPowerStates = NULL; 541 fNumberOfPowerStates = 0; 542 fCurrentPowerState = 0; 543 fParentsCurrentPowerFlags = 0; 544 fMaxPowerState = 0; 545 fName = getName(); 546 fParentsKnowState = false; 547 fSerialNumber = 0; 548 fResponseArray = NULL; 549 fNotifyClientArray = NULL; 550 fCurrentPowerConsumption = kIOPMUnknown; 551 fOverrideMaxPowerState = kIOPMPowerStateMax; 552 553 if (!gIOPMRootNode && (getParentEntry(gIOPowerPlane) == getRegistryRoot())) 554 { 555 gIOPMRootNode = this; 556 fParentsKnowState = true; 557 } 558 559 fAckTimer = thread_call_allocate( 560 &IOService::ack_timer_expired, (thread_call_param_t)this); 561 fSettleTimer = thread_call_allocate( 562 &settle_timer_expired, (thread_call_param_t)this); 563 fIdleTimer = thread_call_allocate( 564 &idle_timer_expired, (thread_call_param_t)this); 565 fDriverCallEntry = thread_call_allocate( 566 (thread_call_func_t) &IOService::pmDriverCallout, this); 567 assert(fDriverCallEntry); 568 569 // Check for powerChangeDone override. 570 if (OSMemberFunctionCast(void (*)(void), 571 getResourceService(), &IOService::powerChangeDone) != 572 OSMemberFunctionCast(void (*)(void), 573 this, &IOService::powerChangeDone)) 574 { 575 fPCDFunctionOverride = true; 576 } 577 578#if PM_VARS_SUPPORT 579 IOPMprot * prot = new IOPMprot; 580 if (prot) 581 { 582 prot->init(); 583 prot->ourName = fName; 584 prot->thePlatform = gPlatform; 585 fPMVars = prot; 586 pm_vars = prot; 587 } 588#else 589 pm_vars = (void *) (uintptr_t) true; 590#endif 591 592 initialized = true; 593 } 594} 595 596//********************************************************************************* 597// [private] PMfree 598// 599// Free the data created by PMinit. Only called from IOService::free(). 600//********************************************************************************* 601 602void IOService::PMfree ( void ) 603{ 604 initialized = false; 605 pm_vars = 0; 606 607 if ( pwrMgt ) 608 { 609 assert(fMachineState == kIOPM_Finished); 610 assert(fInsertInterestSet == NULL); 611 assert(fRemoveInterestSet == NULL); 612 assert(fNotifyChildArray == NULL); 613 assert(queue_empty(&pwrMgt->RequestHead)); 614 assert(queue_empty(&fPMDriverCallQueue)); 615 616 if ( fSettleTimer ) { 617 thread_call_cancel(fSettleTimer); 618 thread_call_free(fSettleTimer); 619 fSettleTimer = NULL; 620 } 621 if ( fAckTimer ) { 622 thread_call_cancel(fAckTimer); 623 thread_call_free(fAckTimer); 624 fAckTimer = NULL; 625 } 626 if ( fIdleTimer ) { 627 thread_call_cancel(fIdleTimer); 628 thread_call_free(fIdleTimer); 629 fIdleTimer = NULL; 630 } 631 if ( fDriverCallEntry ) { 632 thread_call_free(fDriverCallEntry); 633 fDriverCallEntry = NULL; 634 } 635 if ( fPMLock ) { 636 IOLockFree(fPMLock); 637 fPMLock = NULL; 638 } 639 if ( fActivityLock ) { 640 IOLockFree(fActivityLock); 641 fActivityLock = NULL; 642 } 643 if ( fInterestedDrivers ) { 644 fInterestedDrivers->release(); 645 fInterestedDrivers = NULL; 646 } 647 if (fDriverCallParamSlots && fDriverCallParamPtr) { 648 IODelete(fDriverCallParamPtr, DriverCallParam, fDriverCallParamSlots); 649 fDriverCallParamPtr = 0; 650 fDriverCallParamSlots = 0; 651 } 652 if ( fResponseArray ) { 653 fResponseArray->release(); 654 fResponseArray = NULL; 655 } 656 if ( fNotifyClientArray ) { 657 fNotifyClientArray->release(); 658 fNotifyClientArray = NULL; 659 } 660 if (fPowerStates && fNumberOfPowerStates) { 661 IODelete(fPowerStates, IOPMPSEntry, fNumberOfPowerStates); 662 fNumberOfPowerStates = 0; 663 fPowerStates = NULL; 664 } 665 if (fPowerClients) { 666 fPowerClients->release(); 667 fPowerClients = 0; 668 } 669 670#if PM_VARS_SUPPORT 671 if (fPMVars) 672 { 673 fPMVars->release(); 674 fPMVars = 0; 675 } 676#endif 677 678 pwrMgt->release(); 679 pwrMgt = 0; 680 } 681} 682 683void IOService::PMDebug( uint32_t event, uintptr_t param1, uintptr_t param2 ) 684{ 685 OUR_PMLog(event, param1, param2); 686} 687 688//********************************************************************************* 689// [public] joinPMtree 690// 691// A policy-maker calls its nub here when initializing, to be attached into 692// the power management hierarchy. The default function is to call the 693// platform expert, which knows how to do it. This method is overridden 694// by a nub subclass which may either know how to do it, or may need to 695// take other action. 696// 697// This may be the only "power management" method used in a nub, 698// meaning it may not be initialized for power management. 699//********************************************************************************* 700 701void IOService::joinPMtree ( IOService * driver ) 702{ 703 IOPlatformExpert * platform; 704 705 platform = getPlatform(); 706 assert(platform != 0); 707 platform->PMRegisterDevice(this, driver); 708} 709 710#ifndef __LP64__ 711//********************************************************************************* 712// [deprecated] youAreRoot 713// 714// Power Managment is informing us that we are the root power domain. 715//********************************************************************************* 716 717IOReturn IOService::youAreRoot ( void ) 718{ 719 return IOPMNoErr; 720} 721#endif /* !__LP64__ */ 722 723//********************************************************************************* 724// [public] PMstop 725// 726// Immediately stop driver callouts. Schedule an async stop request to detach 727// from power plane. 728//********************************************************************************* 729 730void IOService::PMstop ( void ) 731{ 732 IOPMRequest * request; 733 734 if (!initialized) 735 return; 736 737 PM_LOCK(); 738 739 if (fLockedFlags.PMStop) 740 { 741 PM_LOG2("%s: PMstop() already stopped\n", fName); 742 PM_UNLOCK(); 743 return; 744 } 745 746 // Inhibit future driver calls. 747 fLockedFlags.PMStop = true; 748 749 // Wait for all prior driver calls to finish. 750 waitForPMDriverCall(); 751 752 PM_UNLOCK(); 753 754 // The rest of the work is performed async. 755 request = acquirePMRequest( this, kIOPMRequestTypePMStop ); 756 if (request) 757 { 758 PM_LOG2("%s: %p PMstop\n", getName(), this); 759 submitPMRequest( request ); 760 } 761} 762 763//********************************************************************************* 764// [private] handlePMstop 765// 766// Disconnect the node from all parents and children in the power plane. 767//********************************************************************************* 768 769void IOService::handlePMstop ( IOPMRequest * request ) 770{ 771 OSIterator * iter; 772 OSObject * next; 773 IOPowerConnection * connection; 774 IOService * theChild; 775 IOService * theParent; 776 777 PM_ASSERT_IN_GATE(); 778 PM_LOG2("%s: %p %s start\n", getName(), this, __FUNCTION__); 779 780 // remove driver from prevent system sleep lists 781 getPMRootDomain()->updatePreventIdleSleepList(this, false); 782 getPMRootDomain()->updatePreventSystemSleepList(this, false); 783 784 // remove the property 785 removeProperty(kPwrMgtKey); 786 787 // detach parents 788 iter = getParentIterator(gIOPowerPlane); 789 if ( iter ) 790 { 791 while ( (next = iter->getNextObject()) ) 792 { 793 if ( (connection = OSDynamicCast(IOPowerConnection, next)) ) 794 { 795 theParent = (IOService *)connection->copyParentEntry(gIOPowerPlane); 796 if ( theParent ) 797 { 798 theParent->removePowerChild(connection); 799 theParent->release(); 800 } 801 } 802 } 803 iter->release(); 804 } 805 806 // detach IOConnections 807 detachAbove( gIOPowerPlane ); 808 809 // no more power state changes 810 fParentsKnowState = false; 811 812 // detach children 813 iter = getChildIterator(gIOPowerPlane); 814 if ( iter ) 815 { 816 while ( (next = iter->getNextObject()) ) 817 { 818 if ( (connection = OSDynamicCast(IOPowerConnection, next)) ) 819 { 820 theChild = ((IOService *)(connection->copyChildEntry(gIOPowerPlane))); 821 if ( theChild ) 822 { 823 // detach nub from child 824 connection->detachFromChild(theChild, gIOPowerPlane); 825 theChild->release(); 826 } 827 // detach us from nub 828 detachFromChild(connection, gIOPowerPlane); 829 } 830 } 831 iter->release(); 832 } 833 834 // Remove all interested drivers from the list, including the power 835 // controlling driver. 836 // 837 // Usually, the controlling driver and the policy-maker functionality 838 // are implemented by the same object, and without the deregistration, 839 // the object will be holding an extra retain on itself, and cannot 840 // be freed. 841 842 if ( fInterestedDrivers ) 843 { 844 IOPMinformeeList * list = fInterestedDrivers; 845 IOPMinformee * item; 846 847 PM_LOCK(); 848 while ((item = list->firstInList())) 849 { 850 list->removeFromList(item->whatObject); 851 } 852 PM_UNLOCK(); 853 } 854 855 // Tell idleTimerExpired() to ignore idle timer. 856 fIdleTimerPeriod = 0; 857 if (fIdleTimer && thread_call_cancel(fIdleTimer)) 858 release(); 859 860 PM_LOG2("%s: %p %s done\n", getName(), this, __FUNCTION__); 861} 862 863//********************************************************************************* 864// [public] addPowerChild 865// 866// Power Management is informing us who our children are. 867//********************************************************************************* 868 869IOReturn IOService::addPowerChild ( IOService * child ) 870{ 871 IOPowerConnection * connection = 0; 872 IOPMRequest * requests[3] = {0, 0, 0}; 873 OSIterator * iter; 874 bool ok = true; 875 876 if (!child) 877 return kIOReturnBadArgument; 878 879 if (!initialized || !child->initialized) 880 return IOPMNotYetInitialized; 881 882 OUR_PMLog( kPMLogAddChild, (uintptr_t) child, 0 ); 883 884 do { 885 // Is this child already one of our children? 886 887 iter = child->getParentIterator( gIOPowerPlane ); 888 if ( iter ) 889 { 890 IORegistryEntry * entry; 891 OSObject * next; 892 893 while ((next = iter->getNextObject())) 894 { 895 if ((entry = OSDynamicCast(IORegistryEntry, next)) && 896 isChild(entry, gIOPowerPlane)) 897 { 898 ok = false; 899 break; 900 } 901 } 902 iter->release(); 903 } 904 if (!ok) 905 { 906 PM_LOG("%s: %s (%p) is already a child\n", 907 getName(), child->getName(), child); 908 break; 909 } 910 911 // Add the child to the power plane immediately, but the 912 // joining connection is marked as not ready. 913 // We want the child to appear in the power plane before 914 // returning to the caller, but don't want the caller to 915 // block on the PM work loop. 916 917 connection = new IOPowerConnection; 918 if (!connection) 919 break; 920 921 // Create a chain of PM requests to perform the bottom-half 922 // work from the PM work loop. 923 924 requests[0] = acquirePMRequest( 925 /* target */ this, 926 /* type */ kIOPMRequestTypeAddPowerChild1 ); 927 928 requests[1] = acquirePMRequest( 929 /* target */ child, 930 /* type */ kIOPMRequestTypeAddPowerChild2 ); 931 932 requests[2] = acquirePMRequest( 933 /* target */ this, 934 /* type */ kIOPMRequestTypeAddPowerChild3 ); 935 936 if (!requests[0] || !requests[1] || !requests[2]) 937 break; 938 939 requests[0]->attachNextRequest( requests[1] ); 940 requests[1]->attachNextRequest( requests[2] ); 941 942 connection->init(); 943 connection->start(this); 944 connection->setAwaitingAck(false); 945 connection->setReadyFlag(false); 946 947 attachToChild( connection, gIOPowerPlane ); 948 connection->attachToChild( child, gIOPowerPlane ); 949 950 // connection needs to be released 951 requests[0]->fArg0 = connection; 952 requests[1]->fArg0 = connection; 953 requests[2]->fArg0 = connection; 954 955 submitPMRequest( requests, 3 ); 956 return kIOReturnSuccess; 957 } 958 while (false); 959 960 if (connection) connection->release(); 961 if (requests[0]) releasePMRequest(requests[0]); 962 if (requests[1]) releasePMRequest(requests[1]); 963 if (requests[2]) releasePMRequest(requests[2]); 964 965 // Silent failure, to prevent platform drivers from adding the child 966 // to the root domain. 967 968 return kIOReturnSuccess; 969} 970 971//********************************************************************************* 972// [private] addPowerChild1 973// 974// Step 1/3 of adding a power child. Called on the power parent. 975//********************************************************************************* 976 977void IOService::addPowerChild1 ( IOPMRequest * request ) 978{ 979 unsigned long tempDesire = 0; 980 981 // Make us temporary usable before adding the child. 982 983 PM_ASSERT_IN_GATE(); 984 OUR_PMLog( kPMLogMakeUsable, kPMLogMakeUsable, 0 ); 985 986 if (fControllingDriver && inPlane(gIOPowerPlane) && fParentsKnowState) 987 { 988 tempDesire = fNumberOfPowerStates - 1; 989 } 990 991 if (tempDesire && (IS_PM_ROOT || (fMaxPowerState >= tempDesire))) 992 { 993 adjustPowerState(tempDesire); 994 } 995} 996 997//********************************************************************************* 998// [private] addPowerChild2 999// 1000// Step 2/3 of adding a power child. Called on the joining child. 1001// Execution blocked behind addPowerChild1. 1002//********************************************************************************* 1003 1004void IOService::addPowerChild2 ( IOPMRequest * request ) 1005{ 1006 IOPowerConnection * connection = (IOPowerConnection *) request->fArg0; 1007 IOService * parent; 1008 IOPMPowerFlags powerFlags; 1009 bool knowsState; 1010 unsigned long powerState; 1011 unsigned long tempDesire; 1012 1013 PM_ASSERT_IN_GATE(); 1014 parent = (IOService *) connection->getParentEntry(gIOPowerPlane); 1015 1016 if (!parent || !inPlane(gIOPowerPlane)) 1017 { 1018 PM_LOG("%s: addPowerChild2 not in power plane\n", getName()); 1019 return; 1020 } 1021 1022 // Parent will be waiting for us to complete this stage. 1023 // It is safe to directly access parent's vars. 1024 1025 knowsState = (parent->fPowerStates) && (parent->fParentsKnowState); 1026 powerState = parent->fCurrentPowerState; 1027 1028 if (knowsState) 1029 powerFlags = parent->fPowerStates[powerState].outputPowerFlags; 1030 else 1031 powerFlags = 0; 1032 1033 // Set our power parent. 1034 1035 OUR_PMLog(kPMLogSetParent, knowsState, powerFlags); 1036 1037 setParentInfo( powerFlags, connection, knowsState ); 1038 1039 connection->setReadyFlag(true); 1040 1041 if ( fControllingDriver && fParentsKnowState ) 1042 { 1043 fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fParentsCurrentPowerFlags); 1044 // initially change into the state we are already in 1045 tempDesire = fControllingDriver->initialPowerStateForDomainState(fParentsCurrentPowerFlags); 1046 fPreviousRequestPowerFlags = (IOPMPowerFlags)(-1); 1047 adjustPowerState(tempDesire); 1048 } 1049 1050 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions); 1051} 1052 1053//********************************************************************************* 1054// [private] addPowerChild3 1055// 1056// Step 3/3 of adding a power child. Called on the parent. 1057// Execution blocked behind addPowerChild2. 1058//********************************************************************************* 1059 1060void IOService::addPowerChild3 ( IOPMRequest * request ) 1061{ 1062 IOPowerConnection * connection = (IOPowerConnection *) request->fArg0; 1063 IOService * child; 1064 IOPMrootDomain * rootDomain = getPMRootDomain(); 1065 1066 PM_ASSERT_IN_GATE(); 1067 child = (IOService *) connection->getChildEntry(gIOPowerPlane); 1068 1069 if (child && inPlane(gIOPowerPlane)) 1070 { 1071 if ((this != rootDomain) && child->getProperty("IOPMStrictTreeOrder")) 1072 { 1073 PM_LOG1("%s: strict PM order enforced\n", getName()); 1074 fStrictTreeOrder = true; 1075 } 1076 1077 if (rootDomain) 1078 rootDomain->joinAggressiveness( child ); 1079 } 1080 else 1081 { 1082 PM_LOG("%s: addPowerChild3 not in power plane\n", getName()); 1083 } 1084 1085 connection->release(); 1086} 1087 1088#ifndef __LP64__ 1089//********************************************************************************* 1090// [deprecated] setPowerParent 1091// 1092// Power Management is informing us who our parent is. 1093// If we have a controlling driver, find out, given our newly-informed 1094// power domain state, what state it would be in, and then tell it 1095// to assume that state. 1096//********************************************************************************* 1097 1098IOReturn IOService::setPowerParent ( 1099 IOPowerConnection * theParent, bool stateKnown, IOPMPowerFlags powerFlags ) 1100{ 1101 return kIOReturnUnsupported; 1102} 1103#endif /* !__LP64__ */ 1104 1105//********************************************************************************* 1106// [public] removePowerChild 1107// 1108// Called on a parent whose child is being removed by PMstop(). 1109//********************************************************************************* 1110 1111IOReturn IOService::removePowerChild ( IOPowerConnection * theNub ) 1112{ 1113 IORegistryEntry * theChild; 1114 1115 PM_ASSERT_IN_GATE(); 1116 OUR_PMLog( kPMLogRemoveChild, 0, 0 ); 1117 1118 theNub->retain(); 1119 1120 // detach nub from child 1121 theChild = theNub->copyChildEntry(gIOPowerPlane); 1122 if ( theChild ) 1123 { 1124 theNub->detachFromChild(theChild, gIOPowerPlane); 1125 theChild->release(); 1126 } 1127 // detach from the nub 1128 detachFromChild(theNub, gIOPowerPlane); 1129 1130 // Are we awaiting an ack from this child? 1131 if ( theNub->getAwaitingAck() ) 1132 { 1133 // yes, pretend we got one 1134 theNub->setAwaitingAck(false); 1135 if (fHeadNotePendingAcks != 0 ) 1136 { 1137 // that's one fewer ack to worry about 1138 fHeadNotePendingAcks--; 1139 1140 // is that the last? 1141 if ( fHeadNotePendingAcks == 0 ) 1142 { 1143 stop_ack_timer(); 1144 1145 // Request unblocked, work queue 1146 // should re-scan all busy requests. 1147 gIOPMWorkQueue->incrementProducerCount(); 1148 } 1149 } 1150 } 1151 1152 theNub->release(); 1153 1154 // A child has gone away, re-scan children desires and clamp bits. 1155 // The fPendingAdjustPowerRequest helps to reduce redundant parent work. 1156 1157 if (!fAdjustPowerScheduled) 1158 { 1159 IOPMRequest * request; 1160 request = acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState ); 1161 if (request) 1162 { 1163 submitPMRequest( request ); 1164 fAdjustPowerScheduled = true; 1165 } 1166 } 1167 1168 return IOPMNoErr; 1169} 1170 1171//********************************************************************************* 1172// [public] registerPowerDriver 1173// 1174// A driver has called us volunteering to control power to our device. 1175//********************************************************************************* 1176 1177IOReturn IOService::registerPowerDriver ( 1178 IOService * powerDriver, 1179 IOPMPowerState * powerStates, 1180 unsigned long numberOfStates ) 1181{ 1182 IOPMRequest * request; 1183 IOPMPSEntry * powerStatesCopy = 0; 1184 1185 if (!initialized) 1186 return IOPMNotYetInitialized; 1187 1188 // Validate arguments. 1189 if (!powerStates || (numberOfStates < 2)) 1190 { 1191 OUR_PMLog(kPMLogControllingDriverErr5, numberOfStates, 0); 1192 return kIOReturnBadArgument; 1193 } 1194 1195 if (!powerDriver || !powerDriver->initialized) 1196 { 1197 OUR_PMLog(kPMLogControllingDriverErr4, 0, 0); 1198 return kIOReturnBadArgument; 1199 } 1200 1201 if (powerStates[0].version != kIOPMPowerStateVersion1) 1202 { 1203 OUR_PMLog(kPMLogControllingDriverErr1, powerStates[0].version, 0); 1204 return kIOReturnBadArgument; 1205 } 1206 1207 do { 1208 // Make a copy of the supplied power state array. 1209 powerStatesCopy = IONew(IOPMPSEntry, numberOfStates); 1210 if (!powerStatesCopy) 1211 break; 1212 1213 for (uint32_t i = 0; i < numberOfStates; i++) 1214 { 1215 powerStatesCopy[i].capabilityFlags = powerStates[i].capabilityFlags; 1216 powerStatesCopy[i].outputPowerFlags = powerStates[i].outputPowerCharacter; 1217 powerStatesCopy[i].inputPowerFlags = powerStates[i].inputPowerRequirement; 1218 powerStatesCopy[i].staticPower = powerStates[i].staticPower; 1219 powerStatesCopy[i].settleUpTime = powerStates[i].settleUpTime; 1220 powerStatesCopy[i].settleDownTime = powerStates[i].settleDownTime; 1221 } 1222 1223 request = acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver ); 1224 if (!request) 1225 break; 1226 1227 powerDriver->retain(); 1228 request->fArg0 = (void *) powerDriver; 1229 request->fArg1 = (void *) powerStatesCopy; 1230 request->fArg2 = (void *) numberOfStates; 1231 1232 submitPMRequest( request ); 1233 return kIOReturnSuccess; 1234 } 1235 while (false); 1236 1237 if (powerStatesCopy) 1238 IODelete(powerStatesCopy, IOPMPSEntry, numberOfStates); 1239 return kIOReturnNoMemory; 1240} 1241 1242//********************************************************************************* 1243// [private] handleRegisterPowerDriver 1244//********************************************************************************* 1245 1246void IOService::handleRegisterPowerDriver ( IOPMRequest * request ) 1247{ 1248 IOService * powerDriver = (IOService *) request->fArg0; 1249 IOPMPSEntry * powerStates = (IOPMPSEntry *) request->fArg1; 1250 unsigned long numberOfStates = (unsigned long) request->fArg2; 1251 unsigned long i; 1252 IOService * root; 1253 OSIterator * iter; 1254 1255 PM_ASSERT_IN_GATE(); 1256 assert(powerStates); 1257 assert(powerDriver); 1258 assert(numberOfStates > 1); 1259 1260 if ( !fNumberOfPowerStates ) 1261 { 1262 OUR_PMLog(kPMLogControllingDriver, 1263 (unsigned long) numberOfStates, 1264 (unsigned long) kIOPMPowerStateVersion1); 1265 1266 fPowerStates = powerStates; 1267 fNumberOfPowerStates = numberOfStates; 1268 fControllingDriver = powerDriver; 1269 fCurrentCapabilityFlags = fPowerStates[0].capabilityFlags; 1270 1271 // make a mask of all the character bits we know about 1272 fOutputPowerCharacterFlags = 0; 1273 for ( i = 0; i < numberOfStates; i++ ) { 1274 fOutputPowerCharacterFlags |= fPowerStates[i].outputPowerFlags; 1275 if (!fDeviceUsablePowerState && 1276 (fPowerStates[i].capabilityFlags & IOPMDeviceUsable)) 1277 { 1278 // The minimum power state that the device is usable 1279 fDeviceUsablePowerState = i; 1280 } 1281 } 1282 1283 // Register powerDriver as interested, unless already done. 1284 // We don't want to register the default implementation since 1285 // it does nothing. One ramification of not always registering 1286 // is the one fewer retain count held. 1287 1288 root = getPlatform()->getProvider(); 1289 assert(root); 1290 if (!root || 1291 ((OSMemberFunctionCast(void (*)(void), 1292 root, &IOService::powerStateDidChangeTo)) != 1293 ((OSMemberFunctionCast(void (*)(void), 1294 this, &IOService::powerStateDidChangeTo)))) || 1295 ((OSMemberFunctionCast(void (*)(void), 1296 root, &IOService::powerStateWillChangeTo)) != 1297 ((OSMemberFunctionCast(void (*)(void), 1298 this, &IOService::powerStateWillChangeTo))))) 1299 { 1300 if (fInterestedDrivers->findItem(powerDriver) == NULL) 1301 { 1302 PM_LOCK(); 1303 fInterestedDrivers->appendNewInformee(powerDriver); 1304 PM_UNLOCK(); 1305 } 1306 } 1307 1308 // Examine all existing power clients and perform limit check. 1309 1310 if (fPowerClients) 1311 { 1312 iter = OSCollectionIterator::withCollection(fPowerClients); 1313 if (iter) 1314 { 1315 const OSSymbol * client; 1316 while ((client = (const OSSymbol *) iter->getNextObject())) 1317 { 1318 uint32_t powerState = getPowerStateForClient(client); 1319 if (powerState >= numberOfStates) 1320 { 1321 updatePowerClient(client, numberOfStates - 1); 1322 } 1323 } 1324 iter->release(); 1325 } 1326 } 1327 1328 if ( inPlane(gIOPowerPlane) && fParentsKnowState ) 1329 { 1330 unsigned long tempDesire; 1331 fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fParentsCurrentPowerFlags); 1332 // initially change into the state we are already in 1333 tempDesire = fControllingDriver->initialPowerStateForDomainState(fParentsCurrentPowerFlags); 1334 adjustPowerState(tempDesire); 1335 } 1336 } 1337 else 1338 { 1339 OUR_PMLog(kPMLogControllingDriverErr2, numberOfStates, 0); 1340 IODelete(powerStates, IOPMPSEntry, numberOfStates); 1341 } 1342 1343 powerDriver->release(); 1344} 1345 1346//********************************************************************************* 1347// [public] registerInterestedDriver 1348// 1349// Add the caller to our list of interested drivers and return our current 1350// power state. If we don't have a power-controlling driver yet, we will 1351// call this interested driver again later when we do get a driver and find 1352// out what the current power state of the device is. 1353//********************************************************************************* 1354 1355IOPMPowerFlags IOService::registerInterestedDriver ( IOService * driver ) 1356{ 1357 IOPMRequest * request; 1358 bool signal; 1359 1360 if (!driver || !initialized || !fInterestedDrivers) 1361 return 0; 1362 1363 PM_LOCK(); 1364 signal = (!fInsertInterestSet && !fRemoveInterestSet); 1365 if (fInsertInterestSet == NULL) 1366 fInsertInterestSet = OSSet::withCapacity(4); 1367 if (fInsertInterestSet) 1368 { 1369 fInsertInterestSet->setObject(driver); 1370 if (fRemoveInterestSet) 1371 fRemoveInterestSet->removeObject(driver); 1372 } 1373 PM_UNLOCK(); 1374 1375 if (signal) 1376 { 1377 request = acquirePMRequest( this, kIOPMRequestTypeInterestChanged ); 1378 if (request) 1379 submitPMRequest( request ); 1380 } 1381 1382 // This return value cannot be trusted, but return a value 1383 // for those clients that care. 1384 1385 OUR_PMLog(kPMLogInterestedDriver, kIOPMDeviceUsable, 2); 1386 return kIOPMDeviceUsable; 1387} 1388 1389//********************************************************************************* 1390// [public] deRegisterInterestedDriver 1391//********************************************************************************* 1392 1393IOReturn IOService::deRegisterInterestedDriver ( IOService * driver ) 1394{ 1395 IOPMinformeeList * list; 1396 IOPMinformee * item; 1397 IOPMRequest * request; 1398 bool signal; 1399 1400 if (!driver) 1401 return kIOReturnBadArgument; 1402 if (!initialized || !fInterestedDrivers) 1403 return IOPMNotPowerManaged; 1404 1405 PM_LOCK(); 1406 signal = (!fRemoveInterestSet && !fInsertInterestSet); 1407 if (fRemoveInterestSet == NULL) 1408 fRemoveInterestSet = OSSet::withCapacity(4); 1409 if (fRemoveInterestSet) 1410 { 1411 fRemoveInterestSet->setObject(driver); 1412 if (fInsertInterestSet) 1413 fInsertInterestSet->removeObject(driver); 1414 1415 list = fInterestedDrivers; 1416 item = list->findItem(driver); 1417 if (item && item->active) 1418 { 1419 item->active = false; 1420 waitForPMDriverCall( driver ); 1421 } 1422 } 1423 PM_UNLOCK(); 1424 1425 if (signal) 1426 { 1427 request = acquirePMRequest( this, kIOPMRequestTypeInterestChanged ); 1428 if (request) 1429 submitPMRequest( request ); 1430 } 1431 1432 return IOPMNoErr; 1433} 1434 1435//********************************************************************************* 1436// [private] handleInterestChanged 1437// 1438// Handle interest added or removed. 1439//********************************************************************************* 1440 1441void IOService::handleInterestChanged( IOPMRequest * request ) 1442{ 1443 IOService * driver; 1444 IOPMinformee * informee; 1445 IOPMinformeeList * list = fInterestedDrivers; 1446 1447 PM_LOCK(); 1448 1449 if (fInsertInterestSet) 1450 { 1451 while ((driver = (IOService *) fInsertInterestSet->getAnyObject())) 1452 { 1453 if (list->findItem(driver) == NULL) 1454 { 1455 informee = list->appendNewInformee(driver); 1456 } 1457 fInsertInterestSet->removeObject(driver); 1458 } 1459 fInsertInterestSet->release(); 1460 fInsertInterestSet = 0; 1461 } 1462 1463 if (fRemoveInterestSet) 1464 { 1465 while ((driver = (IOService *) fRemoveInterestSet->getAnyObject())) 1466 { 1467 informee = list->findItem(driver); 1468 if (informee) 1469 { 1470 // Clean-up async interest acknowledgement 1471 if (fHeadNotePendingAcks && informee->timer) 1472 { 1473 informee->timer = 0; 1474 fHeadNotePendingAcks--; 1475 } 1476 list->removeFromList(driver); 1477 } 1478 fRemoveInterestSet->removeObject(driver); 1479 } 1480 fRemoveInterestSet->release(); 1481 fRemoveInterestSet = 0; 1482 } 1483 1484 PM_UNLOCK(); 1485} 1486 1487//********************************************************************************* 1488// [public] acknowledgePowerChange 1489// 1490// After we notified one of the interested drivers or a power-domain child 1491// of an impending change in power, it has called to say it is now 1492// prepared for the change. If this object is the last to 1493// acknowledge this change, we take whatever action we have been waiting 1494// for. 1495// That may include acknowledging to our parent. In this case, we do it 1496// last of all to insure that this doesn't cause the parent to call us some- 1497// where else and alter data we are relying on here (like the very existance 1498// of a "current change note".) 1499//********************************************************************************* 1500 1501IOReturn IOService::acknowledgePowerChange ( IOService * whichObject ) 1502{ 1503 IOPMRequest * request; 1504 1505 if (!initialized) 1506 return IOPMNotYetInitialized; 1507 if (!whichObject) 1508 return kIOReturnBadArgument; 1509 1510 request = acquirePMRequest( this, kIOPMRequestTypeAckPowerChange ); 1511 if (!request) 1512 return kIOReturnNoMemory; 1513 1514 whichObject->retain(); 1515 request->fArg0 = whichObject; 1516 1517 submitPMRequest( request ); 1518 return IOPMNoErr; 1519} 1520 1521//********************************************************************************* 1522// [private] handleAcknowledgePowerChange 1523//********************************************************************************* 1524 1525bool IOService::handleAcknowledgePowerChange ( IOPMRequest * request ) 1526{ 1527 IOPMinformee * informee; 1528 unsigned long childPower = kIOPMUnknown; 1529 IOService * theChild; 1530 IOService * whichObject; 1531 bool all_acked = false; 1532 1533 PM_ASSERT_IN_GATE(); 1534 whichObject = (IOService *) request->fArg0; 1535 assert(whichObject); 1536 1537 // one of our interested drivers? 1538 informee = fInterestedDrivers->findItem( whichObject ); 1539 if ( informee == NULL ) 1540 { 1541 if ( !isChild(whichObject, gIOPowerPlane) ) 1542 { 1543 OUR_PMLog(kPMLogAcknowledgeErr1, 0, 0); 1544 goto no_err; 1545 } else { 1546 OUR_PMLog(kPMLogChildAcknowledge, fHeadNotePendingAcks, 0); 1547 } 1548 } else { 1549 OUR_PMLog(kPMLogDriverAcknowledge, fHeadNotePendingAcks, 0); 1550 } 1551 1552 if ( fHeadNotePendingAcks != 0 ) 1553 { 1554 assert(fPowerStates != NULL); 1555 1556 // yes, make sure we're expecting acks 1557 if ( informee != NULL ) 1558 { 1559 // it's an interested driver 1560 // make sure we're expecting this ack 1561 if ( informee->timer != 0 ) 1562 { 1563#if LOG_SETPOWER_TIMES 1564 if (informee->timer > 0) 1565 { 1566 uint64_t nsec = computeTimeDeltaNS(&informee->startTime); 1567 if (nsec > LOG_SETPOWER_TIMES) 1568 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) async took %d ms\n", 1569 informee->whatObject->getName(), 1570 (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did", 1571 informee->whatObject, 1572 fName, fCurrentPowerState, fHeadNotePowerState, NS_TO_US(nsec)); 1573 1574 uint16_t logType = (fDriverCallReason == kDriverCallInformPreChange) 1575 ? kIOPMEventTypePSWillChangeTo 1576 : kIOPMEventTypePSDidChangeTo; 1577 1578 PMEventDetails *details = PMEventDetails::eventDetails( 1579 logType, 1580 fName, 1581 (uintptr_t)this, 1582 informee->whatObject->getName(), 1583 0, 0, 0, 1584 NS_TO_MS(nsec)); 1585 1586 getPMRootDomain()->recordAndReleasePMEventGated( details ); 1587 } 1588#endif 1589 // mark it acked 1590 informee->timer = 0; 1591 // that's one fewer to worry about 1592 fHeadNotePendingAcks--; 1593 } else { 1594 // this driver has already acked 1595 OUR_PMLog(kPMLogAcknowledgeErr2, 0, 0); 1596 } 1597 } else { 1598 // it's a child 1599 // make sure we're expecting this ack 1600 if ( ((IOPowerConnection *)whichObject)->getAwaitingAck() ) 1601 { 1602 // that's one fewer to worry about 1603 fHeadNotePendingAcks--; 1604 ((IOPowerConnection *)whichObject)->setAwaitingAck(false); 1605 theChild = (IOService *)whichObject->copyChildEntry(gIOPowerPlane); 1606 if ( theChild ) 1607 { 1608 childPower = theChild->currentPowerConsumption(); 1609 theChild->release(); 1610 } 1611 if ( childPower == kIOPMUnknown ) 1612 { 1613 fHeadNotePowerArrayEntry->staticPower = kIOPMUnknown; 1614 } else { 1615 if (fHeadNotePowerArrayEntry->staticPower != kIOPMUnknown) 1616 { 1617 fHeadNotePowerArrayEntry->staticPower += childPower; 1618 } 1619 } 1620 } 1621 } 1622 1623 if ( fHeadNotePendingAcks == 0 ) { 1624 // yes, stop the timer 1625 stop_ack_timer(); 1626 // and now we can continue 1627 all_acked = true; 1628 } 1629 } else { 1630 OUR_PMLog(kPMLogAcknowledgeErr3, 0, 0); // not expecting anybody to ack 1631 } 1632 1633no_err: 1634 if (whichObject) 1635 whichObject->release(); 1636 1637 return all_acked; 1638} 1639 1640//********************************************************************************* 1641// [public] acknowledgeSetPowerState 1642// 1643// After we instructed our controlling driver to change power states, 1644// it has called to say it has finished doing so. 1645// We continue to process the power state change. 1646//********************************************************************************* 1647 1648IOReturn IOService::acknowledgeSetPowerState ( void ) 1649{ 1650 IOPMRequest * request; 1651 1652 if (!initialized) 1653 return IOPMNotYetInitialized; 1654 1655 request = acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState ); 1656 if (!request) 1657 return kIOReturnNoMemory; 1658 1659 submitPMRequest( request ); 1660 return kIOReturnSuccess; 1661} 1662 1663//********************************************************************************* 1664// [private] adjustPowerState 1665//********************************************************************************* 1666 1667void IOService::adjustPowerState ( uint32_t clamp ) 1668{ 1669 PM_ASSERT_IN_GATE(); 1670 computeDesiredState(clamp); 1671 if (fControllingDriver && fParentsKnowState && inPlane(gIOPowerPlane)) 1672 { 1673 IOPMPowerChangeFlags changeFlags = kIOPMSelfInitiated; 1674 1675 // Indicate that children desires were ignored, and do not ask 1676 // apps for permission to drop power. This is used by root domain 1677 // for demand sleep. 1678 1679 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride) 1680 changeFlags |= (kIOPMIgnoreChildren | kIOPMSkipAskPowerDown); 1681 1682 startPowerChange( 1683 /* flags */ changeFlags, 1684 /* power state */ fDesiredPowerState, 1685 /* domain flags */ 0, 1686 /* connection */ 0, 1687 /* parent flags */ 0); 1688 } 1689} 1690 1691//********************************************************************************* 1692// [public] synchronizePowerTree 1693//********************************************************************************* 1694 1695IOReturn IOService::synchronizePowerTree ( 1696 IOOptionBits options, 1697 IOService * notifyRoot ) 1698{ 1699 IOPMRequest * request_c = 0; 1700 IOPMRequest * request_s; 1701 1702 if (this != getPMRootDomain()) 1703 return kIOReturnBadArgument; 1704 if (!initialized) 1705 return kIOPMNotYetInitialized; 1706 1707 if (notifyRoot) 1708 { 1709 IOPMRequest * nr; 1710 1711 // Cancels don't need to be synchronized. 1712 nr = acquirePMRequest(notifyRoot, kIOPMRequestTypeChildNotifyDelayCancel); 1713 if (nr) submitPMRequest(nr); 1714 nr = acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel); 1715 if (nr) submitPMRequest(nr); 1716 } 1717 1718 request_s = acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree ); 1719 if (!request_s) 1720 goto error_no_memory; 1721 1722 if (options & kIOPMSyncCancelPowerDown) 1723 request_c = acquirePMRequest( this, kIOPMRequestTypeIdleCancel ); 1724 if (request_c) 1725 { 1726 request_c->attachNextRequest( request_s ); 1727 submitPMRequest(request_c); 1728 } 1729 1730 request_s->fArg0 = (void *)(uintptr_t) options; 1731 submitPMRequest(request_s); 1732 1733 return kIOReturnSuccess; 1734 1735error_no_memory: 1736 if (request_c) releasePMRequest(request_c); 1737 if (request_s) releasePMRequest(request_s); 1738 return kIOReturnNoMemory; 1739} 1740 1741//********************************************************************************* 1742// [private] handleSynchronizePowerTree 1743//********************************************************************************* 1744 1745void IOService::handleSynchronizePowerTree ( IOPMRequest * request ) 1746{ 1747 PM_ASSERT_IN_GATE(); 1748 if (fControllingDriver && fParentsKnowState && inPlane(gIOPowerPlane) && 1749 (fCurrentPowerState == fNumberOfPowerStates - 1)) 1750 { 1751 IOOptionBits options = (uintptr_t) request->fArg0; 1752 1753 startPowerChange( 1754 /* flags */ kIOPMSelfInitiated | kIOPMSynchronize | 1755 (options & kIOPMSyncNoChildNotify), 1756 /* power state */ fCurrentPowerState, 1757 /* domain flags */ 0, 1758 /* connection */ 0, 1759 /* parent flags */ 0); 1760 } 1761} 1762 1763#ifndef __LP64__ 1764//********************************************************************************* 1765// [deprecated] powerDomainWillChangeTo 1766// 1767// Called by the power-hierarchy parent notifying of a new power state 1768// in the power domain. 1769// We enqueue a parent power-change to our queue of power changes. 1770// This may or may not cause us to change power, depending on what 1771// kind of change is occuring in the domain. 1772//********************************************************************************* 1773 1774IOReturn IOService::powerDomainWillChangeTo ( 1775 IOPMPowerFlags newPowerFlags, 1776 IOPowerConnection * whichParent ) 1777{ 1778 assert(false); 1779 return kIOReturnUnsupported; 1780} 1781#endif /* !__LP64__ */ 1782 1783//********************************************************************************* 1784// [private] handlePowerDomainWillChangeTo 1785//********************************************************************************* 1786 1787void IOService::handlePowerDomainWillChangeTo ( IOPMRequest * request ) 1788{ 1789 IOPMPowerFlags parentPowerFlags = (IOPMPowerFlags) request->fArg0; 1790 IOPowerConnection * whichParent = (IOPowerConnection *) request->fArg1; 1791 IOPMPowerChangeFlags parentChangeFlags = (IOPMPowerChangeFlags)(uintptr_t) request->fArg2; 1792 IOPMPowerChangeFlags myChangeFlags; 1793 OSIterator * iter; 1794 OSObject * next; 1795 IOPowerConnection * connection; 1796 IOPMPowerStateIndex newPowerState; 1797 IOPMPowerFlags combinedPowerFlags; 1798 bool savedParentsKnowState; 1799 IOReturn result = IOPMAckImplied; 1800 1801 PM_ASSERT_IN_GATE(); 1802 OUR_PMLog(kPMLogWillChange, parentPowerFlags, 0); 1803 1804 if (!inPlane(gIOPowerPlane) || !whichParent || !whichParent->getAwaitingAck()) 1805 { 1806 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__); 1807 goto exit_no_ack; 1808 } 1809 1810 savedParentsKnowState = fParentsKnowState; 1811 1812 // Combine parents' output power flags. 1813 1814 combinedPowerFlags = 0; 1815 1816 iter = getParentIterator(gIOPowerPlane); 1817 if ( iter ) 1818 { 1819 while ( (next = iter->getNextObject()) ) 1820 { 1821 if ( (connection = OSDynamicCast(IOPowerConnection, next)) ) 1822 { 1823 if ( connection == whichParent ) 1824 combinedPowerFlags |= parentPowerFlags; 1825 else 1826 combinedPowerFlags |= connection->parentCurrentPowerFlags(); 1827 } 1828 } 1829 iter->release(); 1830 } 1831 1832 // If our initial change has yet to occur, then defer the power change 1833 // until after the power domain has completed its power transition. 1834 1835 if ( fControllingDriver && !fInitialPowerChange ) 1836 { 1837 newPowerState = fControllingDriver->maxCapabilityForDomainState( 1838 combinedPowerFlags); 1839 1840 // Absorb parent's kIOPMSynchronize flag. 1841 myChangeFlags = kIOPMParentInitiated | kIOPMDomainWillChange | 1842 (parentChangeFlags & kIOPMSynchronize); 1843 1844 result = startPowerChange( 1845 /* flags */ myChangeFlags, 1846 /* power state */ newPowerState, 1847 /* domain flags */ combinedPowerFlags, 1848 /* connection */ whichParent, 1849 /* parent flags */ parentPowerFlags); 1850 } 1851 1852 // If parent is dropping power, immediately update the parent's 1853 // capability flags. Any future merging of parent(s) combined 1854 // power flags should account for this power drop. 1855 1856 if (parentChangeFlags & kIOPMDomainPowerDrop) 1857 { 1858 setParentInfo(parentPowerFlags, whichParent, true); 1859 } 1860 1861 // Parent is expecting an ACK from us. If we did not embark on a state 1862 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are 1863 // still required to issue an ACK to our parent. 1864 1865 if (IOPMAckImplied == result) 1866 { 1867 IOService * parent; 1868 parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane); 1869 assert(parent); 1870 if ( parent ) 1871 { 1872 parent->acknowledgePowerChange( whichParent ); 1873 parent->release(); 1874 } 1875 } 1876 1877exit_no_ack: 1878 // Drop the retain from notifyChild(). 1879 if (whichParent) whichParent->release(); 1880} 1881 1882#ifndef __LP64__ 1883//********************************************************************************* 1884// [deprecated] powerDomainDidChangeTo 1885// 1886// Called by the power-hierarchy parent after the power state of the power domain 1887// has settled at a new level. 1888// We enqueue a parent power-change to our queue of power changes. 1889// This may or may not cause us to change power, depending on what 1890// kind of change is occuring in the domain. 1891//********************************************************************************* 1892 1893IOReturn IOService::powerDomainDidChangeTo ( 1894 IOPMPowerFlags newPowerFlags, 1895 IOPowerConnection * whichParent ) 1896{ 1897 assert(false); 1898 return kIOReturnUnsupported; 1899} 1900#endif /* !__LP64__ */ 1901 1902//********************************************************************************* 1903// [private] handlePowerDomainDidChangeTo 1904//********************************************************************************* 1905 1906void IOService::handlePowerDomainDidChangeTo ( IOPMRequest * request ) 1907{ 1908 IOPMPowerFlags parentPowerFlags = (IOPMPowerFlags) request->fArg0; 1909 IOPowerConnection * whichParent = (IOPowerConnection *) request->fArg1; 1910 IOPMPowerChangeFlags parentChangeFlags = (IOPMPowerChangeFlags)(uintptr_t) request->fArg2; 1911 IOPMPowerChangeFlags myChangeFlags; 1912 IOPMPowerStateIndex newPowerState; 1913 IOPMPowerStateIndex initialDesire; 1914 bool savedParentsKnowState; 1915 IOReturn result = IOPMAckImplied; 1916 1917 PM_ASSERT_IN_GATE(); 1918 OUR_PMLog(kPMLogDidChange, parentPowerFlags, 0); 1919 1920 if (!inPlane(gIOPowerPlane) || !whichParent || !whichParent->getAwaitingAck()) 1921 { 1922 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__); 1923 goto exit_no_ack; 1924 } 1925 1926 savedParentsKnowState = fParentsKnowState; 1927 1928 setParentInfo(parentPowerFlags, whichParent, true); 1929 1930 if ( fControllingDriver ) 1931 { 1932 newPowerState = fControllingDriver->maxCapabilityForDomainState( 1933 fParentsCurrentPowerFlags); 1934 1935 if (fInitialPowerChange) 1936 { 1937 initialDesire = fControllingDriver->initialPowerStateForDomainState( 1938 fParentsCurrentPowerFlags); 1939 computeDesiredState(initialDesire); 1940 } 1941 else if (fAdvisoryTickleUsed && (newPowerState > 0) && 1942 ((parentChangeFlags & kIOPMSynchronize) == 0)) 1943 { 1944 // re-compute desired state in case advisory tickle was enabled 1945 computeDesiredState(); 1946 } 1947 1948 // Absorb parent's kIOPMSynchronize flag. 1949 myChangeFlags = kIOPMParentInitiated | kIOPMDomainDidChange | 1950 (parentChangeFlags & kIOPMSynchronize); 1951 1952 result = startPowerChange( 1953 /* flags */ myChangeFlags, 1954 /* power state */ newPowerState, 1955 /* domain flags */ fParentsCurrentPowerFlags, 1956 /* connection */ whichParent, 1957 /* parent flags */ 0); 1958 } 1959 1960 // Parent is expecting an ACK from us. If we did not embark on a state 1961 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are 1962 // still required to issue an ACK to our parent. 1963 1964 if (IOPMAckImplied == result) 1965 { 1966 IOService * parent; 1967 parent = (IOService *) whichParent->copyParentEntry(gIOPowerPlane); 1968 assert(parent); 1969 if ( parent ) 1970 { 1971 parent->acknowledgePowerChange( whichParent ); 1972 parent->release(); 1973 } 1974 } 1975 1976 // If the parent registers its power driver late, then this is the 1977 // first opportunity to tell our parent about our desire. 1978 1979 if (!savedParentsKnowState && fParentsKnowState) 1980 { 1981 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState = true\n", 1982 getName()); 1983 requestDomainPower( fDesiredPowerState ); 1984 } 1985 1986exit_no_ack: 1987 // Drop the retain from notifyChild(). 1988 if (whichParent) whichParent->release(); 1989} 1990 1991//********************************************************************************* 1992// [private] setParentInfo 1993// 1994// Set our connection data for one specific parent, and then combine all the parent 1995// data together. 1996//********************************************************************************* 1997 1998void IOService::setParentInfo ( 1999 IOPMPowerFlags newPowerFlags, 2000 IOPowerConnection * whichParent, 2001 bool knowsState ) 2002{ 2003 OSIterator * iter; 2004 OSObject * next; 2005 IOPowerConnection * conn; 2006 2007 PM_ASSERT_IN_GATE(); 2008 2009 // set our connection data 2010 whichParent->setParentCurrentPowerFlags(newPowerFlags); 2011 whichParent->setParentKnowsState(knowsState); 2012 2013 // recompute our parent info 2014 fParentsCurrentPowerFlags = 0; 2015 fParentsKnowState = true; 2016 2017 iter = getParentIterator(gIOPowerPlane); 2018 if ( iter ) 2019 { 2020 while ( (next = iter->getNextObject()) ) 2021 { 2022 if ( (conn = OSDynamicCast(IOPowerConnection, next)) ) 2023 { 2024 fParentsKnowState &= conn->parentKnowsState(); 2025 fParentsCurrentPowerFlags |= conn->parentCurrentPowerFlags(); 2026 } 2027 } 2028 iter->release(); 2029 } 2030} 2031 2032//****************************************************************************** 2033// [private] trackSystemSleepPreventers 2034//****************************************************************************** 2035 2036void IOService::trackSystemSleepPreventers( 2037 IOPMPowerStateIndex oldPowerState, 2038 IOPMPowerStateIndex newPowerState, 2039 IOPMPowerChangeFlags changeFlags __unused ) 2040{ 2041 IOPMPowerFlags oldCapability, newCapability; 2042 2043 oldCapability = fPowerStates[oldPowerState].capabilityFlags & 2044 (kIOPMPreventIdleSleep | kIOPMPreventSystemSleep); 2045 newCapability = fPowerStates[newPowerState].capabilityFlags & 2046 (kIOPMPreventIdleSleep | kIOPMPreventSystemSleep); 2047 2048 if (fHeadNoteChangeFlags & kIOPMInitialPowerChange) 2049 oldCapability = 0; 2050 if (oldCapability == newCapability) 2051 return; 2052 2053 if ((oldCapability ^ newCapability) & kIOPMPreventIdleSleep) 2054 { 2055#if SUPPORT_IDLE_CANCEL 2056 if ((oldCapability & kIOPMPreventIdleSleep) == 0) 2057 { 2058 IOPMRequest * cancelRequest; 2059 2060 cancelRequest = acquirePMRequest( this, kIOPMRequestTypeIdleCancel ); 2061 if (cancelRequest) 2062 { 2063 getPMRootDomain()->submitPMRequest( cancelRequest ); 2064 } 2065 } 2066#endif 2067 2068 getPMRootDomain()->updatePreventIdleSleepList(this, 2069 ((oldCapability & kIOPMPreventIdleSleep) == 0)); 2070 } 2071 2072 if ((oldCapability ^ newCapability) & kIOPMPreventSystemSleep) 2073 { 2074 2075 getPMRootDomain()->updatePreventSystemSleepList(this, 2076 ((oldCapability & kIOPMPreventSystemSleep) == 0)); 2077 } 2078} 2079 2080//********************************************************************************* 2081// [public] requestPowerDomainState 2082// 2083// Called on a power parent when a child's power requirement changes. 2084//********************************************************************************* 2085 2086IOReturn IOService::requestPowerDomainState( 2087 IOPMPowerFlags childRequestPowerFlags, 2088 IOPowerConnection * childConnection, 2089 unsigned long specification ) 2090{ 2091 IOPMPowerStateIndex ps; 2092 IOPMPowerFlags outputPowerFlags; 2093 IOService * child; 2094 IOPMRequest * subRequest; 2095 bool adjustPower = false; 2096 2097 if (!initialized) 2098 return IOPMNotYetInitialized; 2099 2100 if (gIOPMWorkLoop->onThread() == false) 2101 { 2102 PM_LOG("%s::requestPowerDomainState\n", getName()); 2103 return kIOReturnSuccess; 2104 } 2105 2106 OUR_PMLog(kPMLogRequestDomain, childRequestPowerFlags, specification); 2107 2108 if (!isChild(childConnection, gIOPowerPlane)) 2109 return kIOReturnNotAttached; 2110 2111 if (!fControllingDriver || !fNumberOfPowerStates) 2112 return kIOReturnNotReady; 2113 2114 child = (IOService *) childConnection->getChildEntry(gIOPowerPlane); 2115 assert(child); 2116 2117 // Merge in the power flags contributed by this power parent 2118 // at its current or impending power state. 2119 2120 outputPowerFlags = fPowerStates[fCurrentPowerState].outputPowerFlags; 2121 if (fMachineState != kIOPM_Finished) 2122 { 2123 if (IS_POWER_DROP && !IS_ROOT_DOMAIN) 2124 { 2125 // Use the lower power state when dropping power. 2126 // Must be careful since a power drop can be canceled 2127 // from the following states: 2128 // - kIOPM_OurChangeTellClientsPowerDown 2129 // - kIOPM_OurChangeTellPriorityClientsPowerDown 2130 // 2131 // The child must not wait for this parent to raise power 2132 // if the power drop was cancelled. The solution is to cancel 2133 // the power drop if possible, then schedule an adjustment to 2134 // re-evaluate the parent's power state. 2135 // 2136 // Root domain is excluded to avoid idle sleep issues. And permit 2137 // root domain children to pop up when system is going to sleep. 2138 2139 if ((fMachineState == kIOPM_OurChangeTellClientsPowerDown) || 2140 (fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown)) 2141 { 2142 fDoNotPowerDown = true; // cancel power drop 2143 adjustPower = true; // schedule an adjustment 2144 PM_LOG1("%s: power drop cancelled in state %u by %s\n", 2145 getName(), fMachineState, child->getName()); 2146 } 2147 else 2148 { 2149 // Beyond cancellation point, report the impending state. 2150 outputPowerFlags = 2151 fPowerStates[fHeadNotePowerState].outputPowerFlags; 2152 } 2153 } 2154 else if (IS_POWER_RISE) 2155 { 2156 // When raising power, must report the output power flags from 2157 // child's perspective. A child power request may arrive while 2158 // parent is transitioning upwards. If a request arrives after 2159 // setParentInfo() has already recorded the output power flags 2160 // for the next power state, then using the power supplied by 2161 // fCurrentPowerState is incorrect, and might cause the child 2162 // to wait when it should not. 2163 2164 outputPowerFlags = childConnection->parentCurrentPowerFlags(); 2165 } 2166 } 2167 child->fHeadNoteDomainTargetFlags |= outputPowerFlags; 2168 2169 // Map child's requested power flags to one of our power state. 2170 2171 for (ps = 0; ps < fNumberOfPowerStates; ps++) 2172 { 2173 if ((fPowerStates[ps].outputPowerFlags & childRequestPowerFlags) == 2174 (fOutputPowerCharacterFlags & childRequestPowerFlags)) 2175 break; 2176 } 2177 if (ps >= fNumberOfPowerStates) 2178 { 2179 ps = 0; // should never happen 2180 } 2181 2182 // Conditions that warrants a power adjustment on this parent. 2183 // Adjust power will also propagate any changes to the child's 2184 // prevent idle/sleep flags towards the root domain. 2185 2186 if (!childConnection->childHasRequestedPower() || 2187 (ps != childConnection->getDesiredDomainState())) 2188 adjustPower = true; 2189 2190#if ENABLE_DEBUG_LOGS 2191 if (adjustPower) 2192 { 2193 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n", 2194 getName(), child->getName(), 2195 !childConnection->childHasRequestedPower(), 2196 (uint32_t) childConnection->getDesiredDomainState(), 2197 (uint32_t) ps); 2198 } 2199#endif 2200 2201 // Record the child's desires on the connection. 2202 childConnection->setChildHasRequestedPower(); 2203 childConnection->setDesiredDomainState( ps ); 2204 2205 // Schedule a request to re-evaluate all children desires and 2206 // adjust power state. Submit a request if one wasn't pending, 2207 // or if the current request is part of a call tree. 2208 2209 if (adjustPower && !fDeviceOverrideEnabled && 2210 (!fAdjustPowerScheduled || gIOPMRequest->getRootRequest())) 2211 { 2212 subRequest = acquirePMRequest( 2213 this, kIOPMRequestTypeAdjustPowerState, gIOPMRequest ); 2214 if (subRequest) 2215 { 2216 submitPMRequest( subRequest ); 2217 fAdjustPowerScheduled = true; 2218 } 2219 } 2220 2221 return kIOReturnSuccess; 2222} 2223 2224//********************************************************************************* 2225// [public] temporaryPowerClampOn 2226// 2227// A power domain wants to clamp its power on till it has children which 2228// will thendetermine the power domain state. 2229// 2230// We enter the highest state until addPowerChild is called. 2231//********************************************************************************* 2232 2233IOReturn IOService::temporaryPowerClampOn ( void ) 2234{ 2235 return requestPowerState( gIOPMPowerClientChildProxy, kIOPMPowerStateMax ); 2236} 2237 2238//********************************************************************************* 2239// [public] makeUsable 2240// 2241// Some client of our device is asking that we become usable. Although 2242// this has not come from a subclassed device object, treat it exactly 2243// as if it had. In this way, subsequent requests for lower power from 2244// a subclassed device object will pre-empt this request. 2245// 2246// We treat this as a subclass object request to switch to the 2247// highest power state. 2248//********************************************************************************* 2249 2250IOReturn IOService::makeUsable ( void ) 2251{ 2252 OUR_PMLog(kPMLogMakeUsable, 0, 0); 2253 return requestPowerState( gIOPMPowerClientDevice, kIOPMPowerStateMax ); 2254} 2255 2256//********************************************************************************* 2257// [public] currentCapability 2258//********************************************************************************* 2259 2260IOPMPowerFlags IOService::currentCapability ( void ) 2261{ 2262 if (!initialized) 2263 return IOPMNotPowerManaged; 2264 2265 return fCurrentCapabilityFlags; 2266} 2267 2268//********************************************************************************* 2269// [public] changePowerStateTo 2270// 2271// Called by our power-controlling driver to change power state. The new desired 2272// power state is computed and compared against the current power state. If those 2273// power states differ, then a power state change is initiated. 2274//********************************************************************************* 2275 2276IOReturn IOService::changePowerStateTo ( unsigned long ordinal ) 2277{ 2278 OUR_PMLog(kPMLogChangeStateTo, ordinal, 0); 2279 return requestPowerState( gIOPMPowerClientDriver, ordinal ); 2280} 2281 2282//********************************************************************************* 2283// [protected] changePowerStateToPriv 2284// 2285// Called by our driver subclass to change power state. The new desired power 2286// state is computed and compared against the current power state. If those 2287// power states differ, then a power state change is initiated. 2288//********************************************************************************* 2289 2290IOReturn IOService::changePowerStateToPriv ( unsigned long ordinal ) 2291{ 2292 OUR_PMLog(kPMLogChangeStateToPriv, ordinal, 0); 2293 return requestPowerState( gIOPMPowerClientDevice, ordinal ); 2294} 2295 2296//********************************************************************************* 2297// [protected] changePowerStateWithOverrideTo 2298// 2299// Called by our driver subclass to change power state. The new desired power 2300// state is computed and compared against the current power state. If those 2301// power states differ, then a power state change is initiated. 2302// Override enforced - Children and Driver desires are ignored. 2303//********************************************************************************* 2304 2305IOReturn IOService::changePowerStateWithOverrideTo ( unsigned long ordinal ) 2306{ 2307 IOPMRequest * request; 2308 2309 if (!initialized) 2310 return kIOPMNotYetInitialized; 2311 2312 OUR_PMLog(kPMLogChangeStateToPriv, ordinal, 0); 2313 2314 request = acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride ); 2315 if (!request) 2316 return kIOReturnNoMemory; 2317 2318 gIOPMPowerClientDevice->retain(); 2319 request->fArg0 = (void *) ordinal; 2320 request->fArg1 = (void *) gIOPMPowerClientDevice; 2321 request->fArg2 = 0; 2322#if NOT_READY 2323 if (action) 2324 request->installCompletionAction( action, target, param ); 2325#endif 2326 2327 // Prevent needless downwards power transitions by clamping power 2328 // until the scheduled request is executed. 2329 2330 if (gIOPMWorkLoop->inGate() && (ordinal < fNumberOfPowerStates)) 2331 { 2332 fTempClampPowerState = max(fTempClampPowerState, ordinal); 2333 fTempClampCount++; 2334 fOverrideMaxPowerState = ordinal; 2335 request->fArg2 = (void *) (uintptr_t) true; 2336 } 2337 2338 submitPMRequest( request ); 2339 return IOPMNoErr; 2340} 2341 2342//********************************************************************************* 2343// [private] requestPowerState 2344//********************************************************************************* 2345 2346IOReturn IOService::requestPowerState ( 2347 const OSSymbol * client, 2348 uint32_t state ) 2349{ 2350 IOPMRequest * request; 2351 2352 if (!client) 2353 return kIOReturnBadArgument; 2354 if (!initialized) 2355 return kIOPMNotYetInitialized; 2356 2357 request = acquirePMRequest( this, kIOPMRequestTypeRequestPowerState ); 2358 if (!request) 2359 return kIOReturnNoMemory; 2360 2361 client->retain(); 2362 request->fArg0 = (void *) state; 2363 request->fArg1 = (void *) client; 2364 request->fArg2 = 0; 2365#if NOT_READY 2366 if (action) 2367 request->installCompletionAction( action, target, param ); 2368#endif 2369 2370 // Prevent needless downwards power transitions by clamping power 2371 // until the scheduled request is executed. 2372 2373 if (gIOPMWorkLoop->inGate() && (state < fNumberOfPowerStates)) 2374 { 2375 fTempClampPowerState = max(fTempClampPowerState, state); 2376 fTempClampCount++; 2377 request->fArg2 = (void *) (uintptr_t) true; 2378 } 2379 2380 submitPMRequest( request ); 2381 return IOPMNoErr; 2382} 2383 2384//********************************************************************************* 2385// [private] handleRequestPowerState 2386//********************************************************************************* 2387 2388void IOService::handleRequestPowerState ( IOPMRequest * request ) 2389{ 2390 const OSSymbol * client = (const OSSymbol *) request->fArg1; 2391 uint32_t state = (uint32_t)(uintptr_t) request->fArg0; 2392 2393 PM_ASSERT_IN_GATE(); 2394 if (request->fArg2) 2395 { 2396 assert(fTempClampCount != 0); 2397 if (fTempClampCount) fTempClampCount--; 2398 if (!fTempClampCount) fTempClampPowerState = 0; 2399 } 2400 2401 if (fNumberOfPowerStates && (state >= fNumberOfPowerStates)) 2402 state = fNumberOfPowerStates - 1; 2403 2404 // The power suppression due to changePowerStateWithOverrideTo() expires 2405 // upon the next "device" power request - changePowerStateToPriv(). 2406 2407 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride) && 2408 (client == gIOPMPowerClientDevice)) 2409 fOverrideMaxPowerState = kIOPMPowerStateMax; 2410 2411 if ((state == 0) && 2412 (client != gIOPMPowerClientDevice) && 2413 (client != gIOPMPowerClientDriver) && 2414 (client != gIOPMPowerClientChildProxy)) 2415 removePowerClient(client); 2416 else 2417 updatePowerClient(client, state); 2418 2419 adjustPowerState(); 2420 client->release(); 2421} 2422 2423//********************************************************************************* 2424// [private] Helper functions to update/remove power clients. 2425//********************************************************************************* 2426 2427void IOService::updatePowerClient( const OSSymbol * client, uint32_t powerState ) 2428{ 2429 if (!fPowerClients) 2430 fPowerClients = OSDictionary::withCapacity(4); 2431 if (fPowerClients && client) 2432 { 2433 OSNumber * num = (OSNumber *) fPowerClients->getObject(client); 2434 if (num) 2435 num->setValue(powerState); 2436 else 2437 { 2438 num = OSNumber::withNumber(powerState, 32); 2439 if (num) 2440 { 2441 fPowerClients->setObject(client, num); 2442 num->release(); 2443 } 2444 } 2445 } 2446} 2447 2448void IOService::removePowerClient( const OSSymbol * client ) 2449{ 2450 if (fPowerClients && client) 2451 fPowerClients->removeObject(client); 2452} 2453 2454uint32_t IOService::getPowerStateForClient( const OSSymbol * client ) 2455{ 2456 uint32_t powerState = 0; 2457 2458 if (fPowerClients && client) 2459 { 2460 OSNumber * num = (OSNumber *) fPowerClients->getObject(client); 2461 if (num) powerState = num->unsigned32BitValue(); 2462 } 2463 return powerState; 2464} 2465 2466//********************************************************************************* 2467// [protected] powerOverrideOnPriv 2468//********************************************************************************* 2469 2470IOReturn IOService::powerOverrideOnPriv ( void ) 2471{ 2472 IOPMRequest * request; 2473 2474 if (!initialized) 2475 return IOPMNotYetInitialized; 2476 2477 if (gIOPMWorkLoop->inGate()) 2478 { 2479 fDeviceOverrideEnabled = true; 2480 return IOPMNoErr; 2481 } 2482 2483 request = acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv ); 2484 if (!request) 2485 return kIOReturnNoMemory; 2486 2487 submitPMRequest( request ); 2488 return IOPMNoErr; 2489} 2490 2491//********************************************************************************* 2492// [protected] powerOverrideOffPriv 2493//********************************************************************************* 2494 2495IOReturn IOService::powerOverrideOffPriv ( void ) 2496{ 2497 IOPMRequest * request; 2498 2499 if (!initialized) 2500 return IOPMNotYetInitialized; 2501 2502 if (gIOPMWorkLoop->inGate()) 2503 { 2504 fDeviceOverrideEnabled = false; 2505 return IOPMNoErr; 2506 } 2507 2508 request = acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv ); 2509 if (!request) 2510 return kIOReturnNoMemory; 2511 2512 submitPMRequest( request ); 2513 return IOPMNoErr; 2514} 2515 2516//********************************************************************************* 2517// [private] handlePowerOverrideChanged 2518//********************************************************************************* 2519 2520void IOService::handlePowerOverrideChanged ( IOPMRequest * request ) 2521{ 2522 PM_ASSERT_IN_GATE(); 2523 if (request->getType() == kIOPMRequestTypePowerOverrideOnPriv) 2524 { 2525 OUR_PMLog(kPMLogOverrideOn, 0, 0); 2526 fDeviceOverrideEnabled = true; 2527 } 2528 else 2529 { 2530 OUR_PMLog(kPMLogOverrideOff, 0, 0); 2531 fDeviceOverrideEnabled = false; 2532 } 2533 2534 adjustPowerState(); 2535} 2536 2537//********************************************************************************* 2538// [private] computeDesiredState 2539//********************************************************************************* 2540 2541void IOService::computeDesiredState ( unsigned long localClamp ) 2542{ 2543 OSIterator * iter; 2544 OSObject * next; 2545 IOPowerConnection * connection; 2546 uint32_t desiredState = 0; 2547 uint32_t newPowerState = 0; 2548 bool hasChildren = false; 2549 2550 // Desired power state is always 0 without a controlling driver. 2551 2552 if (!fNumberOfPowerStates) 2553 { 2554 fDesiredPowerState = 0; 2555 //PM_LOG("%s::%s no controlling driver\n", getName(), __FUNCTION__); 2556 return; 2557 } 2558 2559 // Examine the children's desired power state. 2560 2561 iter = getChildIterator(gIOPowerPlane); 2562 if (iter) 2563 { 2564 while ((next = iter->getNextObject())) 2565 { 2566 if ((connection = OSDynamicCast(IOPowerConnection, next))) 2567 { 2568 if (connection->getReadyFlag() == false) 2569 { 2570 PM_LOG3("[%s] %s: connection not ready\n", 2571 getName(), __FUNCTION__); 2572 continue; 2573 } 2574 if (connection->childHasRequestedPower()) 2575 hasChildren = true; 2576 if (connection->getDesiredDomainState() > desiredState) 2577 desiredState = connection->getDesiredDomainState(); 2578 } 2579 } 2580 iter->release(); 2581 } 2582 if (hasChildren) 2583 updatePowerClient(gIOPMPowerClientChildren, desiredState); 2584 else 2585 removePowerClient(gIOPMPowerClientChildren); 2586 2587 // Iterate through all power clients to determine the min power state. 2588 2589 iter = OSCollectionIterator::withCollection(fPowerClients); 2590 if (iter) 2591 { 2592 const OSSymbol * client; 2593 while ((client = (const OSSymbol *) iter->getNextObject())) 2594 { 2595 // Ignore child and driver when override is in effect. 2596 if ((fDeviceOverrideEnabled || 2597 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride)) && 2598 ((client == gIOPMPowerClientChildren) || 2599 (client == gIOPMPowerClientDriver))) 2600 continue; 2601 2602 // Ignore child proxy when children are present. 2603 if (hasChildren && (client == gIOPMPowerClientChildProxy)) 2604 continue; 2605 2606 if (client == gIOPMPowerClientAdvisoryTickle && 2607 !gIOPMAdvisoryTickleEnabled) 2608 continue; 2609 2610 desiredState = getPowerStateForClient(client); 2611 assert(desiredState < fNumberOfPowerStates); 2612 PM_LOG1(" %u %s\n", 2613 desiredState, client->getCStringNoCopy()); 2614 2615 newPowerState = max(newPowerState, desiredState); 2616 2617 if (client == gIOPMPowerClientDevice) 2618 fDeviceDesire = desiredState; 2619 } 2620 iter->release(); 2621 } 2622 2623 // Factor in the temporary power desires. 2624 2625 newPowerState = max(newPowerState, localClamp); 2626 newPowerState = max(newPowerState, fTempClampPowerState); 2627 2628 // Limit check against max power override. 2629 2630 newPowerState = min(newPowerState, fOverrideMaxPowerState); 2631 2632 // Limit check against number of power states. 2633 2634 if (newPowerState >= fNumberOfPowerStates) 2635 newPowerState = fNumberOfPowerStates - 1; 2636 2637 fDesiredPowerState = newPowerState; 2638 2639 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n", 2640 (uint32_t) localClamp, (uint32_t) fTempClampPowerState, 2641 (uint32_t) fCurrentPowerState, newPowerState); 2642 2643 // Restart idle timer if stopped and device desire has increased. 2644 // Or if advisory desire exists. 2645 2646 if (fIdleTimerStopped) 2647 { 2648 if (fDeviceDesire > 0) 2649 { 2650 fIdleTimerStopped = false; 2651 fActivityTickleCount = 0; 2652 clock_get_uptime(&fIdleTimerStartTime); 2653 start_PM_idle_timer(); 2654 } 2655 else if (fHasAdvisoryDesire) 2656 { 2657 fIdleTimerStopped = false; 2658 start_PM_idle_timer(); 2659 } 2660 } 2661 2662 // Invalidate cached tickle power state when desires change, and not 2663 // due to a tickle request. This invalidation must occur before the 2664 // power state change to minimize races. We want to err on the side 2665 // of servicing more activity tickles rather than dropping one when 2666 // the device is in a low power state. 2667 2668 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle) && 2669 (fActivityTicklePowerState != kInvalidTicklePowerState)) 2670 { 2671 IOLockLock(fActivityLock); 2672 fActivityTicklePowerState = kInvalidTicklePowerState; 2673 IOLockUnlock(fActivityLock); 2674 } 2675} 2676 2677//********************************************************************************* 2678// [public] currentPowerConsumption 2679// 2680//********************************************************************************* 2681 2682unsigned long IOService::currentPowerConsumption ( void ) 2683{ 2684 if (!initialized) 2685 return kIOPMUnknown; 2686 2687 return fCurrentPowerConsumption; 2688} 2689 2690//********************************************************************************* 2691// [deprecated] getPMworkloop 2692//********************************************************************************* 2693 2694IOWorkLoop * IOService::getPMworkloop ( void ) 2695{ 2696 return gIOPMWorkLoop; 2697} 2698 2699#if NOT_YET 2700 2701//********************************************************************************* 2702// Power Parent/Children Applier 2703//********************************************************************************* 2704 2705static void 2706applyToPowerChildren( 2707 IOService * service, 2708 IOServiceApplierFunction applier, 2709 void * context, 2710 IOOptionBits options ) 2711{ 2712 PM_ASSERT_IN_GATE(); 2713 2714 IORegistryEntry * entry; 2715 IORegistryIterator * iter; 2716 IOPowerConnection * connection; 2717 IOService * child; 2718 2719 iter = IORegistryIterator::iterateOver(service, gIOPowerPlane, options); 2720 if (iter) 2721 { 2722 while ((entry = iter->getNextObject())) 2723 { 2724 // Get child of IOPowerConnection objects 2725 if ((connection = OSDynamicCast(IOPowerConnection, entry))) 2726 { 2727 child = (IOService *) connection->copyChildEntry(gIOPowerPlane); 2728 if (child) 2729 { 2730 (*applier)(child, context); 2731 child->release(); 2732 } 2733 } 2734 } 2735 iter->release(); 2736 } 2737} 2738 2739static void 2740applyToPowerParent( 2741 IOService * service, 2742 IOServiceApplierFunction applier, 2743 void * context, 2744 IOOptionBits options ) 2745{ 2746 PM_ASSERT_IN_GATE(); 2747 2748 IORegistryEntry * entry; 2749 IORegistryIterator * iter; 2750 IOPowerConnection * connection; 2751 IOService * parent; 2752 2753 iter = IORegistryIterator::iterateOver(service, gIOPowerPlane, 2754 options | kIORegistryIterateParents); 2755 if (iter) 2756 { 2757 while ((entry = iter->getNextObject())) 2758 { 2759 // Get child of IOPowerConnection objects 2760 if ((connection = OSDynamicCast(IOPowerConnection, entry))) 2761 { 2762 parent = (IOService *) connection->copyParentEntry(gIOPowerPlane); 2763 if (parent) 2764 { 2765 (*applier)(parent, context); 2766 parent->release(); 2767 } 2768 } 2769 } 2770 iter->release(); 2771 } 2772} 2773 2774#endif /* NOT_YET */ 2775 2776// MARK: - 2777// MARK: Activity Tickle & Idle Timer 2778 2779void IOService::setAdvisoryTickleEnable( bool enable ) 2780{ 2781 gIOPMAdvisoryTickleEnabled = enable; 2782} 2783 2784//********************************************************************************* 2785// [public] activityTickle 2786// 2787// The tickle with parameter kIOPMSuperclassPolicy1 causes the activity 2788// flag to be set, and the device state checked. If the device has been 2789// powered down, it is powered up again. 2790// The tickle with parameter kIOPMSubclassPolicy is ignored here and 2791// should be intercepted by a subclass. 2792//********************************************************************************* 2793 2794bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber ) 2795{ 2796 IOPMRequest * request; 2797 bool noPowerChange = true; 2798 2799 if (!initialized) 2800 return true; // no power change 2801 2802 if ((type == kIOPMSuperclassPolicy1) && stateNumber) 2803 { 2804 IOLockLock(fActivityLock); 2805 2806 // Record device activity for the idle timer handler. 2807 2808 fDeviceWasActive = true; 2809 fActivityTickleCount++; 2810 clock_get_uptime(&fDeviceActiveTimestamp); 2811 2812 PM_ACTION_0(actionActivityTickle); 2813 2814 // Record the last tickle power state. 2815 // This helps to filter out redundant tickles as 2816 // this function may be called from the data path. 2817 2818 if (fActivityTicklePowerState < (int)stateNumber) 2819 { 2820 fActivityTicklePowerState = stateNumber; 2821 noPowerChange = false; 2822 2823 request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle ); 2824 if (request) 2825 { 2826 request->fArg0 = (void *) stateNumber; // power state 2827 request->fArg1 = (void *) true; // power rise 2828 request->fArg2 = (void *) false; // regular tickle 2829 submitPMRequest(request); 2830 } 2831 } 2832 2833 IOLockUnlock(fActivityLock); 2834 } 2835 2836 else if ((type == kIOPMActivityTickleTypeAdvisory) && 2837 ((stateNumber = fDeviceUsablePowerState))) 2838 { 2839 IOLockLock(fActivityLock); 2840 2841 fAdvisoryTickled = true; 2842 2843 if (fAdvisoryTicklePowerState != (int)stateNumber) 2844 { 2845 fAdvisoryTicklePowerState = stateNumber; 2846 noPowerChange = false; 2847 2848 request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle ); 2849 if (request) 2850 { 2851 request->fArg0 = (void *) stateNumber; // power state 2852 request->fArg1 = (void *) true; // power rise 2853 request->fArg2 = (void *) true; // advisory tickle 2854 submitPMRequest(request); 2855 } 2856 } 2857 2858 IOLockUnlock(fActivityLock); 2859 } 2860 2861 // Returns false if the activityTickle might cause a transition to a 2862 // higher powered state, true otherwise. 2863 2864 return noPowerChange; 2865} 2866 2867//********************************************************************************* 2868// [private] handleActivityTickle 2869//********************************************************************************* 2870 2871void IOService::handleActivityTickle ( IOPMRequest * request ) 2872{ 2873 uint32_t ticklePowerState = (uint32_t)(uintptr_t) request->fArg0; 2874 bool deviceWasActive = (request->fArg1 == (void *) true); 2875 bool isRegularTickle = (request->fArg2 == (void *) false); 2876 bool adjustPower = false; 2877 2878 PM_ASSERT_IN_GATE(); 2879 if (isRegularTickle) 2880 { 2881 if (deviceWasActive) 2882 { 2883 if ((ticklePowerState > fDeviceDesire) && 2884 (ticklePowerState < fNumberOfPowerStates)) 2885 { 2886 fIdleTimerMinPowerState = ticklePowerState; 2887 updatePowerClient(gIOPMPowerClientDevice, ticklePowerState); 2888 adjustPower = true; 2889 } 2890 } 2891 else if (fDeviceDesire > fIdleTimerMinPowerState) 2892 { 2893 // Power drop due to idle timer expiration. 2894 // Do not allow idle timer to reduce power below tickle power. 2895 // This prevents the idle timer from decreasing the device desire 2896 // to zero and cancelling the effect of a pre-sleep tickle when 2897 // system wakes up to doze state, while the device is unable to 2898 // raise its power state to satisfy the tickle. 2899 2900 ticklePowerState = fDeviceDesire - 1; 2901 updatePowerClient(gIOPMPowerClientDevice, ticklePowerState); 2902 adjustPower = true; 2903 } 2904 } 2905 else // advisory tickle 2906 { 2907 if (deviceWasActive) 2908 { 2909 if ((ticklePowerState == fDeviceUsablePowerState) && 2910 (ticklePowerState < fNumberOfPowerStates)) 2911 { 2912 updatePowerClient(gIOPMPowerClientAdvisoryTickle, ticklePowerState); 2913 fHasAdvisoryDesire = true; 2914 fAdvisoryTickleUsed = true; 2915 adjustPower = true; 2916 } 2917 else 2918 { 2919 IOLockLock(fActivityLock); 2920 fAdvisoryTicklePowerState = kInvalidTicklePowerState; 2921 IOLockUnlock(fActivityLock); 2922 } 2923 } 2924 else if (fHasAdvisoryDesire) 2925 { 2926 removePowerClient(gIOPMPowerClientAdvisoryTickle); 2927 fHasAdvisoryDesire = false; 2928 adjustPower = true; 2929 } 2930 } 2931 2932 if (adjustPower) 2933 { 2934 adjustPowerState(); 2935 } 2936} 2937 2938//****************************************************************************** 2939// [public] setIdleTimerPeriod 2940// 2941// A subclass policy-maker is using our standard idleness detection service. 2942// Start the idle timer. Period is in seconds. 2943//****************************************************************************** 2944 2945IOReturn IOService::setIdleTimerPeriod ( unsigned long period ) 2946{ 2947 if (!initialized) 2948 return IOPMNotYetInitialized; 2949 2950 OUR_PMLog(kPMLogSetIdleTimerPeriod, period, fIdleTimerPeriod); 2951 2952 IOPMRequest * request = 2953 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod ); 2954 if (!request) 2955 return kIOReturnNoMemory; 2956 2957 request->fArg0 = (void *) period; 2958 submitPMRequest( request ); 2959 2960 return kIOReturnSuccess; 2961} 2962 2963IOReturn IOService::setIgnoreIdleTimer( bool ignore ) 2964{ 2965 if (!initialized) 2966 return IOPMNotYetInitialized; 2967 2968 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer, ignore, 0); 2969 2970 IOPMRequest * request = 2971 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer ); 2972 if (!request) 2973 return kIOReturnNoMemory; 2974 2975 request->fArg0 = (void *) ignore; 2976 submitPMRequest( request ); 2977 2978 return kIOReturnSuccess; 2979} 2980 2981//****************************************************************************** 2982// [public] nextIdleTimeout 2983// 2984// Returns how many "seconds from now" the device should idle into its 2985// next lowest power state. 2986//****************************************************************************** 2987 2988SInt32 IOService::nextIdleTimeout( 2989 AbsoluteTime currentTime, 2990 AbsoluteTime lastActivity, 2991 unsigned int powerState) 2992{ 2993 AbsoluteTime delta; 2994 UInt64 delta_ns; 2995 SInt32 delta_secs; 2996 SInt32 delay_secs; 2997 2998 // Calculate time difference using funky macro from clock.h. 2999 delta = currentTime; 3000 SUB_ABSOLUTETIME(&delta, &lastActivity); 3001 3002 // Figure it in seconds. 3003 absolutetime_to_nanoseconds(delta, &delta_ns); 3004 delta_secs = (SInt32)(delta_ns / NSEC_PER_SEC); 3005 3006 // Be paranoid about delta somehow exceeding timer period. 3007 if (delta_secs < (int) fIdleTimerPeriod) 3008 delay_secs = (int) fIdleTimerPeriod - delta_secs; 3009 else 3010 delay_secs = (int) fIdleTimerPeriod; 3011 3012 return (SInt32)delay_secs; 3013} 3014 3015//********************************************************************************* 3016// [public] start_PM_idle_timer 3017//********************************************************************************* 3018 3019void IOService::start_PM_idle_timer ( void ) 3020{ 3021 static const int maxTimeout = 100000; 3022 static const int minTimeout = 1; 3023 AbsoluteTime uptime, deadline; 3024 SInt32 idle_in = 0; 3025 boolean_t pending; 3026 3027 if (!initialized || !fIdleTimerPeriod) 3028 return; 3029 3030 IOLockLock(fActivityLock); 3031 3032 clock_get_uptime(&uptime); 3033 3034 // Subclasses may modify idle sleep algorithm 3035 idle_in = nextIdleTimeout(uptime, fDeviceActiveTimestamp, fCurrentPowerState); 3036 3037 // Check for out-of range responses 3038 if (idle_in > maxTimeout) 3039 { 3040 // use standard implementation 3041 idle_in = IOService::nextIdleTimeout(uptime, 3042 fDeviceActiveTimestamp, 3043 fCurrentPowerState); 3044 } else if (idle_in < minTimeout) { 3045 idle_in = fIdleTimerPeriod; 3046 } 3047 3048 IOLockUnlock(fActivityLock); 3049 3050 retain(); 3051 clock_interval_to_absolutetime_interval(idle_in, kSecondScale, &deadline); 3052 ADD_ABSOLUTETIME(&deadline, &uptime); 3053 pending = thread_call_enter_delayed(fIdleTimer, deadline); 3054 if (pending) release(); 3055} 3056 3057//********************************************************************************* 3058// idle_timer_expired 3059//********************************************************************************* 3060 3061static void 3062idle_timer_expired ( 3063 thread_call_param_t arg0, thread_call_param_t arg1 ) 3064{ 3065 IOService * me = (IOService *) arg0; 3066 3067 if (gIOPMWorkLoop) 3068 gIOPMWorkLoop->runAction( 3069 OSMemberFunctionCast(IOWorkLoop::Action, me, 3070 &IOService::idleTimerExpired), 3071 me); 3072 3073 me->release(); 3074} 3075 3076//********************************************************************************* 3077// [private] idleTimerExpired 3078// 3079// The idle timer has expired. If there has been activity since the last 3080// expiration, just restart the timer and return. If there has not been 3081// activity, switch to the next lower power state and restart the timer. 3082//********************************************************************************* 3083 3084void IOService::idleTimerExpired( void ) 3085{ 3086 IOPMRequest * request; 3087 bool restartTimer = true; 3088 3089 if ( !initialized || !fIdleTimerPeriod || fLockedFlags.PMStop ) 3090 return; 3091 3092 IOLockLock(fActivityLock); 3093 3094 // Check for device activity (tickles) over last timer period. 3095 3096 if (fDeviceWasActive) 3097 { 3098 // Device was active - do not drop power, restart timer. 3099 fDeviceWasActive = false; 3100 } 3101 else if (!fIdleTimerIgnored) 3102 { 3103 // No device activity - drop power state by one level. 3104 // Decrement the cached tickle power state when possible. 3105 // This value may be (-1) before activityTickle() is called, 3106 // but the power drop request must be issued regardless. 3107 3108 if (fActivityTicklePowerState > 0) 3109 fActivityTicklePowerState--; 3110 3111 request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle ); 3112 if (request) 3113 { 3114 request->fArg0 = (void *) 0; // power state (irrelevant) 3115 request->fArg1 = (void *) false; // timer expiration (not tickle) 3116 request->fArg2 = (void *) false; // regular tickle 3117 submitPMRequest( request ); 3118 3119 // Do not restart timer until after the tickle request has been 3120 // processed. 3121 3122 restartTimer = false; 3123 } 3124 } 3125 3126 if (fAdvisoryTickled) 3127 { 3128 fAdvisoryTickled = false; 3129 } 3130 else if (fHasAdvisoryDesire) 3131 { 3132 // Want new tickles to turn into pm request after we drop the lock 3133 fAdvisoryTicklePowerState = kInvalidTicklePowerState; 3134 3135 request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle ); 3136 if (request) 3137 { 3138 request->fArg0 = (void *) 0; // power state (irrelevant) 3139 request->fArg1 = (void *) false; // timer expiration (not tickle) 3140 request->fArg2 = (void *) true; // advisory tickle 3141 submitPMRequest( request ); 3142 3143 // Do not restart timer until after the tickle request has been 3144 // processed. 3145 3146 restartTimer = false; 3147 } 3148 } 3149 3150 IOLockUnlock(fActivityLock); 3151 3152 if (restartTimer) 3153 start_PM_idle_timer(); 3154} 3155 3156#ifndef __LP64__ 3157//********************************************************************************* 3158// [deprecated] PM_idle_timer_expiration 3159//********************************************************************************* 3160 3161void IOService::PM_idle_timer_expiration ( void ) 3162{ 3163} 3164 3165//********************************************************************************* 3166// [deprecated] command_received 3167//********************************************************************************* 3168 3169void IOService::command_received ( void *statePtr , void *, void * , void * ) 3170{ 3171} 3172#endif /* !__LP64__ */ 3173 3174//********************************************************************************* 3175// [public] setAggressiveness 3176// 3177// Pass on the input parameters to all power domain children. All those which are 3178// power domains will pass it on to their children, etc. 3179//********************************************************************************* 3180 3181IOReturn IOService::setAggressiveness ( unsigned long type, unsigned long newLevel ) 3182{ 3183 return kIOReturnSuccess; 3184} 3185 3186//********************************************************************************* 3187// [public] getAggressiveness 3188// 3189// Called by the user client. 3190//********************************************************************************* 3191 3192IOReturn IOService::getAggressiveness ( unsigned long type, unsigned long * currentLevel ) 3193{ 3194 IOPMrootDomain * rootDomain = getPMRootDomain(); 3195 3196 if (!rootDomain) 3197 return kIOReturnNotReady; 3198 3199 return rootDomain->getAggressiveness( type, currentLevel ); 3200} 3201 3202//********************************************************************************* 3203// [public] getPowerState 3204// 3205//********************************************************************************* 3206 3207UInt32 IOService::getPowerState ( void ) 3208{ 3209 if (!initialized) 3210 return 0; 3211 3212 return fCurrentPowerState; 3213} 3214 3215#ifndef __LP64__ 3216//********************************************************************************* 3217// [deprecated] systemWake 3218// 3219// Pass this to all power domain children. All those which are 3220// power domains will pass it on to their children, etc. 3221//********************************************************************************* 3222 3223IOReturn IOService::systemWake ( void ) 3224{ 3225 OSIterator * iter; 3226 OSObject * next; 3227 IOPowerConnection * connection; 3228 IOService * theChild; 3229 3230 iter = getChildIterator(gIOPowerPlane); 3231 if ( iter ) 3232 { 3233 while ( (next = iter->getNextObject()) ) 3234 { 3235 if ( (connection = OSDynamicCast(IOPowerConnection, next)) ) 3236 { 3237 if (connection->getReadyFlag() == false) 3238 { 3239 PM_LOG3("[%s] %s: connection not ready\n", 3240 getName(), __FUNCTION__); 3241 continue; 3242 } 3243 3244 theChild = (IOService *)connection->copyChildEntry(gIOPowerPlane); 3245 if ( theChild ) 3246 { 3247 theChild->systemWake(); 3248 theChild->release(); 3249 } 3250 } 3251 } 3252 iter->release(); 3253 } 3254 3255 if ( fControllingDriver != NULL ) 3256 { 3257 if ( fControllingDriver->didYouWakeSystem() ) 3258 { 3259 makeUsable(); 3260 } 3261 } 3262 3263 return IOPMNoErr; 3264} 3265 3266//********************************************************************************* 3267// [deprecated] temperatureCriticalForZone 3268//********************************************************************************* 3269 3270IOReturn IOService::temperatureCriticalForZone ( IOService * whichZone ) 3271{ 3272 IOService * theParent; 3273 IOService * theNub; 3274 3275 OUR_PMLog(kPMLogCriticalTemp, 0, 0); 3276 3277 if ( inPlane(gIOPowerPlane) && !IS_PM_ROOT ) 3278 { 3279 theNub = (IOService *)copyParentEntry(gIOPowerPlane); 3280 if ( theNub ) 3281 { 3282 theParent = (IOService *)theNub->copyParentEntry(gIOPowerPlane); 3283 theNub->release(); 3284 if ( theParent ) 3285 { 3286 theParent->temperatureCriticalForZone(whichZone); 3287 theParent->release(); 3288 } 3289 } 3290 } 3291 return IOPMNoErr; 3292} 3293#endif /* !__LP64__ */ 3294 3295// MARK: - 3296// MARK: Power Change (Common) 3297 3298//********************************************************************************* 3299// [private] startPowerChange 3300// 3301// All power state changes starts here. 3302//********************************************************************************* 3303 3304IOReturn IOService::startPowerChange( 3305 IOPMPowerChangeFlags changeFlags, 3306 IOPMPowerStateIndex powerState, 3307 IOPMPowerFlags domainFlags, 3308 IOPowerConnection * parentConnection, 3309 IOPMPowerFlags parentFlags ) 3310{ 3311 PM_ASSERT_IN_GATE(); 3312 assert( fMachineState == kIOPM_Finished ); 3313 assert( powerState < fNumberOfPowerStates ); 3314 3315 if (powerState >= fNumberOfPowerStates) 3316 return IOPMAckImplied; 3317 3318 fIsPreChange = true; 3319 PM_ACTION_2(actionPowerChangeOverride, &powerState, &changeFlags); 3320 3321 // Forks to either Driver or Parent initiated power change paths. 3322 3323 fHeadNoteChangeFlags = changeFlags; 3324 fHeadNotePowerState = powerState; 3325 fHeadNotePowerArrayEntry = &fPowerStates[ powerState ]; 3326 fHeadNoteParentConnection = NULL; 3327 3328 if (changeFlags & kIOPMSelfInitiated) 3329 { 3330 if (changeFlags & kIOPMSynchronize) 3331 OurSyncStart(); 3332 else 3333 OurChangeStart(); 3334 return 0; 3335 } 3336 else 3337 { 3338 assert(changeFlags & kIOPMParentInitiated); 3339 fHeadNoteDomainFlags = domainFlags; 3340 fHeadNoteParentFlags = parentFlags; 3341 fHeadNoteParentConnection = parentConnection; 3342 return ParentChangeStart(); 3343 } 3344} 3345 3346//********************************************************************************* 3347// [private] notifyInterestedDrivers 3348//********************************************************************************* 3349 3350bool IOService::notifyInterestedDrivers ( void ) 3351{ 3352 IOPMinformee * informee; 3353 IOPMinformeeList * list = fInterestedDrivers; 3354 DriverCallParam * param; 3355 IOItemCount count; 3356 3357 PM_ASSERT_IN_GATE(); 3358 assert( fDriverCallParamCount == 0 ); 3359 assert( fHeadNotePendingAcks == 0 ); 3360 3361 fHeadNotePendingAcks = 0; 3362 3363 count = list->numberOfItems(); 3364 if (!count) 3365 goto done; // no interested drivers 3366 3367 // Allocate an array of interested drivers and their return values 3368 // for the callout thread. Everything else is still "owned" by the 3369 // PM work loop, which can run to process acknowledgePowerChange() 3370 // responses. 3371 3372 param = (DriverCallParam *) fDriverCallParamPtr; 3373 if (count > fDriverCallParamSlots) 3374 { 3375 if (fDriverCallParamSlots) 3376 { 3377 assert(fDriverCallParamPtr); 3378 IODelete(fDriverCallParamPtr, DriverCallParam, fDriverCallParamSlots); 3379 fDriverCallParamPtr = 0; 3380 fDriverCallParamSlots = 0; 3381 } 3382 3383 param = IONew(DriverCallParam, count); 3384 if (!param) 3385 goto done; // no memory 3386 3387 fDriverCallParamPtr = (void *) param; 3388 fDriverCallParamSlots = count; 3389 } 3390 3391 informee = list->firstInList(); 3392 assert(informee); 3393 for (IOItemCount i = 0; i < count; i++) 3394 { 3395 informee->timer = -1; 3396 param[i].Target = informee; 3397 informee->retain(); 3398 informee = list->nextInList( informee ); 3399 } 3400 3401 fDriverCallParamCount = count; 3402 fHeadNotePendingAcks = count; 3403 3404 // Block state machine and wait for callout completion. 3405 assert(!fDriverCallBusy); 3406 fDriverCallBusy = true; 3407 thread_call_enter( fDriverCallEntry ); 3408 return true; 3409 3410done: 3411 // Return false if there are no interested drivers or could not schedule 3412 // callout thread due to error. 3413 return false; 3414} 3415 3416//********************************************************************************* 3417// [private] notifyInterestedDriversDone 3418//********************************************************************************* 3419 3420void IOService::notifyInterestedDriversDone ( void ) 3421{ 3422 IOPMinformee * informee; 3423 IOItemCount count; 3424 DriverCallParam * param; 3425 IOReturn result; 3426 3427 PM_ASSERT_IN_GATE(); 3428 assert( fDriverCallBusy == false ); 3429 assert( fMachineState == kIOPM_DriverThreadCallDone ); 3430 3431 param = (DriverCallParam *) fDriverCallParamPtr; 3432 count = fDriverCallParamCount; 3433 3434 if (param && count) 3435 { 3436 for (IOItemCount i = 0; i < count; i++, param++) 3437 { 3438 informee = (IOPMinformee *) param->Target; 3439 result = param->Result; 3440 3441 if ((result == IOPMAckImplied) || (result < 0)) 3442 { 3443 // Interested driver return IOPMAckImplied. 3444 // If informee timer is zero, it must have de-registered 3445 // interest during the thread callout. That also drops 3446 // the pending ack count. 3447 3448 if (fHeadNotePendingAcks && informee->timer) 3449 fHeadNotePendingAcks--; 3450 3451 informee->timer = 0; 3452 } 3453 else if (informee->timer) 3454 { 3455 assert(informee->timer == -1); 3456 3457 // Driver has not acked, and has returned a positive result. 3458 // Enforce a minimum permissible timeout value. 3459 // Make the min value large enough so timeout is less likely 3460 // to occur if a driver misinterpreted that the return value 3461 // should be in microsecond units. And make it large enough 3462 // to be noticeable if a driver neglects to ack. 3463 3464 if (result < kMinAckTimeoutTicks) 3465 result = kMinAckTimeoutTicks; 3466 3467 informee->timer = (result / (ACK_TIMER_PERIOD / ns_per_us)) + 1; 3468 } 3469 // else, child has already acked or driver has removed interest, 3470 // and head_note_pendingAcks decremented. 3471 // informee may have been removed from the interested drivers list, 3472 // thus the informee must be retained across the callout. 3473 3474 informee->release(); 3475 } 3476 3477 fDriverCallParamCount = 0; 3478 3479 if ( fHeadNotePendingAcks ) 3480 { 3481 OUR_PMLog(kPMLogStartAckTimer, 0, 0); 3482 start_ack_timer(); 3483 } 3484 } 3485 3486 MS_POP(); // pushed by notifyAll() 3487 3488 // If interest acks are outstanding, wait for fHeadNotePendingAcks to become 3489 // zero before notifying children. This enforces the children after interest 3490 // ordering even for async interest clients. 3491 3492 if (!fHeadNotePendingAcks) 3493 { 3494 notifyChildren(); 3495 } 3496 else 3497 { 3498 MS_PUSH(fMachineState); 3499 fMachineState = kIOPM_NotifyChildrenStart; 3500 PM_LOG2("%s: %u outstanding async interest\n", 3501 getName(), fHeadNotePendingAcks); 3502 } 3503} 3504 3505//********************************************************************************* 3506// [private] notifyChildren 3507//********************************************************************************* 3508 3509void IOService::notifyChildren ( void ) 3510{ 3511 OSIterator * iter; 3512 OSObject * next; 3513 IOPowerConnection * connection; 3514 OSArray * children = 0; 3515 IOPMrootDomain * rootDomain; 3516 bool delayNotify = false; 3517 3518 if ((fHeadNotePowerState != fCurrentPowerState) && 3519 (IS_POWER_DROP == fIsPreChange) && 3520 ((rootDomain = getPMRootDomain()) == this)) 3521 { 3522 rootDomain->tracePoint( IS_POWER_DROP ? 3523 kIOPMTracePointSleepPowerPlaneDrivers : 3524 kIOPMTracePointWakePowerPlaneDrivers ); 3525 } 3526 3527 if (fStrictTreeOrder) 3528 children = OSArray::withCapacity(8); 3529 3530 // Sum child power consumption in notifyChild() 3531 fHeadNotePowerArrayEntry->staticPower = 0; 3532 3533 iter = getChildIterator(gIOPowerPlane); 3534 if ( iter ) 3535 { 3536 while ((next = iter->getNextObject())) 3537 { 3538 if ((connection = OSDynamicCast(IOPowerConnection, next))) 3539 { 3540 if (connection->getReadyFlag() == false) 3541 { 3542 PM_LOG3("[%s] %s: connection not ready\n", 3543 getName(), __FUNCTION__); 3544 continue; 3545 } 3546 3547 // Mechanism to postpone the did-change notification to 3548 // certain power children to order those children last. 3549 // Cannot be used together with strict tree ordering. 3550 3551 if (!fIsPreChange && 3552 (connection->delayChildNotification) && 3553 getPMRootDomain()->shouldDelayChildNotification(this)) 3554 { 3555 if (!children) 3556 { 3557 children = OSArray::withCapacity(8); 3558 if (children) 3559 delayNotify = true; 3560 } 3561 if (delayNotify) 3562 { 3563 children->setObject( connection ); 3564 continue; 3565 } 3566 } 3567 3568 if (!delayNotify && children) 3569 children->setObject( connection ); 3570 else 3571 notifyChild( connection ); 3572 } 3573 } 3574 iter->release(); 3575 } 3576 3577 if (children && (children->getCount() == 0)) 3578 { 3579 children->release(); 3580 children = 0; 3581 } 3582 if (children) 3583 { 3584 assert(fNotifyChildArray == 0); 3585 fNotifyChildArray = children; 3586 MS_PUSH(fMachineState); 3587 3588 if (delayNotify) 3589 { 3590 // Wait for exiting child notifications to complete, 3591 // before notifying the children in the array. 3592 fMachineState = kIOPM_NotifyChildrenDelayed; 3593 PM_LOG2("%s: %d children in delayed array\n", 3594 getName(), children->getCount()); 3595 } 3596 else 3597 { 3598 // Notify children in the array one at a time. 3599 fMachineState = kIOPM_NotifyChildrenOrdered; 3600 } 3601 } 3602} 3603 3604//********************************************************************************* 3605// [private] notifyChildrenOrdered 3606//********************************************************************************* 3607 3608void IOService::notifyChildrenOrdered ( void ) 3609{ 3610 PM_ASSERT_IN_GATE(); 3611 assert(fNotifyChildArray); 3612 assert(fMachineState == kIOPM_NotifyChildrenOrdered); 3613 3614 // Notify one child, wait for it to ack, then repeat for next child. 3615 // This is a workaround for some drivers with multiple instances at 3616 // the same branch in the power tree, but the driver is slow to power 3617 // up unless the tree ordering is observed. Problem observed only on 3618 // system wake, not on system sleep. 3619 // 3620 // We have the ability to power off in reverse child index order. 3621 // That works nicely on some machines, but not on all HW configs. 3622 3623 if (fNotifyChildArray->getCount()) 3624 { 3625 IOPowerConnection * connection; 3626 connection = (IOPowerConnection *) fNotifyChildArray->getObject(0); 3627 notifyChild( connection ); 3628 fNotifyChildArray->removeObject(0); 3629 } 3630 else 3631 { 3632 fNotifyChildArray->release(); 3633 fNotifyChildArray = 0; 3634 3635 MS_POP(); // pushed by notifyChildren() 3636 } 3637} 3638 3639//********************************************************************************* 3640// [private] notifyChildrenDelayed 3641//********************************************************************************* 3642 3643void IOService::notifyChildrenDelayed ( void ) 3644{ 3645 IOPowerConnection * connection; 3646 3647 PM_ASSERT_IN_GATE(); 3648 assert(fNotifyChildArray); 3649 assert(fMachineState == kIOPM_NotifyChildrenDelayed); 3650 3651 // Wait after all non-delayed children and interested drivers have ack'ed, 3652 // then notify all delayed children. When explicitly cancelled, interest 3653 // acks (and ack timer) may still be outstanding. 3654 3655 for (int i = 0; ; i++) 3656 { 3657 connection = (IOPowerConnection *) fNotifyChildArray->getObject(i); 3658 if (!connection) 3659 break; 3660 3661 notifyChild( connection ); 3662 } 3663 3664 PM_LOG2("%s: notified delayed children\n", getName()); 3665 fNotifyChildArray->release(); 3666 fNotifyChildArray = 0; 3667 3668 MS_POP(); // pushed by notifyChildren() 3669} 3670 3671//********************************************************************************* 3672// [private] notifyAll 3673//********************************************************************************* 3674 3675IOReturn IOService::notifyAll ( uint32_t nextMS ) 3676{ 3677 // Save the next machine_state to be restored by notifyInterestedDriversDone() 3678 3679 PM_ASSERT_IN_GATE(); 3680 MS_PUSH(nextMS); 3681 fMachineState = kIOPM_DriverThreadCallDone; 3682 fDriverCallReason = fIsPreChange ? 3683 kDriverCallInformPreChange : kDriverCallInformPostChange; 3684 3685 if (!notifyInterestedDrivers()) 3686 notifyInterestedDriversDone(); 3687 3688 return IOPMWillAckLater; 3689} 3690 3691//********************************************************************************* 3692// [private, static] pmDriverCallout 3693// 3694// Thread call context 3695//********************************************************************************* 3696 3697IOReturn IOService::actionDriverCalloutDone ( 3698 OSObject * target, 3699 void * arg0, void * arg1, 3700 void * arg2, void * arg3 ) 3701{ 3702 IOServicePM * pwrMgt = (IOServicePM *) arg0; 3703 3704 assert( fDriverCallBusy ); 3705 fDriverCallBusy = false; 3706 3707 assert(gIOPMWorkQueue); 3708 gIOPMWorkQueue->signalWorkAvailable(); 3709 3710 return kIOReturnSuccess; 3711} 3712 3713void IOService::pmDriverCallout ( IOService * from ) 3714{ 3715 assert(from); 3716 switch (from->fDriverCallReason) 3717 { 3718 case kDriverCallSetPowerState: 3719 from->driverSetPowerState(); 3720 break; 3721 3722 case kDriverCallInformPreChange: 3723 case kDriverCallInformPostChange: 3724 from->driverInformPowerChange(); 3725 break; 3726 3727 default: 3728 panic("IOService::pmDriverCallout bad machine state %x", 3729 from->fDriverCallReason); 3730 } 3731 3732 gIOPMWorkLoop->runAction(actionDriverCalloutDone, 3733 /* target */ from, 3734 /* arg0 */ (void *) from->pwrMgt ); 3735} 3736 3737//********************************************************************************* 3738// [private] driverSetPowerState 3739// 3740// Thread call context 3741//********************************************************************************* 3742 3743void IOService::driverSetPowerState ( void ) 3744{ 3745 IOPMPowerStateIndex powerState; 3746 DriverCallParam * param; 3747 IOPMDriverCallEntry callEntry; 3748 AbsoluteTime end; 3749 IOReturn result; 3750 uint32_t oldPowerState = getPowerState(); 3751 3752 assert( fDriverCallBusy ); 3753 assert( fDriverCallParamPtr ); 3754 assert( fDriverCallParamCount == 1 ); 3755 3756 param = (DriverCallParam *) fDriverCallParamPtr; 3757 powerState = fHeadNotePowerState; 3758 3759 if (assertPMDriverCall(&callEntry)) 3760 { 3761 OUR_PMLog( kPMLogProgramHardware, (uintptr_t) this, powerState); 3762 clock_get_uptime(&fDriverCallStartTime); 3763 result = fControllingDriver->setPowerState( powerState, this ); 3764 clock_get_uptime(&end); 3765 OUR_PMLog((UInt32) -kPMLogProgramHardware, (uintptr_t) this, (UInt32) result); 3766 3767 deassertPMDriverCall(&callEntry); 3768 3769 if (result < 0) 3770 { 3771 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n", 3772 fName, this, fCurrentPowerState, powerState, result); 3773 } 3774 3775#if LOG_SETPOWER_TIMES 3776 if ((result == IOPMAckImplied) || (result < 0)) 3777 { 3778 uint64_t nsec; 3779 3780 SUB_ABSOLUTETIME(&end, &fDriverCallStartTime); 3781 absolutetime_to_nanoseconds(end, &nsec); 3782 if (nsec > LOG_SETPOWER_TIMES) 3783 PM_LOG("%s::setPowerState(%p, %lu -> %lu) took %d ms\n", 3784 fName, this, fCurrentPowerState, powerState, NS_TO_MS(nsec)); 3785 3786 PMEventDetails *details = PMEventDetails::eventDetails( 3787 kIOPMEventTypeSetPowerStateImmediate, // type 3788 fName, // who 3789 (uintptr_t)this, // owner unique 3790 NULL, // interest name 3791 (uint8_t)oldPowerState, // old 3792 (uint8_t)powerState, // new 3793 0, // result 3794 NS_TO_US(nsec)); // usec completion time 3795 3796 getPMRootDomain()->recordAndReleasePMEventGated( details ); 3797 } 3798#endif 3799 } 3800 else 3801 result = kIOPMAckImplied; 3802 3803 param->Result = result; 3804} 3805 3806//********************************************************************************* 3807// [private] driverInformPowerChange 3808// 3809// Thread call context 3810//********************************************************************************* 3811 3812void IOService::driverInformPowerChange ( void ) 3813{ 3814 IOPMinformee * informee; 3815 IOService * driver; 3816 DriverCallParam * param; 3817 IOPMDriverCallEntry callEntry; 3818 IOPMPowerFlags powerFlags; 3819 IOPMPowerStateIndex powerState; 3820 AbsoluteTime end; 3821 IOReturn result; 3822 IOItemCount count; 3823 3824 assert( fDriverCallBusy ); 3825 assert( fDriverCallParamPtr ); 3826 assert( fDriverCallParamCount ); 3827 3828 param = (DriverCallParam *) fDriverCallParamPtr; 3829 count = fDriverCallParamCount; 3830 3831 powerFlags = fHeadNotePowerArrayEntry->capabilityFlags; 3832 powerState = fHeadNotePowerState; 3833 3834 for (IOItemCount i = 0; i < count; i++) 3835 { 3836 informee = (IOPMinformee *) param->Target; 3837 driver = informee->whatObject; 3838 3839 if (assertPMDriverCall(&callEntry, 0, informee)) 3840 { 3841 if (fDriverCallReason == kDriverCallInformPreChange) 3842 { 3843 OUR_PMLog(kPMLogInformDriverPreChange, (uintptr_t) this, powerState); 3844 clock_get_uptime(&informee->startTime); 3845 result = driver->powerStateWillChangeTo(powerFlags, powerState, this); 3846 clock_get_uptime(&end); 3847 OUR_PMLog((UInt32)-kPMLogInformDriverPreChange, (uintptr_t) this, result); 3848 } 3849 else 3850 { 3851 OUR_PMLog(kPMLogInformDriverPostChange, (uintptr_t) this, powerState); 3852 clock_get_uptime(&informee->startTime); 3853 result = driver->powerStateDidChangeTo(powerFlags, powerState, this); 3854 clock_get_uptime(&end); 3855 OUR_PMLog((UInt32)-kPMLogInformDriverPostChange, (uintptr_t) this, result); 3856 } 3857 3858 deassertPMDriverCall(&callEntry); 3859 3860#if LOG_SETPOWER_TIMES 3861 if ((result == IOPMAckImplied) || (result < 0)) 3862 { 3863 uint64_t nsec; 3864 3865 SUB_ABSOLUTETIME(&end, &informee->startTime); 3866 absolutetime_to_nanoseconds(end, &nsec); 3867 if (nsec > LOG_SETPOWER_TIMES) 3868 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) took %d ms\n", 3869 driver->getName(), 3870 (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did", 3871 driver, fName, fCurrentPowerState, powerState, NS_TO_MS(nsec)); 3872 3873 uint16_t logType = (fDriverCallReason == kDriverCallInformPreChange) 3874 ? kIOPMEventTypePSWillChangeTo 3875 : kIOPMEventTypePSDidChangeTo; 3876 3877 PMEventDetails *details = PMEventDetails::eventDetails( 3878 logType, // type 3879 fName, // who 3880 (uintptr_t)this, // owner unique 3881 driver->getName(), // interest name 3882 (uint8_t)fCurrentPowerState, // old 3883 (uint8_t)fHeadNotePowerState, // new 3884 0, // result 3885 NS_TO_US(nsec)); // usec completion time 3886 3887 getPMRootDomain()->recordAndReleasePMEventGated( details ); 3888 } 3889#endif 3890 } 3891 else 3892 result = kIOPMAckImplied; 3893 3894 param->Result = result; 3895 param++; 3896 } 3897} 3898 3899//********************************************************************************* 3900// [private] notifyChild 3901// 3902// Notify a power domain child of an upcoming power change. 3903// If the object acknowledges the current change, we return TRUE. 3904//********************************************************************************* 3905 3906bool IOService::notifyChild ( IOPowerConnection * theNub ) 3907{ 3908 IOReturn ret = IOPMAckImplied; 3909 unsigned long childPower; 3910 IOService * theChild; 3911 IOPMRequest * childRequest; 3912 IOPMPowerChangeFlags requestArg2; 3913 int requestType; 3914 3915 PM_ASSERT_IN_GATE(); 3916 theChild = (IOService *)(theNub->copyChildEntry(gIOPowerPlane)); 3917 if (!theChild) 3918 { 3919 return true; 3920 } 3921 3922 // Unless the child handles the notification immediately and returns 3923 // kIOPMAckImplied, we'll be awaiting their acknowledgement later. 3924 fHeadNotePendingAcks++; 3925 theNub->setAwaitingAck(true); 3926 3927 requestArg2 = fHeadNoteChangeFlags; 3928 if (fHeadNotePowerState < fCurrentPowerState) 3929 requestArg2 |= kIOPMDomainPowerDrop; 3930 3931 requestType = fIsPreChange ? 3932 kIOPMRequestTypePowerDomainWillChange : 3933 kIOPMRequestTypePowerDomainDidChange; 3934 3935 childRequest = acquirePMRequest( theChild, requestType ); 3936 if (childRequest) 3937 { 3938 theNub->retain(); 3939 childRequest->fArg0 = (void *) fHeadNotePowerArrayEntry->outputPowerFlags; 3940 childRequest->fArg1 = (void *) theNub; 3941 childRequest->fArg2 = (void *) requestArg2; 3942 theChild->submitPMRequest( childRequest ); 3943 ret = IOPMWillAckLater; 3944 } 3945 else 3946 { 3947 ret = IOPMAckImplied; 3948 fHeadNotePendingAcks--; 3949 theNub->setAwaitingAck(false); 3950 childPower = theChild->currentPowerConsumption(); 3951 if ( childPower == kIOPMUnknown ) 3952 { 3953 fHeadNotePowerArrayEntry->staticPower = kIOPMUnknown; 3954 } else { 3955 if (fHeadNotePowerArrayEntry->staticPower != kIOPMUnknown ) 3956 fHeadNotePowerArrayEntry->staticPower += childPower; 3957 } 3958 } 3959 3960 theChild->release(); 3961 return (IOPMAckImplied == ret); 3962} 3963 3964//********************************************************************************* 3965// [private] notifyControllingDriver 3966//********************************************************************************* 3967 3968bool IOService::notifyControllingDriver ( void ) 3969{ 3970 DriverCallParam * param; 3971 3972 PM_ASSERT_IN_GATE(); 3973 assert( fDriverCallParamCount == 0 ); 3974 assert( fControllingDriver ); 3975 3976 if (fInitialSetPowerState) 3977 { 3978 fInitialSetPowerState = false; 3979 fHeadNoteChangeFlags |= kIOPMInitialPowerChange; 3980 3981 // Driver specified flag to skip the inital setPowerState() 3982 if (fHeadNotePowerArrayEntry->capabilityFlags & kIOPMInitialDeviceState) 3983 { 3984 return false; 3985 } 3986 } 3987 3988 param = (DriverCallParam *) fDriverCallParamPtr; 3989 if (!param) 3990 { 3991 param = IONew(DriverCallParam, 1); 3992 if (!param) 3993 return false; // no memory 3994 3995 fDriverCallParamPtr = (void *) param; 3996 fDriverCallParamSlots = 1; 3997 } 3998 3999 param->Target = fControllingDriver; 4000 fDriverCallParamCount = 1; 4001 fDriverTimer = -1; 4002 4003 // Block state machine and wait for callout completion. 4004 assert(!fDriverCallBusy); 4005 fDriverCallBusy = true; 4006 thread_call_enter( fDriverCallEntry ); 4007 4008 return true; 4009} 4010 4011//********************************************************************************* 4012// [private] notifyControllingDriverDone 4013//********************************************************************************* 4014 4015void IOService::notifyControllingDriverDone( void ) 4016{ 4017 DriverCallParam * param; 4018 IOReturn result; 4019 4020 PM_ASSERT_IN_GATE(); 4021 param = (DriverCallParam *) fDriverCallParamPtr; 4022 4023 assert( fDriverCallBusy == false ); 4024 assert( fMachineState == kIOPM_DriverThreadCallDone ); 4025 4026 if (param && fDriverCallParamCount) 4027 { 4028 assert(fDriverCallParamCount == 1); 4029 4030 // the return value from setPowerState() 4031 result = param->Result; 4032 4033 if ((result == IOPMAckImplied) || (result < 0)) 4034 { 4035 fDriverTimer = 0; 4036 } 4037 else if (fDriverTimer) 4038 { 4039 assert(fDriverTimer == -1); 4040 4041 // Driver has not acked, and has returned a positive result. 4042 // Enforce a minimum permissible timeout value. 4043 // Make the min value large enough so timeout is less likely 4044 // to occur if a driver misinterpreted that the return value 4045 // should be in microsecond units. And make it large enough 4046 // to be noticeable if a driver neglects to ack. 4047 4048 if (result < kMinAckTimeoutTicks) 4049 result = kMinAckTimeoutTicks; 4050 4051 fDriverTimer = (result / (ACK_TIMER_PERIOD / ns_per_us)) + 1; 4052 } 4053 // else, child has already acked and driver_timer reset to 0. 4054 4055 fDriverCallParamCount = 0; 4056 4057 if ( fDriverTimer ) 4058 { 4059 OUR_PMLog(kPMLogStartAckTimer, 0, 0); 4060 start_ack_timer(); 4061 } 4062 } 4063 4064 MS_POP(); // pushed by OurChangeSetPowerState() 4065 fIsPreChange = false; 4066} 4067 4068//********************************************************************************* 4069// [private] all_done 4070// 4071// A power change is done. 4072//********************************************************************************* 4073 4074void IOService::all_done ( void ) 4075{ 4076 IOPMPowerStateIndex prevPowerState; 4077 const IOPMPSEntry * powerStatePtr; 4078 IOPMDriverCallEntry callEntry; 4079 uint32_t prevMachineState = fMachineState; 4080 bool callAction = false; 4081 4082 fMachineState = kIOPM_Finished; 4083 4084 if ((fHeadNoteChangeFlags & kIOPMSynchronize) && 4085 ((prevMachineState == kIOPM_Finished) || 4086 (prevMachineState == kIOPM_SyncFinish))) 4087 { 4088 // Sync operation and no power change occurred. 4089 // Do not inform driver and clients about this request completion, 4090 // except for the originator (root domain). 4091 4092 PM_ACTION_2(actionPowerChangeDone, 4093 fHeadNotePowerState, fHeadNoteChangeFlags); 4094 4095 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree) 4096 { 4097 powerChangeDone(fCurrentPowerState); 4098 } 4099 else if (fAdvisoryTickleUsed) 4100 { 4101 // Not root domain and advisory tickle target 4102 // Re-adjust power after power tree sync at the 'did' pass 4103 if (!fAdjustPowerScheduled && 4104 (fHeadNoteChangeFlags & kIOPMDomainDidChange)) 4105 { 4106 IOPMRequest * request; 4107 request = acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState ); 4108 if (request) 4109 { 4110 submitPMRequest( request ); 4111 fAdjustPowerScheduled = true; 4112 } 4113 } 4114 } 4115 4116 return; 4117 } 4118 4119 // our power change 4120 if ( fHeadNoteChangeFlags & kIOPMSelfInitiated ) 4121 { 4122 // could our driver switch to the new state? 4123 if ( !( fHeadNoteChangeFlags & kIOPMNotDone) ) 4124 { 4125 trackSystemSleepPreventers( 4126 fCurrentPowerState, fHeadNotePowerState, fHeadNoteChangeFlags); 4127 4128 // we changed, tell our parent 4129 requestDomainPower(fHeadNotePowerState); 4130 4131 // yes, did power raise? 4132 if ( fCurrentPowerState < fHeadNotePowerState ) 4133 { 4134 // yes, inform clients and apps 4135 tellChangeUp (fHeadNotePowerState); 4136 } 4137 prevPowerState = fCurrentPowerState; 4138 // either way 4139 fCurrentPowerState = fHeadNotePowerState; 4140#if PM_VARS_SUPPORT 4141 fPMVars->myCurrentState = fCurrentPowerState; 4142#endif 4143 OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, prevPowerState); 4144 PM_ACTION_2(actionPowerChangeDone, 4145 fHeadNotePowerState, fHeadNoteChangeFlags); 4146 callAction = true; 4147 4148 powerStatePtr = &fPowerStates[fCurrentPowerState]; 4149 fCurrentCapabilityFlags = powerStatePtr->capabilityFlags; 4150 if (fCurrentCapabilityFlags & kIOPMStaticPowerValid) 4151 fCurrentPowerConsumption = powerStatePtr->staticPower; 4152 4153 // inform subclass policy-maker 4154 if (fPCDFunctionOverride && fParentsKnowState && 4155 assertPMDriverCall(&callEntry, kIOPMADC_NoInactiveCheck)) 4156 { 4157 powerChangeDone(prevPowerState); 4158 deassertPMDriverCall(&callEntry); 4159 } 4160 } 4161 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride) 4162 { 4163 // changePowerStateWithOverrideTo() was cancelled 4164 fOverrideMaxPowerState = kIOPMPowerStateMax; 4165 } 4166 } 4167 4168 // parent's power change 4169 if ( fHeadNoteChangeFlags & kIOPMParentInitiated) 4170 { 4171 if (((fHeadNoteChangeFlags & kIOPMDomainWillChange) && 4172 (fCurrentPowerState >= fHeadNotePowerState)) || 4173 ((fHeadNoteChangeFlags & kIOPMDomainDidChange) && 4174 (fCurrentPowerState < fHeadNotePowerState))) 4175 { 4176 trackSystemSleepPreventers( 4177 fCurrentPowerState, fHeadNotePowerState, fHeadNoteChangeFlags); 4178 4179 // did power raise? 4180 if ( fCurrentPowerState < fHeadNotePowerState ) 4181 { 4182 // yes, inform clients and apps 4183 tellChangeUp (fHeadNotePowerState); 4184 } 4185 // either way 4186 prevPowerState = fCurrentPowerState; 4187 fCurrentPowerState = fHeadNotePowerState; 4188#if PM_VARS_SUPPORT 4189 fPMVars->myCurrentState = fCurrentPowerState; 4190#endif 4191 fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fHeadNoteDomainFlags); 4192 4193 OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, prevPowerState); 4194 PM_ACTION_2(actionPowerChangeDone, 4195 fHeadNotePowerState, fHeadNoteChangeFlags); 4196 callAction = true; 4197 4198 powerStatePtr = &fPowerStates[fCurrentPowerState]; 4199 fCurrentCapabilityFlags = powerStatePtr->capabilityFlags; 4200 if (fCurrentCapabilityFlags & kIOPMStaticPowerValid) 4201 fCurrentPowerConsumption = powerStatePtr->staticPower; 4202 4203 // inform subclass policy-maker 4204 if (fPCDFunctionOverride && fParentsKnowState && 4205 assertPMDriverCall(&callEntry, kIOPMADC_NoInactiveCheck)) 4206 { 4207 powerChangeDone(prevPowerState); 4208 deassertPMDriverCall(&callEntry); 4209 } 4210 } 4211 } 4212 4213 // When power rises enough to satisfy the tickle's desire for more power, 4214 // the condition preventing idle-timer from dropping power is removed. 4215 4216 if (fCurrentPowerState >= fIdleTimerMinPowerState) 4217 { 4218 fIdleTimerMinPowerState = 0; 4219 } 4220 4221 if (!callAction) 4222 { 4223 PM_ACTION_2(actionPowerChangeDone, 4224 fHeadNotePowerState, fHeadNoteChangeFlags); 4225 } 4226} 4227 4228// MARK: - 4229// MARK: Power Change Initiated by Driver 4230 4231//********************************************************************************* 4232// [private] OurChangeStart 4233// 4234// Begin the processing of a power change initiated by us. 4235//********************************************************************************* 4236 4237void IOService::OurChangeStart ( void ) 4238{ 4239 PM_ASSERT_IN_GATE(); 4240 OUR_PMLog( kPMLogStartDeviceChange, fHeadNotePowerState, fCurrentPowerState ); 4241 4242 // fMaxPowerState is our maximum possible power state based on the current 4243 // power state of our parents. If we are trying to raise power beyond the 4244 // maximum, send an async request for more power to all parents. 4245 4246 if (!IS_PM_ROOT && (fMaxPowerState < fHeadNotePowerState)) 4247 { 4248 fHeadNoteChangeFlags |= kIOPMNotDone; 4249 requestDomainPower(fHeadNotePowerState); 4250 OurChangeFinish(); 4251 return; 4252 } 4253 4254 // Redundant power changes skips to the end of the state machine. 4255 4256 if (!fInitialPowerChange && (fHeadNotePowerState == fCurrentPowerState)) 4257 { 4258 OurChangeFinish(); 4259 return; 4260 } 4261 fInitialPowerChange = false; 4262 4263 // Change started, but may not complete... 4264 // Can be canceled (power drop) or deferred (power rise). 4265 4266 PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags); 4267 4268 // Two separate paths, depending if power is being raised or lowered. 4269 // Lowering power is subject to approval by clients of this service. 4270 4271 if (IS_POWER_DROP) 4272 { 4273 fDoNotPowerDown = false; 4274 4275 // Ask for persmission to drop power state 4276 fMachineState = kIOPM_OurChangeTellClientsPowerDown; 4277 fOutOfBandParameter = kNotifyApps; 4278 askChangeDown(fHeadNotePowerState); 4279 } 4280 else 4281 { 4282 // This service is raising power and parents are able to support the 4283 // new power state. However a parent may have already committed to 4284 // drop power, which might force this object to temporarily drop power. 4285 // This results in "oscillations" before the state machines converge 4286 // to a steady state. 4287 // 4288 // To prevent this, a child must make a power reservation against all 4289 // parents before raising power. If the reservation fails, indicating 4290 // that the child will be unable to sustain the higher power state, 4291 // then the child will signal the parent to adjust power, and the child 4292 // will defer its power change. 4293 4294 IOReturn ret; 4295 4296 // Reserve parent power necessary to achieve fHeadNotePowerState. 4297 ret = requestDomainPower( fHeadNotePowerState, kReserveDomainPower ); 4298 if (ret != kIOReturnSuccess) 4299 { 4300 // Reservation failed, defer power rise. 4301 fHeadNoteChangeFlags |= kIOPMNotDone; 4302 OurChangeFinish(); 4303 return; 4304 } 4305 4306 OurChangeTellCapabilityWillChange(); 4307 } 4308} 4309 4310//********************************************************************************* 4311 4312struct IOPMRequestDomainPowerContext { 4313 IOService * child; // the requesting child 4314 IOPMPowerFlags requestPowerFlags; // power flags requested by child 4315}; 4316 4317static void 4318requestDomainPowerApplier( 4319 IORegistryEntry * entry, 4320 void * inContext ) 4321{ 4322 IOPowerConnection * connection; 4323 IOService * parent; 4324 IOPMRequestDomainPowerContext * context; 4325 4326 if ((connection = OSDynamicCast(IOPowerConnection, entry)) == 0) 4327 return; 4328 parent = (IOService *) connection->copyParentEntry(gIOPowerPlane); 4329 if (!parent) 4330 return; 4331 4332 assert(inContext); 4333 context = (IOPMRequestDomainPowerContext *) inContext; 4334 4335 if (connection->parentKnowsState() && connection->getReadyFlag()) 4336 { 4337 parent->requestPowerDomainState( 4338 context->requestPowerFlags, 4339 connection, 4340 IOPMLowestState); 4341 } 4342 4343 parent->release(); 4344} 4345 4346//********************************************************************************* 4347// [private] requestDomainPower 4348//********************************************************************************* 4349 4350IOReturn IOService::requestDomainPower( 4351 IOPMPowerStateIndex ourPowerState, 4352 IOOptionBits options ) 4353{ 4354 IOPMPowerFlags requestPowerFlags; 4355 IOPMPowerStateIndex maxPowerState; 4356 IOPMRequestDomainPowerContext context; 4357 4358 PM_ASSERT_IN_GATE(); 4359 assert(ourPowerState < fNumberOfPowerStates); 4360 if (ourPowerState >= fNumberOfPowerStates) 4361 return kIOReturnBadArgument; 4362 if (IS_PM_ROOT) 4363 return kIOReturnSuccess; 4364 4365 // Fetch the input power flags for the requested power state. 4366 // Parent request is stated in terms of required power flags. 4367 4368 requestPowerFlags = fPowerStates[ourPowerState].inputPowerFlags; 4369 4370 // Disregard the "previous request" for power reservation. 4371 4372 if (((options & kReserveDomainPower) == 0) && 4373 (fPreviousRequestPowerFlags == requestPowerFlags)) 4374 { 4375 // skip if domain already knows our requirements 4376 goto done; 4377 } 4378 fPreviousRequestPowerFlags = requestPowerFlags; 4379 4380 context.child = this; 4381 context.requestPowerFlags = requestPowerFlags; 4382 fHeadNoteDomainTargetFlags = 0; 4383 applyToParents(requestDomainPowerApplier, &context, gIOPowerPlane); 4384 4385 if (options & kReserveDomainPower) 4386 { 4387 maxPowerState = fControllingDriver->maxCapabilityForDomainState( 4388 fHeadNoteDomainTargetFlags ); 4389 4390 if (maxPowerState < fHeadNotePowerState) 4391 { 4392 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n", 4393 getName(), 4394 (uint32_t) ourPowerState, (uint32_t) requestPowerFlags, 4395 (uint32_t) maxPowerState, (uint32_t) fHeadNoteDomainTargetFlags); 4396 return kIOReturnNoPower; 4397 } 4398 } 4399 4400done: 4401 return kIOReturnSuccess; 4402} 4403 4404//********************************************************************************* 4405// [private] OurSyncStart 4406//********************************************************************************* 4407 4408void IOService::OurSyncStart ( void ) 4409{ 4410 PM_ASSERT_IN_GATE(); 4411 4412 if (fInitialPowerChange) 4413 return; 4414 4415 PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags); 4416 4417 if (fHeadNoteChangeFlags & kIOPMNotDone) 4418 { 4419 OurChangeFinish(); 4420 return; 4421 } 4422 4423 if (fHeadNoteChangeFlags & kIOPMSyncTellPowerDown) 4424 { 4425 fDoNotPowerDown = false; 4426 4427 // Ask for permission to drop power state 4428 fMachineState = kIOPM_SyncTellClientsPowerDown; 4429 fOutOfBandParameter = kNotifyApps; 4430 askChangeDown(fHeadNotePowerState); 4431 } 4432 else 4433 { 4434 // Only inform capability app and clients. 4435 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange ); 4436 } 4437} 4438 4439//********************************************************************************* 4440// [private] OurChangeTellClientsPowerDown 4441// 4442// All applications and kernel clients have acknowledged our permission to drop 4443// power. Here we notify them that we will lower the power and wait for acks. 4444//********************************************************************************* 4445 4446void IOService::OurChangeTellClientsPowerDown ( void ) 4447{ 4448 fMachineState = kIOPM_OurChangeTellPriorityClientsPowerDown; 4449 tellChangeDown1(fHeadNotePowerState); 4450} 4451 4452//********************************************************************************* 4453// [private] OurChangeTellPriorityClientsPowerDown 4454// 4455// All applications and kernel clients have acknowledged our intention to drop 4456// power. Here we notify "priority" clients that we are lowering power. 4457//********************************************************************************* 4458 4459void IOService::OurChangeTellPriorityClientsPowerDown ( void ) 4460{ 4461 fMachineState = kIOPM_OurChangeNotifyInterestedDriversWillChange; 4462 tellChangeDown2(fHeadNotePowerState); 4463} 4464 4465//********************************************************************************* 4466// [private] OurChangeTellCapabilityWillChange 4467// 4468// Extra stage for root domain to notify apps and drivers about the 4469// system capability change when raising power state. 4470//********************************************************************************* 4471 4472void IOService::OurChangeTellCapabilityWillChange ( void ) 4473{ 4474 if (!IS_ROOT_DOMAIN) 4475 return OurChangeNotifyInterestedDriversWillChange(); 4476 4477 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange ); 4478} 4479 4480//********************************************************************************* 4481// [private] OurChangeNotifyInterestedDriversWillChange 4482// 4483// All applications and kernel clients have acknowledged our power state change. 4484// Here we notify interested drivers pre-change. 4485//********************************************************************************* 4486 4487void IOService::OurChangeNotifyInterestedDriversWillChange ( void ) 4488{ 4489 IOPMrootDomain * rootDomain; 4490 if ((rootDomain = getPMRootDomain()) == this) 4491 { 4492 if (IS_POWER_DROP) 4493 { 4494 rootDomain->tracePoint( kIOPMTracePointSleepWillChangeInterests ); 4495 4496 PMEventDetails *details = PMEventDetails::eventDetails( 4497 kIOPMEventTypeAppNotificationsFinished, 4498 NULL, 4499 100, 4500 kIOReturnSuccess); 4501 rootDomain->recordAndReleasePMEventGated( details ); 4502 } 4503 else 4504 rootDomain->tracePoint( kIOPMTracePointWakeWillChangeInterests ); 4505 } 4506 4507 notifyAll( kIOPM_OurChangeSetPowerState ); 4508} 4509 4510//********************************************************************************* 4511// [private] OurChangeSetPowerState 4512// 4513// Instruct our controlling driver to program the hardware for the power state 4514// change. Wait for async completions. 4515//********************************************************************************* 4516 4517void IOService::OurChangeSetPowerState ( void ) 4518{ 4519 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle ); 4520 fMachineState = kIOPM_DriverThreadCallDone; 4521 fDriverCallReason = kDriverCallSetPowerState; 4522 4523 if (notifyControllingDriver() == false) 4524 notifyControllingDriverDone(); 4525} 4526 4527//********************************************************************************* 4528// [private] OurChangeWaitForPowerSettle 4529// 4530// Our controlling driver has completed the power state change we initiated. 4531// Wait for the driver specified settle time to expire. 4532//********************************************************************************* 4533 4534void IOService::OurChangeWaitForPowerSettle ( void ) 4535{ 4536 fMachineState = kIOPM_OurChangeNotifyInterestedDriversDidChange; 4537 startSettleTimer(); 4538} 4539 4540//********************************************************************************* 4541// [private] OurChangeNotifyInterestedDriversDidChange 4542// 4543// Power has settled on a power change we initiated. Here we notify 4544// all our interested drivers post-change. 4545//********************************************************************************* 4546 4547void IOService::OurChangeNotifyInterestedDriversDidChange ( void ) 4548{ 4549 IOPMrootDomain * rootDomain; 4550 if ((rootDomain = getPMRootDomain()) == this) 4551 { 4552 rootDomain->tracePoint( IS_POWER_DROP ? 4553 kIOPMTracePointSleepDidChangeInterests : 4554 kIOPMTracePointWakeDidChangeInterests ); 4555 } 4556 4557 notifyAll( kIOPM_OurChangeTellCapabilityDidChange ); 4558} 4559 4560//********************************************************************************* 4561// [private] OurChangeTellCapabilityDidChange 4562// 4563// For root domain to notify capability power-change. 4564//********************************************************************************* 4565 4566void IOService::OurChangeTellCapabilityDidChange ( void ) 4567{ 4568 if (!IS_ROOT_DOMAIN) 4569 return OurChangeFinish(); 4570 4571 getPMRootDomain()->tracePoint( IS_POWER_DROP ? 4572 kIOPMTracePointSleepCapabilityClients : 4573 kIOPMTracePointWakeCapabilityClients ); 4574 4575 tellSystemCapabilityChange( kIOPM_OurChangeFinish ); 4576} 4577 4578//********************************************************************************* 4579// [private] OurChangeFinish 4580// 4581// Done with this self-induced power state change. 4582//********************************************************************************* 4583 4584void IOService::OurChangeFinish ( void ) 4585{ 4586 all_done(); 4587} 4588 4589// MARK: - 4590// MARK: Power Change Initiated by Parent 4591 4592//********************************************************************************* 4593// [private] ParentChangeStart 4594// 4595// Here we begin the processing of a power change initiated by our parent. 4596//********************************************************************************* 4597 4598IOReturn IOService::ParentChangeStart ( void ) 4599{ 4600 PM_ASSERT_IN_GATE(); 4601 OUR_PMLog( kPMLogStartParentChange, fHeadNotePowerState, fCurrentPowerState ); 4602 4603 // Power domain is lowering power 4604 if ( fHeadNotePowerState < fCurrentPowerState ) 4605 { 4606 // Piggy-back idle timer cancellation on a parent down 4607 if (0 == fHeadNotePowerState) 4608 ParentChangeCancelIdleTimer(fHeadNotePowerState); 4609 4610 // TODO: redundant? See handlePowerDomainWillChangeTo() 4611 setParentInfo( fHeadNoteParentFlags, fHeadNoteParentConnection, true ); 4612 4613 PM_ACTION_2(actionPowerChangeStart, fHeadNotePowerState, &fHeadNoteChangeFlags); 4614 4615 // Tell apps and kernel clients 4616 fInitialPowerChange = false; 4617 fMachineState = kIOPM_ParentChangeTellPriorityClientsPowerDown; 4618 tellChangeDown1(fHeadNotePowerState); 4619 return IOPMWillAckLater; 4620 } 4621 4622 // Power domain is raising power 4623 if ( fHeadNotePowerState > fCurrentPowerState ) 4624 { 4625 if ( fDesiredPowerState > fCurrentPowerState ) 4626 { 4627 if ( fDesiredPowerState < fHeadNotePowerState ) 4628 { 4629 // We power up, but not all the way 4630 fHeadNotePowerState = fDesiredPowerState; 4631 fHeadNotePowerArrayEntry = &fPowerStates[fDesiredPowerState]; 4632 OUR_PMLog(kPMLogAmendParentChange, fHeadNotePowerState, 0); 4633 } 4634 } else { 4635 // We don't need to change 4636 fHeadNotePowerState = fCurrentPowerState; 4637 fHeadNotePowerArrayEntry = &fPowerStates[fCurrentPowerState]; 4638 OUR_PMLog(kPMLogAmendParentChange, fHeadNotePowerState, 0); 4639 } 4640 } 4641 4642 if ( fHeadNoteChangeFlags & kIOPMDomainDidChange ) 4643 { 4644 if ( fHeadNotePowerState > fCurrentPowerState ) 4645 { 4646 PM_ACTION_2(actionPowerChangeStart, 4647 fHeadNotePowerState, &fHeadNoteChangeFlags); 4648 4649 // Parent did change up - start our change up 4650 fInitialPowerChange = false; 4651 ParentChangeTellCapabilityWillChange(); 4652 return IOPMWillAckLater; 4653 } 4654 else if (fHeadNoteChangeFlags & kIOPMSynchronize) 4655 { 4656 // We do not need to change power state, but notify 4657 // children to propagate tree synchronization. 4658 fMachineState = kIOPM_SyncNotifyDidChange; 4659 fDriverCallReason = kDriverCallInformPreChange; 4660 notifyChildren(); 4661 return IOPMWillAckLater; 4662 } 4663 } 4664 4665 all_done(); 4666 return IOPMAckImplied; 4667} 4668 4669//********************************************************************************* 4670// [private] ParentChangeTellPriorityClientsPowerDown 4671// 4672// All applications and kernel clients have acknowledged our intention to drop 4673// power. Here we notify "priority" clients that we are lowering power. 4674//********************************************************************************* 4675 4676void IOService::ParentChangeTellPriorityClientsPowerDown ( void ) 4677{ 4678 fMachineState = kIOPM_ParentChangeNotifyInterestedDriversWillChange; 4679 tellChangeDown2(fHeadNotePowerState); 4680} 4681 4682//********************************************************************************* 4683// [private] ParentChangeTellCapabilityWillChange 4684// 4685// All (legacy) applications and kernel clients have acknowledged, extra stage for 4686// root domain to notify apps and drivers about the system capability change. 4687//********************************************************************************* 4688 4689void IOService::ParentChangeTellCapabilityWillChange ( void ) 4690{ 4691 if (!IS_ROOT_DOMAIN) 4692 return ParentChangeNotifyInterestedDriversWillChange(); 4693 4694 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange ); 4695} 4696 4697//********************************************************************************* 4698// [private] ParentChangeNotifyInterestedDriversWillChange 4699// 4700// All applications and kernel clients have acknowledged our power state change. 4701// Here we notify interested drivers pre-change. 4702//********************************************************************************* 4703 4704void IOService::ParentChangeNotifyInterestedDriversWillChange ( void ) 4705{ 4706 notifyAll( kIOPM_ParentChangeSetPowerState ); 4707} 4708 4709//********************************************************************************* 4710// [private] ParentChangeSetPowerState 4711// 4712// Instruct our controlling driver to program the hardware for the power state 4713// change. Wait for async completions. 4714//********************************************************************************* 4715 4716void IOService::ParentChangeSetPowerState ( void ) 4717{ 4718 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle ); 4719 fMachineState = kIOPM_DriverThreadCallDone; 4720 fDriverCallReason = kDriverCallSetPowerState; 4721 4722 if (notifyControllingDriver() == false) 4723 notifyControllingDriverDone(); 4724} 4725 4726//********************************************************************************* 4727// [private] ParentChangeWaitForPowerSettle 4728// 4729// Our controlling driver has completed the power state change initiated by our 4730// parent. Wait for the driver specified settle time to expire. 4731//********************************************************************************* 4732 4733void IOService::ParentChangeWaitForPowerSettle ( void ) 4734{ 4735 fMachineState = kIOPM_ParentChangeNotifyInterestedDriversDidChange; 4736 startSettleTimer(); 4737} 4738 4739//********************************************************************************* 4740// [private] ParentChangeNotifyInterestedDriversDidChange 4741// 4742// Power has settled on a power change initiated by our parent. Here we notify 4743// all our interested drivers post-change. 4744//********************************************************************************* 4745 4746void IOService::ParentChangeNotifyInterestedDriversDidChange ( void ) 4747{ 4748 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange ); 4749} 4750 4751//********************************************************************************* 4752// [private] ParentChangeTellCapabilityDidChange 4753// 4754// For root domain to notify capability power-change. 4755//********************************************************************************* 4756 4757void IOService::ParentChangeTellCapabilityDidChange ( void ) 4758{ 4759 if (!IS_ROOT_DOMAIN) 4760 return ParentChangeAcknowledgePowerChange(); 4761 4762 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange ); 4763} 4764 4765//********************************************************************************* 4766// [private] ParentAcknowledgePowerChange 4767// 4768// Acknowledge our power parent that our power change is done. 4769//********************************************************************************* 4770 4771void IOService::ParentChangeAcknowledgePowerChange ( void ) 4772{ 4773 IORegistryEntry * nub; 4774 IOService * parent; 4775 4776 nub = fHeadNoteParentConnection; 4777 nub->retain(); 4778 all_done(); 4779 parent = (IOService *)nub->copyParentEntry(gIOPowerPlane); 4780 if ( parent ) 4781 { 4782 parent->acknowledgePowerChange((IOService *)nub); 4783 parent->release(); 4784 } 4785 nub->release(); 4786} 4787 4788void IOService::ParentChangeCancelIdleTimer( IOPMPowerStateIndex newPowerState ) 4789{ 4790 AbsoluteTime now; 4791 uint64_t nsec; 4792 bool cancel = false; 4793 4794 // No ready or idle timer not in use 4795 if (!initialized || !fIdleTimerPeriod || fLockedFlags.PMStop || 4796 !fAdvisoryTickleUsed) 4797 return; 4798 4799 // Not allowed to induce artifical idle timeout 4800 if (fIdleTimerIgnored || fIdleTimerMinPowerState) 4801 goto done; 4802 4803 // Idle timer already has no influence 4804 if (!fDesiredPowerState || fIdleTimerStopped) 4805 goto done; 4806 4807 IOLockLock(fActivityLock); 4808 4809 if (!fDeviceWasActive) 4810 { 4811 // No tickles since the last idle timer expiration. 4812 // Safe to drop the device desire to zero. 4813 cancel = true; 4814 } 4815 else 4816 { 4817 // Was tickled since the last idle timer expiration, 4818 // but not in the last minute. 4819 clock_get_uptime(&now); 4820 SUB_ABSOLUTETIME(&now, &fDeviceActiveTimestamp); 4821 absolutetime_to_nanoseconds(now, &nsec); 4822 if (nsec >= kNoTickleCancelWindow) 4823 { 4824 cancel = true; 4825 } 4826 } 4827 4828 if (cancel) 4829 { 4830 // Force the next tickle to raise power state 4831 fActivityTicklePowerState = kInvalidTicklePowerState; 4832 fDeviceWasActive = false; 4833 } 4834 4835 IOLockUnlock(fActivityLock); 4836 4837 if (cancel) 4838 { 4839 // cancel idle timer 4840 if (fIdleTimer && thread_call_cancel(fIdleTimer)) 4841 release(); 4842 4843 updatePowerClient(gIOPMPowerClientDevice, 0); 4844 computeDesiredState(); 4845 4846 fIdleTimerStopped = true; 4847 } 4848 4849done: 4850 OUR_PMLog( kPMLogStartParentChange, fHeadNotePowerState, fCurrentPowerState ); 4851 PM_LOG("%s::%s cancel=%d\n", fName, __FUNCTION__, cancel); 4852} 4853 4854// MARK: - 4855// MARK: Ack and Settle timers 4856 4857//********************************************************************************* 4858// [private] settleTimerExpired 4859// 4860// Power has settled after our last change. Notify interested parties that 4861// there is a new power state. 4862//********************************************************************************* 4863 4864void IOService::settleTimerExpired( void ) 4865{ 4866 fSettleTimeUS = 0; 4867 gIOPMWorkQueue->signalWorkAvailable(); 4868} 4869 4870//********************************************************************************* 4871// settle_timer_expired 4872// 4873// Holds a retain while the settle timer callout is in flight. 4874//********************************************************************************* 4875 4876static void 4877settle_timer_expired( thread_call_param_t arg0, thread_call_param_t arg1 ) 4878{ 4879 IOService * me = (IOService *) arg0; 4880 4881 if (gIOPMWorkLoop && gIOPMWorkQueue) 4882 { 4883 gIOPMWorkLoop->runAction( 4884 OSMemberFunctionCast(IOWorkLoop::Action, me, &IOService::settleTimerExpired), 4885 me); 4886 } 4887 me->release(); 4888} 4889 4890//********************************************************************************* 4891// [private] startSettleTimer 4892// 4893// Calculate a power-settling delay in microseconds and start a timer. 4894//********************************************************************************* 4895 4896void IOService::startSettleTimer( void ) 4897{ 4898 AbsoluteTime deadline; 4899 IOPMPowerStateIndex i; 4900 uint32_t settleTime = 0; 4901 boolean_t pending; 4902 4903 PM_ASSERT_IN_GATE(); 4904 4905 i = fCurrentPowerState; 4906 4907 // lowering power 4908 if ( fHeadNotePowerState < fCurrentPowerState ) 4909 { 4910 while ( i > fHeadNotePowerState ) 4911 { 4912 settleTime += (uint32_t) fPowerStates[i].settleDownTime; 4913 i--; 4914 } 4915 } 4916 4917 // raising power 4918 if ( fHeadNotePowerState > fCurrentPowerState ) 4919 { 4920 while ( i < fHeadNotePowerState ) 4921 { 4922 settleTime += (uint32_t) fPowerStates[i+1].settleUpTime; 4923 i++; 4924 } 4925 } 4926 4927 if (settleTime) 4928 { 4929 retain(); 4930 clock_interval_to_deadline(settleTime, kMicrosecondScale, &deadline); 4931 pending = thread_call_enter_delayed(fSettleTimer, deadline); 4932 if (pending) release(); 4933 } 4934} 4935 4936//********************************************************************************* 4937// [private] ackTimerTick 4938// 4939// The acknowledgement timeout periodic timer has ticked. 4940// If we are awaiting acks for a power change notification, 4941// we decrement the timer word of each interested driver which hasn't acked. 4942// If a timer word becomes zero, we pretend the driver aknowledged. 4943// If we are waiting for the controlling driver to change the power 4944// state of the hardware, we decrement its timer word, and if it becomes 4945// zero, we pretend the driver acknowledged. 4946// 4947// Returns true if the timer tick made it possible to advance to the next 4948// machine state, false otherwise. 4949//********************************************************************************* 4950 4951#ifndef __LP64__ 4952void IOService::ack_timer_ticked ( void ) 4953{ 4954 assert(false); 4955} 4956#endif /* !__LP64__ */ 4957 4958bool IOService::ackTimerTick( void ) 4959{ 4960 IOPMinformee * nextObject; 4961 bool done = false; 4962 4963 PM_ASSERT_IN_GATE(); 4964 switch (fMachineState) { 4965 case kIOPM_OurChangeWaitForPowerSettle: 4966 case kIOPM_ParentChangeWaitForPowerSettle: 4967 // are we waiting for controlling driver to acknowledge? 4968 if ( fDriverTimer > 0 ) 4969 { 4970 // yes, decrement timer tick 4971 fDriverTimer--; 4972 if ( fDriverTimer == 0 ) 4973 { 4974 // controlling driver is tardy 4975 uint64_t nsec = computeTimeDeltaNS(&fDriverCallStartTime); 4976 OUR_PMLog(kPMLogCtrlDriverTardy, 0, 0); 4977 setProperty(kIOPMTardyAckSPSKey, kOSBooleanTrue); 4978 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n", 4979 fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec)); 4980 4981#if LOG_SETPOWER_TIMES 4982 PMEventDetails *details = PMEventDetails::eventDetails( 4983 kIOPMEventTypeSetPowerStateDelayed, // type 4984 fName, // who 4985 (uintptr_t)this, // owner unique 4986 NULL, // interest name 4987 (uint8_t)getPowerState(), // old 4988 0, // new 4989 kIOReturnTimeout, // result 4990 NS_TO_US(nsec)); // usec completion time 4991 4992 getPMRootDomain()->recordAndReleasePMEventGated( details ); 4993#endif 4994 4995 if (gIOKitDebug & kIOLogDebugPower) 4996 { 4997 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms", 4998 fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec)); 4999 } 5000 else 5001 { 5002 // Unblock state machine and pretend driver has acked. 5003 done = true; 5004 } 5005 } else { 5006 // still waiting, set timer again 5007 start_ack_timer(); 5008 } 5009 } 5010 break; 5011 5012 case kIOPM_NotifyChildrenStart: 5013 // are we waiting for interested parties to acknowledge? 5014 if ( fHeadNotePendingAcks != 0 ) 5015 { 5016 // yes, go through the list of interested drivers 5017 nextObject = fInterestedDrivers->firstInList(); 5018 // and check each one 5019 while ( nextObject != NULL ) 5020 { 5021 if ( nextObject->timer > 0 ) 5022 { 5023 nextObject->timer--; 5024 // this one should have acked by now 5025 if ( nextObject->timer == 0 ) 5026 { 5027 uint64_t nsec = computeTimeDeltaNS(&nextObject->startTime); 5028 OUR_PMLog(kPMLogIntDriverTardy, 0, 0); 5029 nextObject->whatObject->setProperty(kIOPMTardyAckPSCKey, kOSBooleanTrue); 5030 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n", 5031 nextObject->whatObject->getName(), 5032 (fDriverCallReason == kDriverCallInformPreChange) ? "Will" : "Did", 5033 nextObject->whatObject, fName, fCurrentPowerState, fHeadNotePowerState, 5034 NS_TO_MS(nsec)); 5035 5036#if LOG_SETPOWER_TIMES 5037 uint16_t logType = (fDriverCallReason == kDriverCallInformPreChange) 5038 ? kIOPMEventTypePSWillChangeTo 5039 : kIOPMEventTypePSDidChangeTo; 5040 5041 PMEventDetails *details = PMEventDetails::eventDetails( 5042 logType, // type 5043 fName, // who 5044 (uintptr_t)this, // owner unique 5045 nextObject->whatObject->getName(), // interest name 5046 (uint8_t)fCurrentPowerState, // old 5047 (uint8_t)fHeadNotePowerState, // new 5048 kIOReturnTimeout, // result 5049 NS_TO_US(nsec)); // usec completion time 5050 5051 getPMRootDomain()->recordAndReleasePMEventGated( details ); 5052#endif 5053 5054 // Pretend driver has acked. 5055 fHeadNotePendingAcks--; 5056 } 5057 } 5058 nextObject = fInterestedDrivers->nextInList(nextObject); 5059 } 5060 5061 // is that the last? 5062 if ( fHeadNotePendingAcks == 0 ) 5063 { 5064 // yes, we can continue 5065 done = true; 5066 } else { 5067 // no, set timer again 5068 start_ack_timer(); 5069 } 5070 } 5071 break; 5072 5073 // TODO: aggreggate this 5074 case kIOPM_OurChangeTellClientsPowerDown: 5075 case kIOPM_OurChangeTellPriorityClientsPowerDown: 5076 case kIOPM_OurChangeNotifyInterestedDriversWillChange: 5077 case kIOPM_ParentChangeTellPriorityClientsPowerDown: 5078 case kIOPM_ParentChangeNotifyInterestedDriversWillChange: 5079 case kIOPM_SyncTellClientsPowerDown: 5080 case kIOPM_SyncTellPriorityClientsPowerDown: 5081 case kIOPM_SyncNotifyWillChange: 5082 case kIOPM_TellCapabilityChangeDone: 5083 // apps didn't respond in time 5084 cleanClientResponses(true); 5085 OUR_PMLog(kPMLogClientTardy, 0, 1); 5086 // tardy equates to approval 5087 done = true; 5088 break; 5089 5090 default: 5091 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n", 5092 getName(), fMachineState); 5093 break; 5094 } 5095 return done; 5096} 5097 5098//********************************************************************************* 5099// [private] start_ack_timer 5100//********************************************************************************* 5101 5102void IOService::start_ack_timer ( void ) 5103{ 5104 start_ack_timer( ACK_TIMER_PERIOD, kNanosecondScale ); 5105} 5106 5107void IOService::start_ack_timer ( UInt32 interval, UInt32 scale ) 5108{ 5109 AbsoluteTime deadline; 5110 boolean_t pending; 5111 5112 clock_interval_to_deadline(interval, scale, &deadline); 5113 5114 retain(); 5115 pending = thread_call_enter_delayed(fAckTimer, deadline); 5116 if (pending) release(); 5117} 5118 5119//********************************************************************************* 5120// [private] stop_ack_timer 5121//********************************************************************************* 5122 5123void IOService::stop_ack_timer ( void ) 5124{ 5125 boolean_t pending; 5126 5127 pending = thread_call_cancel(fAckTimer); 5128 if (pending) release(); 5129} 5130 5131//********************************************************************************* 5132// [static] actionAckTimerExpired 5133// 5134// Inside PM work loop's gate. 5135//********************************************************************************* 5136 5137IOReturn 5138IOService::actionAckTimerExpired ( 5139 OSObject * target, 5140 void * arg0, void * arg1, 5141 void * arg2, void * arg3 ) 5142{ 5143 IOService * me = (IOService *) target; 5144 bool done; 5145 5146 // done will be true if the timer tick unblocks the machine state, 5147 // otherwise no need to signal the work loop. 5148 5149 done = me->ackTimerTick(); 5150 if (done && gIOPMWorkQueue) 5151 gIOPMWorkQueue->signalWorkAvailable(); 5152 5153 return kIOReturnSuccess; 5154} 5155 5156//********************************************************************************* 5157// ack_timer_expired 5158// 5159// Thread call function. Holds a retain while the callout is in flight. 5160//********************************************************************************* 5161 5162void 5163IOService::ack_timer_expired ( thread_call_param_t arg0, thread_call_param_t arg1 ) 5164{ 5165 IOService * me = (IOService *) arg0; 5166 5167 if (gIOPMWorkLoop) 5168 { 5169 gIOPMWorkLoop->runAction(&actionAckTimerExpired, me); 5170 } 5171 me->release(); 5172} 5173 5174// MARK: - 5175// MARK: Client Messaging 5176 5177//********************************************************************************* 5178// [private] tellSystemCapabilityChange 5179//********************************************************************************* 5180 5181void IOService::tellSystemCapabilityChange( uint32_t nextMS ) 5182{ 5183 MS_PUSH( nextMS ); 5184 fMachineState = kIOPM_TellCapabilityChangeDone; 5185 fOutOfBandMessage = kIOMessageSystemCapabilityChange; 5186 5187 if (fIsPreChange) 5188 { 5189 // Notify app first on pre-change. 5190 fOutOfBandParameter = kNotifyCapabilityChangeApps; 5191 } 5192 else 5193 { 5194 // Notify kernel clients first on post-change. 5195 fOutOfBandParameter = kNotifyCapabilityChangePriority; 5196 } 5197 5198 tellClientsWithResponse( fOutOfBandMessage ); 5199} 5200 5201//********************************************************************************* 5202// [public] askChangeDown 5203// 5204// Ask registered applications and kernel clients if we can change to a lower 5205// power state. 5206// 5207// Subclass can override this to send a different message type. Parameter is 5208// the destination state number. 5209// 5210// Return true if we don't have to wait for acknowledgements 5211//********************************************************************************* 5212 5213bool IOService::askChangeDown ( unsigned long stateNum ) 5214{ 5215 return tellClientsWithResponse( kIOMessageCanDevicePowerOff ); 5216} 5217 5218//********************************************************************************* 5219// [private] tellChangeDown1 5220// 5221// Notify registered applications and kernel clients that we are definitely 5222// dropping power. 5223// 5224// Return true if we don't have to wait for acknowledgements 5225//********************************************************************************* 5226 5227bool IOService::tellChangeDown1 ( unsigned long stateNum ) 5228{ 5229 fOutOfBandParameter = kNotifyApps; 5230 return tellChangeDown(stateNum); 5231} 5232 5233//********************************************************************************* 5234// [private] tellChangeDown2 5235// 5236// Notify priority clients that we are definitely dropping power. 5237// 5238// Return true if we don't have to wait for acknowledgements 5239//********************************************************************************* 5240 5241bool IOService::tellChangeDown2 ( unsigned long stateNum ) 5242{ 5243 fOutOfBandParameter = kNotifyPriority; 5244 return tellChangeDown(stateNum); 5245} 5246 5247//********************************************************************************* 5248// [public] tellChangeDown 5249// 5250// Notify registered applications and kernel clients that we are definitely 5251// dropping power. 5252// 5253// Subclass can override this to send a different message type. Parameter is 5254// the destination state number. 5255// 5256// Return true if we don't have to wait for acknowledgements 5257//********************************************************************************* 5258 5259bool IOService::tellChangeDown ( unsigned long stateNum ) 5260{ 5261 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff ); 5262} 5263 5264//********************************************************************************* 5265// cleanClientResponses 5266// 5267//********************************************************************************* 5268 5269static void logAppTimeouts ( OSObject * object, void * arg ) 5270{ 5271 IOPMInterestContext * context = (IOPMInterestContext *) arg; 5272 OSObject * flag; 5273 unsigned int clientIndex; 5274 5275 if (OSDynamicCast(_IOServiceInterestNotifier, object)) 5276 { 5277 // Discover the 'counter' value or index assigned to this client 5278 // when it was notified, by searching for the array index of the 5279 // client in an array holding the cached interested clients. 5280 5281 clientIndex = context->notifyClients->getNextIndexOfObject(object, 0); 5282 5283 if ((clientIndex != (unsigned int) -1) && 5284 (flag = context->responseArray->getObject(clientIndex)) && 5285 (flag != kOSBooleanTrue)) 5286 { 5287 OSString *logClientID = NULL; 5288 OSNumber *clientID = copyClientIDForNotification(object, context); 5289 5290 if (clientID) { 5291 logClientID = IOCopyLogNameForPID(clientID->unsigned32BitValue()); 5292 clientID->release(); 5293 } 5294 5295 PM_ERROR(context->errorLog, logClientID ? logClientID->getCStringNoCopy() : ""); 5296 5297 // TODO: record message type if possible 5298 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse( 5299 gIOPMStatsApplicationResponseTimedOut, 5300 logClientID ? logClientID->getCStringNoCopy() : "", 5301 0, (30*1000), -1); 5302 5303 if (logClientID) 5304 logClientID->release(); 5305 } 5306 } 5307} 5308 5309void IOService::cleanClientResponses ( bool logErrors ) 5310{ 5311 if (logErrors && fResponseArray) 5312 { 5313 switch ( fOutOfBandParameter ) { 5314 case kNotifyApps: 5315 case kNotifyCapabilityChangeApps: 5316 if (fNotifyClientArray) 5317 { 5318 IOPMInterestContext context; 5319 5320 context.responseArray = fResponseArray; 5321 context.notifyClients = fNotifyClientArray; 5322 context.serialNumber = fSerialNumber; 5323 context.messageType = kIOMessageCopyClientID; 5324 context.notifyType = kNotifyApps; 5325 context.isPreChange = fIsPreChange; 5326 context.enableTracing = false; 5327 context.us = this; 5328 context.maxTimeRequested = 0; 5329 context.stateNumber = fHeadNotePowerState; 5330 context.stateFlags = fHeadNotePowerArrayEntry->capabilityFlags; 5331 context.changeFlags = fHeadNoteChangeFlags; 5332 context.errorLog = "PM notification timeout (%s)\n"; 5333 5334 applyToInterested(gIOAppPowerStateInterest, logAppTimeouts, (void *) &context); 5335 } 5336 break; 5337 5338 default: 5339 // kNotifyPriority, kNotifyCapabilityChangePriority 5340 // TODO: identify the priority client that has not acked 5341 PM_ERROR("PM priority notification timeout\n"); 5342 if (gIOKitDebug & kIOLogDebugPower) 5343 { 5344 panic("PM priority notification timeout"); 5345 } 5346 break; 5347 } 5348 } 5349 5350 if (fResponseArray) 5351 { 5352 fResponseArray->release(); 5353 fResponseArray = NULL; 5354 } 5355 if (fNotifyClientArray) 5356 { 5357 fNotifyClientArray->release(); 5358 fNotifyClientArray = NULL; 5359 } 5360} 5361 5362//********************************************************************************* 5363// [protected] tellClientsWithResponse 5364// 5365// Notify registered applications and kernel clients that we are definitely 5366// dropping power. 5367// 5368// Return true if we don't have to wait for acknowledgements 5369//********************************************************************************* 5370 5371bool IOService::tellClientsWithResponse ( int messageType ) 5372{ 5373 IOPMInterestContext context; 5374 bool isRootDomain = IS_ROOT_DOMAIN; 5375 5376 PM_ASSERT_IN_GATE(); 5377 assert( fResponseArray == NULL ); 5378 assert( fNotifyClientArray == NULL ); 5379 5380 RD_LOG("tellClientsWithResponse( %s, %d )\n", 5381 getIOMessageString(messageType), fOutOfBandParameter); 5382 5383 fResponseArray = OSArray::withCapacity( 1 ); 5384 if (!fResponseArray) 5385 goto exit; 5386 5387 fResponseArray->setCapacityIncrement(8); 5388 if (++fSerialNumber == 0) 5389 fSerialNumber++; 5390 5391 context.responseArray = fResponseArray; 5392 context.notifyClients = 0; 5393 context.serialNumber = fSerialNumber; 5394 context.messageType = messageType; 5395 context.notifyType = fOutOfBandParameter; 5396 context.isPreChange = fIsPreChange; 5397 context.enableTracing = false; 5398 context.us = this; 5399 context.maxTimeRequested = 0; 5400 context.stateNumber = fHeadNotePowerState; 5401 context.stateFlags = fHeadNotePowerArrayEntry->capabilityFlags; 5402 context.changeFlags = fHeadNoteChangeFlags; 5403 context.messageFilter = (isRootDomain) ? 5404 OSMemberFunctionCast( 5405 IOPMMessageFilter, 5406 this, 5407 &IOPMrootDomain::systemMessageFilter) : 0; 5408 5409 switch ( fOutOfBandParameter ) { 5410 case kNotifyApps: 5411 applyToInterested( gIOAppPowerStateInterest, 5412 pmTellAppWithResponse, (void *) &context ); 5413 5414 if (isRootDomain && 5415 (fMachineState != kIOPM_OurChangeTellClientsPowerDown) && 5416 (fMachineState != kIOPM_SyncTellClientsPowerDown)) 5417 { 5418 // Notify capability app for tellChangeDown1() 5419 // but not for askChangeDown(). 5420 context.notifyType = kNotifyCapabilityChangeApps; 5421 context.messageType = kIOMessageSystemCapabilityChange; 5422 applyToInterested( gIOAppPowerStateInterest, 5423 pmTellCapabilityAppWithResponse, (void *) &context ); 5424 context.notifyType = fOutOfBandParameter; 5425 context.messageType = messageType; 5426 } 5427 context.maxTimeRequested = k30Seconds; 5428 5429 applyToInterested( gIOGeneralInterest, 5430 pmTellClientWithResponse, (void *) &context ); 5431 5432 fNotifyClientArray = context.notifyClients; 5433 break; 5434 5435 case kNotifyPriority: 5436 context.enableTracing = isRootDomain; 5437 applyToInterested( gIOPriorityPowerStateInterest, 5438 pmTellClientWithResponse, (void *) &context ); 5439 5440 if (isRootDomain) 5441 { 5442 // Notify capability clients for tellChangeDown2(). 5443 context.notifyType = kNotifyCapabilityChangePriority; 5444 context.messageType = kIOMessageSystemCapabilityChange; 5445 applyToInterested( gIOPriorityPowerStateInterest, 5446 pmTellCapabilityClientWithResponse, (void *) &context ); 5447 } 5448 break; 5449 5450 case kNotifyCapabilityChangeApps: 5451 applyToInterested( gIOAppPowerStateInterest, 5452 pmTellCapabilityAppWithResponse, (void *) &context ); 5453 fNotifyClientArray = context.notifyClients; 5454 context.maxTimeRequested = k30Seconds; 5455 break; 5456 5457 case kNotifyCapabilityChangePriority: 5458 applyToInterested( gIOPriorityPowerStateInterest, 5459 pmTellCapabilityClientWithResponse, (void *) &context ); 5460 break; 5461 } 5462 5463 // do we have to wait for somebody? 5464 if ( !checkForDone() ) 5465 { 5466 OUR_PMLog(kPMLogStartAckTimer, context.maxTimeRequested, 0); 5467 if (context.enableTracing) 5468 getPMRootDomain()->traceDetail( context.maxTimeRequested / 1000 ); 5469 start_ack_timer( context.maxTimeRequested / 1000, kMillisecondScale ); 5470 return false; 5471 } 5472 5473exit: 5474 // everybody responded 5475 if (fResponseArray) 5476 { 5477 fResponseArray->release(); 5478 fResponseArray = NULL; 5479 } 5480 if (fNotifyClientArray) 5481 { 5482 fNotifyClientArray->release(); 5483 fNotifyClientArray = NULL; 5484 } 5485 5486 return true; 5487} 5488 5489//********************************************************************************* 5490// [static private] pmTellAppWithResponse 5491// 5492// We send a message to an application, and we expect a response, so we compute a 5493// cookie we can identify the response with. 5494//********************************************************************************* 5495 5496void IOService::pmTellAppWithResponse ( OSObject * object, void * arg ) 5497{ 5498 IOPMInterestContext * context = (IOPMInterestContext *) arg; 5499 IOServicePM * pwrMgt = context->us->pwrMgt; 5500 uint32_t msgIndex, msgRef, msgType; 5501 OSNumber *clientID = NULL; 5502 proc_t proc = NULL; 5503 boolean_t proc_suspended = FALSE; 5504#if LOG_APP_RESPONSE_TIMES 5505 AbsoluteTime now; 5506#endif 5507 5508 if (!OSDynamicCast(_IOServiceInterestNotifier, object)) 5509 return; 5510 5511 if (context->us == getPMRootDomain()) 5512 { 5513 if ((clientID = copyClientIDForNotification(object, context))) 5514 { 5515 uint32_t clientPID = clientID->unsigned32BitValue(); 5516 clientID->release(); 5517 proc = proc_find(clientPID); 5518 5519 if (proc) 5520 { 5521 proc_suspended = get_task_pidsuspended((task_t) proc->task); 5522 proc_rele(proc); 5523 5524 if (proc_suspended) 5525 { 5526 logClientIDForNotification(object, context, "PMTellAppWithResponse - Suspended"); 5527 return; 5528 } 5529 } 5530 } 5531 } 5532 5533 if (context->messageFilter && 5534 !context->messageFilter(context->us, object, context, 0, 0)) 5535 { 5536 if (kIOLogDebugPower & gIOKitDebug) 5537 { 5538 logClientIDForNotification(object, context, "DROP App"); 5539 } 5540 return; 5541 } 5542 5543 // Create client array (for tracking purposes) only if the service 5544 // has app clients. Usually only root domain does. 5545 if (0 == context->notifyClients) 5546 context->notifyClients = OSArray::withCapacity( 32 ); 5547 5548 msgType = context->messageType; 5549 msgIndex = context->responseArray->getCount(); 5550 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF); 5551 5552 OUR_PMLog(kPMLogAppNotify, msgType, msgRef); 5553 if (kIOLogDebugPower & gIOKitDebug) 5554 { 5555 logClientIDForNotification(object, context, "MESG App"); 5556 } 5557 5558#if LOG_APP_RESPONSE_TIMES 5559 OSNumber * num; 5560 clock_get_uptime(&now); 5561 num = OSNumber::withNumber(AbsoluteTime_to_scalar(&now), sizeof(uint64_t) * 8); 5562 if (num) 5563 { 5564 context->responseArray->setObject(msgIndex, num); 5565 num->release(); 5566 } 5567 else 5568#endif 5569 context->responseArray->setObject(msgIndex, kOSBooleanFalse); 5570 5571 if (context->notifyClients) 5572 context->notifyClients->setObject(msgIndex, object); 5573 5574 context->us->messageClient(msgType, object, (void *) msgRef); 5575} 5576 5577//********************************************************************************* 5578// [static private] pmTellClientWithResponse 5579// 5580// We send a message to an in-kernel client, and we expect a response, 5581// so we compute a cookie we can identify the response with. 5582//********************************************************************************* 5583 5584void IOService::pmTellClientWithResponse ( OSObject * object, void * arg ) 5585{ 5586 IOPowerStateChangeNotification notify; 5587 IOPMInterestContext * context = (IOPMInterestContext *) arg; 5588 OSObject * replied = kOSBooleanTrue; 5589 _IOServiceInterestNotifier * notifier; 5590 uint32_t msgIndex, msgRef, msgType; 5591 IOReturn retCode; 5592 5593 if (context->messageFilter && 5594 !context->messageFilter(context->us, object, context, 0, 0)) 5595 { 5596 if ((kIOLogDebugPower & gIOKitDebug) && 5597 (OSDynamicCast(_IOServiceInterestNotifier, object))) 5598 { 5599 _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object; 5600 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n", 5601 context->us->getName(), 5602 getIOMessageString(context->messageType), 5603 object, n->handler); 5604 } 5605 return; 5606 } 5607 5608 notifier = OSDynamicCast(_IOServiceInterestNotifier, object); 5609 msgType = context->messageType; 5610 msgIndex = context->responseArray->getCount(); 5611 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF); 5612 5613 IOServicePM * pwrMgt = context->us->pwrMgt; 5614 if (gIOKitDebug & kIOLogPower) { 5615 OUR_PMLog(kPMLogClientNotify, msgRef, msgType); 5616 if (OSDynamicCast(IOService, object)) { 5617 const char *who = ((IOService *) object)->getName(); 5618 gPlatform->PMLog(who, kPMLogClientNotify, (uintptr_t) object, 0); 5619 } 5620 else if (notifier) { 5621 OUR_PMLog(kPMLogClientNotify, (uintptr_t) notifier->handler, 0); 5622 } 5623 } 5624 if ((kIOLogDebugPower & gIOKitDebug) && notifier) 5625 { 5626 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n", 5627 context->us->getName(), 5628 getIOMessageString(msgType), 5629 object, notifier->handler); 5630 } 5631 5632 notify.powerRef = (void *)(uintptr_t) msgRef; 5633 notify.returnValue = 0; 5634 notify.stateNumber = context->stateNumber; 5635 notify.stateFlags = context->stateFlags; 5636 5637 if (context->enableTracing && (notifier != 0)) 5638 { 5639 uint32_t detail = ((msgIndex & 0xff) << 24) | 5640 ((msgType & 0xfff) << 12) | 5641 (((uintptr_t) notifier->handler) & 0xfff); 5642 getPMRootDomain()->traceDetail( detail ); 5643 } 5644 5645 retCode = context->us->messageClient(msgType, object, (void *) ¬ify, sizeof(notify)); 5646 5647 if (kIOReturnSuccess == retCode) 5648 { 5649 if (0 == notify.returnValue) { 5650 OUR_PMLog(kPMLogClientAcknowledge, msgRef, (uintptr_t) object); 5651 } else { 5652 replied = kOSBooleanFalse; 5653 if ( notify.returnValue > context->maxTimeRequested ) 5654 { 5655 if (notify.returnValue > kPriorityClientMaxWait) 5656 { 5657 context->maxTimeRequested = kPriorityClientMaxWait; 5658 PM_ERROR("%s: client %p returned %llu for %s\n", 5659 context->us->getName(), 5660 notifier ? (void *) notifier->handler : object, 5661 (uint64_t) notify.returnValue, 5662 getIOMessageString(msgType)); 5663 } 5664 else 5665 context->maxTimeRequested = notify.returnValue; 5666 } 5667 } 5668 } else { 5669 // not a client of ours 5670 // so we won't be waiting for response 5671 OUR_PMLog(kPMLogClientAcknowledge, msgRef, 0); 5672 } 5673 5674 context->responseArray->setObject(msgIndex, replied); 5675} 5676 5677//********************************************************************************* 5678// [static private] pmTellCapabilityAppWithResponse 5679//********************************************************************************* 5680 5681void IOService::pmTellCapabilityAppWithResponse ( OSObject * object, void * arg ) 5682{ 5683 IOPMSystemCapabilityChangeParameters msgArg; 5684 IOPMInterestContext * context = (IOPMInterestContext *) arg; 5685 OSObject * replied = kOSBooleanTrue; 5686 IOServicePM * pwrMgt = context->us->pwrMgt; 5687 uint32_t msgIndex, msgRef, msgType; 5688#if LOG_APP_RESPONSE_TIMES 5689 AbsoluteTime now; 5690#endif 5691 5692 if (!OSDynamicCast(_IOServiceInterestNotifier, object)) 5693 return; 5694 5695 memset(&msgArg, 0, sizeof(msgArg)); 5696 if (context->messageFilter && 5697 !context->messageFilter(context->us, object, context, &msgArg, &replied)) 5698 { 5699 return; 5700 } 5701 5702 // Create client array (for tracking purposes) only if the service 5703 // has app clients. Usually only root domain does. 5704 if (0 == context->notifyClients) 5705 context->notifyClients = OSArray::withCapacity( 32 ); 5706 5707 msgType = context->messageType; 5708 msgIndex = context->responseArray->getCount(); 5709 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF); 5710 5711 OUR_PMLog(kPMLogAppNotify, msgType, msgRef); 5712 if (kIOLogDebugPower & gIOKitDebug) 5713 { 5714 // Log client pid/name and client array index. 5715 OSNumber * clientID = NULL; 5716 OSString * clientIDString = NULL;; 5717 context->us->messageClient(kIOMessageCopyClientID, object, &clientID); 5718 if (clientID) { 5719 clientIDString = IOCopyLogNameForPID(clientID->unsigned32BitValue()); 5720 } 5721 5722 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n", 5723 context->us->getName(), 5724 msgIndex, getIOMessageString(msgType), 5725 (replied != kOSBooleanTrue), 5726 clientIDString ? clientIDString->getCStringNoCopy() : ""); 5727 if (clientID) clientID->release(); 5728 if (clientIDString) clientIDString->release(); 5729 } 5730 5731 msgArg.notifyRef = msgRef; 5732 msgArg.maxWaitForReply = 0; 5733 5734 if (replied == kOSBooleanTrue) 5735 { 5736 msgArg.notifyRef = 0; 5737 context->responseArray->setObject(msgIndex, kOSBooleanTrue); 5738 if (context->notifyClients) 5739 context->notifyClients->setObject(msgIndex, kOSBooleanTrue); 5740 } 5741 else 5742 { 5743#if LOG_APP_RESPONSE_TIMES 5744 OSNumber * num; 5745 clock_get_uptime(&now); 5746 num = OSNumber::withNumber(AbsoluteTime_to_scalar(&now), sizeof(uint64_t) * 8); 5747 if (num) 5748 { 5749 context->responseArray->setObject(msgIndex, num); 5750 num->release(); 5751 } 5752 else 5753#endif 5754 context->responseArray->setObject(msgIndex, kOSBooleanFalse); 5755 5756 if (context->notifyClients) 5757 context->notifyClients->setObject(msgIndex, object); 5758 } 5759 5760 context->us->messageClient(msgType, object, (void *) &msgArg, sizeof(msgArg)); 5761} 5762 5763//********************************************************************************* 5764// [static private] pmTellCapabilityClientWithResponse 5765//********************************************************************************* 5766 5767void IOService::pmTellCapabilityClientWithResponse( 5768 OSObject * object, void * arg ) 5769{ 5770 IOPMSystemCapabilityChangeParameters msgArg; 5771 IOPMInterestContext * context = (IOPMInterestContext *) arg; 5772 OSObject * replied = kOSBooleanTrue; 5773 _IOServiceInterestNotifier * notifier; 5774 uint32_t msgIndex, msgRef, msgType; 5775 IOReturn retCode; 5776 5777 memset(&msgArg, 0, sizeof(msgArg)); 5778 if (context->messageFilter && 5779 !context->messageFilter(context->us, object, context, &msgArg, 0)) 5780 { 5781 if ((kIOLogDebugPower & gIOKitDebug) && 5782 (OSDynamicCast(_IOServiceInterestNotifier, object))) 5783 { 5784 _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object; 5785 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n", 5786 context->us->getName(), 5787 getIOMessageString(context->messageType), 5788 object, n->handler); 5789 } 5790 return; 5791 } 5792 5793 notifier = OSDynamicCast(_IOServiceInterestNotifier, object); 5794 msgType = context->messageType; 5795 msgIndex = context->responseArray->getCount(); 5796 msgRef = ((context->serialNumber & 0xFFFF) << 16) + (msgIndex & 0xFFFF); 5797 5798 IOServicePM * pwrMgt = context->us->pwrMgt; 5799 if (gIOKitDebug & kIOLogPower) { 5800 OUR_PMLog(kPMLogClientNotify, msgRef, msgType); 5801 if (OSDynamicCast(IOService, object)) { 5802 const char *who = ((IOService *) object)->getName(); 5803 gPlatform->PMLog(who, kPMLogClientNotify, (uintptr_t) object, 0); 5804 } 5805 else if (notifier) { 5806 OUR_PMLog(kPMLogClientNotify, (uintptr_t) notifier->handler, 0); 5807 } 5808 } 5809 if ((kIOLogDebugPower & gIOKitDebug) && notifier) 5810 { 5811 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n", 5812 context->us->getName(), 5813 getIOMessageString(msgType), 5814 object, notifier->handler); 5815 } 5816 5817 msgArg.notifyRef = msgRef; 5818 msgArg.maxWaitForReply = 0; 5819 5820 if (context->enableTracing && (notifier != 0)) 5821 { 5822 uint32_t detail = ((msgIndex & 0xff) << 24) | 5823 ((msgType & 0xfff) << 12) | 5824 (((uintptr_t) notifier->handler) & 0xfff); 5825 getPMRootDomain()->traceDetail( detail ); 5826 } 5827 5828 retCode = context->us->messageClient( 5829 msgType, object, (void *) &msgArg, sizeof(msgArg)); 5830 5831 if ( kIOReturnSuccess == retCode ) 5832 { 5833 if ( 0 == msgArg.maxWaitForReply ) 5834 { 5835 // client doesn't want time to respond 5836 OUR_PMLog(kPMLogClientAcknowledge, msgRef, (uintptr_t) object); 5837 } 5838 else 5839 { 5840 replied = kOSBooleanFalse; 5841 if ( msgArg.maxWaitForReply > context->maxTimeRequested ) 5842 { 5843 if (msgArg.maxWaitForReply > kCapabilityClientMaxWait) 5844 { 5845 context->maxTimeRequested = kCapabilityClientMaxWait; 5846 PM_ERROR("%s: client %p returned %u for %s\n", 5847 context->us->getName(), 5848 notifier ? (void *) notifier->handler : object, 5849 msgArg.maxWaitForReply, 5850 getIOMessageString(msgType)); 5851 } 5852 else 5853 context->maxTimeRequested = msgArg.maxWaitForReply; 5854 } 5855 } 5856 } 5857 else 5858 { 5859 // not a client of ours 5860 // so we won't be waiting for response 5861 OUR_PMLog(kPMLogClientAcknowledge, msgRef, 0); 5862 } 5863 5864 context->responseArray->setObject(msgIndex, replied); 5865} 5866 5867//********************************************************************************* 5868// [public] tellNoChangeDown 5869// 5870// Notify registered applications and kernel clients that we are not 5871// dropping power. 5872// 5873// Subclass can override this to send a different message type. Parameter is 5874// the aborted destination state number. 5875//********************************************************************************* 5876 5877void IOService::tellNoChangeDown ( unsigned long ) 5878{ 5879 return tellClients( kIOMessageDeviceWillNotPowerOff ); 5880} 5881 5882//********************************************************************************* 5883// [public] tellChangeUp 5884// 5885// Notify registered applications and kernel clients that we are raising power. 5886// 5887// Subclass can override this to send a different message type. Parameter is 5888// the aborted destination state number. 5889//********************************************************************************* 5890 5891void IOService::tellChangeUp ( unsigned long ) 5892{ 5893 return tellClients( kIOMessageDeviceHasPoweredOn ); 5894} 5895 5896//********************************************************************************* 5897// [protected] tellClients 5898// 5899// Notify registered applications and kernel clients of something. 5900//********************************************************************************* 5901 5902void IOService::tellClients ( int messageType ) 5903{ 5904 IOPMInterestContext context; 5905 5906 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType)); 5907 5908 memset(&context, 0, sizeof(context)); 5909 context.messageType = messageType; 5910 context.isPreChange = fIsPreChange; 5911 context.us = this; 5912 context.stateNumber = fHeadNotePowerState; 5913 context.stateFlags = fHeadNotePowerArrayEntry->capabilityFlags; 5914 context.changeFlags = fHeadNoteChangeFlags; 5915 context.messageFilter = (IS_ROOT_DOMAIN) ? 5916 OSMemberFunctionCast( 5917 IOPMMessageFilter, 5918 this, 5919 &IOPMrootDomain::systemMessageFilter) : 0; 5920 5921 context.notifyType = kNotifyPriority; 5922 applyToInterested( gIOPriorityPowerStateInterest, 5923 tellKernelClientApplier, (void *) &context ); 5924 5925 context.notifyType = kNotifyApps; 5926 applyToInterested( gIOAppPowerStateInterest, 5927 tellAppClientApplier, (void *) &context ); 5928 5929 applyToInterested( gIOGeneralInterest, 5930 tellKernelClientApplier, (void *) &context ); 5931} 5932 5933//********************************************************************************* 5934// [private] tellKernelClientApplier 5935// 5936// Message a kernel client. 5937//********************************************************************************* 5938 5939static void tellKernelClientApplier ( OSObject * object, void * arg ) 5940{ 5941 IOPowerStateChangeNotification notify; 5942 IOPMInterestContext * context = (IOPMInterestContext *) arg; 5943 5944 if (context->messageFilter && 5945 !context->messageFilter(context->us, object, context, 0, 0)) 5946 { 5947 if ((kIOLogDebugPower & gIOKitDebug) && 5948 (OSDynamicCast(_IOServiceInterestNotifier, object))) 5949 { 5950 _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object; 5951 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n", 5952 context->us->getName(), 5953 IOService::getIOMessageString(context->messageType), 5954 object, n->handler); 5955 } 5956 return; 5957 } 5958 5959 notify.powerRef = (void *) 0; 5960 notify.returnValue = 0; 5961 notify.stateNumber = context->stateNumber; 5962 notify.stateFlags = context->stateFlags; 5963 5964 context->us->messageClient(context->messageType, object, ¬ify, sizeof(notify)); 5965 5966 if ((kIOLogDebugPower & gIOKitDebug) && 5967 (OSDynamicCast(_IOServiceInterestNotifier, object))) 5968 { 5969 _IOServiceInterestNotifier *n = (_IOServiceInterestNotifier *) object; 5970 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n", 5971 context->us->getName(), 5972 IOService::getIOMessageString(context->messageType), 5973 object, n->handler); 5974 } 5975} 5976 5977static OSNumber * copyClientIDForNotification( 5978 OSObject *object, 5979 IOPMInterestContext *context) 5980{ 5981 OSNumber *clientID = NULL; 5982 context->us->messageClient(kIOMessageCopyClientID, object, &clientID); 5983 return clientID; 5984} 5985 5986static void logClientIDForNotification( 5987 OSObject *object, 5988 IOPMInterestContext *context, 5989 const char *logString) 5990{ 5991 OSString *logClientID = NULL; 5992 OSNumber *clientID = copyClientIDForNotification(object, context); 5993 5994 if (logString) 5995 { 5996 if (clientID) 5997 logClientID = IOCopyLogNameForPID(clientID->unsigned32BitValue()); 5998 5999 PM_LOG("%s %s %s, %s\n", 6000 context->us->getName(), logString, 6001 IOService::getIOMessageString(context->messageType), 6002 logClientID ? logClientID->getCStringNoCopy() : ""); 6003 6004 if (logClientID) 6005 logClientID->release(); 6006 } 6007 6008 if (clientID) 6009 clientID->release(); 6010 6011 return; 6012} 6013 6014 6015static void tellAppClientApplier ( OSObject * object, void * arg ) 6016{ 6017 IOPMInterestContext * context = (IOPMInterestContext *) arg; 6018 OSNumber * clientID = NULL; 6019 proc_t proc = NULL; 6020 boolean_t proc_suspended = FALSE; 6021 6022 if (context->us == IOService::getPMRootDomain()) 6023 { 6024 if ((clientID = copyClientIDForNotification(object, context))) 6025 { 6026 uint32_t clientPID = clientID->unsigned32BitValue(); 6027 clientID->release(); 6028 proc = proc_find(clientPID); 6029 6030 if (proc) 6031 { 6032 proc_suspended = get_task_pidsuspended((task_t) proc->task); 6033 proc_rele(proc); 6034 6035 if (proc_suspended) 6036 { 6037 logClientIDForNotification(object, context, "tellAppClientApplier - Suspended"); 6038 return; 6039 } 6040 } 6041 } 6042 } 6043 6044 if (context->messageFilter && 6045 !context->messageFilter(context->us, object, context, 0, 0)) 6046 { 6047 if (kIOLogDebugPower & gIOKitDebug) 6048 { 6049 logClientIDForNotification(object, context, "DROP App"); 6050 } 6051 return; 6052 } 6053 6054 if (kIOLogDebugPower & gIOKitDebug) 6055 { 6056 logClientIDForNotification(object, context, "MESG App"); 6057 } 6058 6059 context->us->messageClient(context->messageType, object, 0); 6060} 6061 6062//********************************************************************************* 6063// [private] checkForDone 6064//********************************************************************************* 6065 6066bool IOService::checkForDone ( void ) 6067{ 6068 int i = 0; 6069 OSObject * theFlag; 6070 6071 if (fResponseArray == NULL) { 6072 return true; 6073 } 6074 6075 for (i = 0; ; i++) { 6076 theFlag = fResponseArray->getObject(i); 6077 6078 if (NULL == theFlag) { 6079 break; 6080 } 6081 6082 if (kOSBooleanTrue != theFlag) { 6083 return false; 6084 } 6085 } 6086 return true; 6087} 6088 6089//********************************************************************************* 6090// [public] responseValid 6091//********************************************************************************* 6092 6093bool IOService::responseValid ( uint32_t refcon, int pid ) 6094{ 6095 UInt16 serialComponent; 6096 UInt16 ordinalComponent; 6097 OSObject * theFlag; 6098 6099 serialComponent = (refcon >> 16) & 0xFFFF; 6100 ordinalComponent = (refcon & 0xFFFF); 6101 6102 if ( serialComponent != fSerialNumber ) 6103 { 6104 return false; 6105 } 6106 6107 if ( fResponseArray == NULL ) 6108 { 6109 return false; 6110 } 6111 6112 theFlag = fResponseArray->getObject(ordinalComponent); 6113 6114 if ( theFlag == 0 ) 6115 { 6116 return false; 6117 } 6118 6119 OSNumber * num; 6120 if ((num = OSDynamicCast(OSNumber, theFlag))) 6121 { 6122#if LOG_APP_RESPONSE_TIMES 6123 AbsoluteTime now; 6124 AbsoluteTime start; 6125 uint64_t nsec; 6126 OSString *name = IOCopyLogNameForPID(pid); 6127 6128 clock_get_uptime(&now); 6129 AbsoluteTime_to_scalar(&start) = num->unsigned64BitValue(); 6130 SUB_ABSOLUTETIME(&now, &start); 6131 absolutetime_to_nanoseconds(now, &nsec); 6132 6133 PMEventDetails *details = PMEventDetails::eventDetails( 6134 kIOPMEventTypeAppResponse, // type 6135 name ? name->getCStringNoCopy() : "", // who 6136 (uintptr_t)pid, // owner unique 6137 NULL, // interest name 6138 0, // old 6139 0, // new 6140 0, // result 6141 NS_TO_US(nsec)); // usec completion time 6142 6143 getPMRootDomain()->recordAndReleasePMEventGated( details ); 6144 6145 if (kIOLogDebugPower & gIOKitDebug) 6146 { 6147 PM_LOG("Ack(%u) %u ms\n", 6148 (uint32_t) ordinalComponent, 6149 NS_TO_MS(nsec)); 6150 } 6151 6152 // > 100 ms 6153 if (nsec > LOG_APP_RESPONSE_TIMES) 6154 { 6155 PM_LOG("PM response took %d ms (%s)\n", NS_TO_MS(nsec), 6156 name ? name->getCStringNoCopy() : ""); 6157 6158 if (nsec > LOG_APP_RESPONSE_MSG_TRACER) 6159 { 6160 // TODO: populate the messageType argument 6161 getPMRootDomain()->pmStatsRecordApplicationResponse( 6162 gIOPMStatsApplicationResponseSlow, 6163 name ? name->getCStringNoCopy() : "", 0, 6164 NS_TO_MS(nsec), pid); 6165 } 6166 } 6167 6168 if (name) 6169 name->release(); 6170#endif 6171 theFlag = kOSBooleanFalse; 6172 } 6173 6174 if ( kOSBooleanFalse == theFlag ) 6175 { 6176 fResponseArray->replaceObject(ordinalComponent, kOSBooleanTrue); 6177 } 6178 6179 return true; 6180} 6181 6182//********************************************************************************* 6183// [public] allowPowerChange 6184// 6185// Our power state is about to lower, and we have notified applications 6186// and kernel clients, and one of them has acknowledged. If this is the last to do 6187// so, and all acknowledgements are positive, we continue with the power change. 6188//********************************************************************************* 6189 6190IOReturn IOService::allowPowerChange ( unsigned long refcon ) 6191{ 6192 IOPMRequest * request; 6193 6194 if ( !initialized ) 6195 { 6196 // we're unloading 6197 return kIOReturnSuccess; 6198 } 6199 6200 request = acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange ); 6201 if (!request) 6202 return kIOReturnNoMemory; 6203 6204 request->fArg0 = (void *) refcon; 6205 request->fArg1 = (void *) proc_selfpid(); 6206 request->fArg2 = (void *) 0; 6207 submitPMRequest( request ); 6208 6209 return kIOReturnSuccess; 6210} 6211 6212#ifndef __LP64__ 6213IOReturn IOService::serializedAllowPowerChange2 ( unsigned long refcon ) 6214{ 6215 // [deprecated] public 6216 return kIOReturnUnsupported; 6217} 6218#endif /* !__LP64__ */ 6219 6220//********************************************************************************* 6221// [public] cancelPowerChange 6222// 6223// Our power state is about to lower, and we have notified applications 6224// and kernel clients, and one of them has vetoed the change. If this is the last 6225// client to respond, we abandon the power change. 6226//********************************************************************************* 6227 6228IOReturn IOService::cancelPowerChange ( unsigned long refcon ) 6229{ 6230 IOPMRequest * request; 6231 OSString * name; 6232 6233 if ( !initialized ) 6234 { 6235 // we're unloading 6236 return kIOReturnSuccess; 6237 } 6238 6239 name = IOCopyLogNameForPID(proc_selfpid()); 6240 PM_ERROR("PM notification cancel (%s)\n", name ? name->getCStringNoCopy() : ""); 6241 6242 request = acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange ); 6243 if (!request) 6244 { 6245 if (name) 6246 name->release(); 6247 return kIOReturnNoMemory; 6248 } 6249 6250 request->fArg0 = (void *) refcon; 6251 request->fArg1 = (void *) proc_selfpid(); 6252 request->fArg2 = (void *) name; 6253 submitPMRequest( request ); 6254 6255 return kIOReturnSuccess; 6256} 6257 6258#ifndef __LP64__ 6259IOReturn IOService::serializedCancelPowerChange2 ( unsigned long refcon ) 6260{ 6261 // [deprecated] public 6262 return kIOReturnUnsupported; 6263} 6264 6265//********************************************************************************* 6266// PM_Clamp_Timer_Expired 6267// 6268// called when clamp timer expires...set power state to 0. 6269//********************************************************************************* 6270 6271void IOService::PM_Clamp_Timer_Expired ( void ) 6272{ 6273} 6274 6275//********************************************************************************* 6276// clampPowerOn 6277// 6278// Set to highest available power state for a minimum of duration milliseconds 6279//********************************************************************************* 6280 6281void IOService::clampPowerOn ( unsigned long duration ) 6282{ 6283} 6284#endif /* !__LP64__ */ 6285 6286// MARK: - 6287// MARK: Driver Overrides 6288 6289//********************************************************************************* 6290// [public] setPowerState 6291// 6292// Does nothing here. This should be implemented in a subclass driver. 6293//********************************************************************************* 6294 6295IOReturn IOService::setPowerState ( 6296 unsigned long powerStateOrdinal, IOService * whatDevice ) 6297{ 6298 return IOPMNoErr; 6299} 6300 6301//********************************************************************************* 6302// [public] maxCapabilityForDomainState 6303// 6304// Finds the highest power state in the array whose input power 6305// requirement is equal to the input parameter. Where a more intelligent 6306// decision is possible, override this in the subclassed driver. 6307//********************************************************************************* 6308 6309unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState ) 6310{ 6311 int i; 6312 6313 if (fNumberOfPowerStates == 0 ) 6314 { 6315 return 0; 6316 } 6317 for ( i = fNumberOfPowerStates - 1; i >= 0; i-- ) 6318 { 6319 if ( (domainState & fPowerStates[i].inputPowerFlags) == 6320 fPowerStates[i].inputPowerFlags ) 6321 { 6322 return i; 6323 } 6324 } 6325 return 0; 6326} 6327 6328//********************************************************************************* 6329// [public] initialPowerStateForDomainState 6330// 6331// Finds the highest power state in the array whose input power 6332// requirement is equal to the input parameter. Where a more intelligent 6333// decision is possible, override this in the subclassed driver. 6334//********************************************************************************* 6335 6336unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState ) 6337{ 6338 int i; 6339 6340 if (fNumberOfPowerStates == 0 ) 6341 { 6342 return 0; 6343 } 6344 for ( i = fNumberOfPowerStates - 1; i >= 0; i-- ) 6345 { 6346 if ( (domainState & fPowerStates[i].inputPowerFlags) == 6347 fPowerStates[i].inputPowerFlags ) 6348 { 6349 return i; 6350 } 6351 } 6352 return 0; 6353} 6354 6355//********************************************************************************* 6356// [public] powerStateForDomainState 6357// 6358// Finds the highest power state in the array whose input power 6359// requirement is equal to the input parameter. Where a more intelligent 6360// decision is possible, override this in the subclassed driver. 6361//********************************************************************************* 6362 6363unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState ) 6364{ 6365 int i; 6366 6367 if (fNumberOfPowerStates == 0 ) 6368 { 6369 return 0; 6370 } 6371 for ( i = fNumberOfPowerStates - 1; i >= 0; i-- ) 6372 { 6373 if ( (domainState & fPowerStates[i].inputPowerFlags) == 6374 fPowerStates[i].inputPowerFlags ) 6375 { 6376 return i; 6377 } 6378 } 6379 return 0; 6380} 6381 6382#ifndef __LP64__ 6383//********************************************************************************* 6384// [deprecated] didYouWakeSystem 6385// 6386// Does nothing here. This should be implemented in a subclass driver. 6387//********************************************************************************* 6388 6389bool IOService::didYouWakeSystem ( void ) 6390{ 6391 return false; 6392} 6393#endif /* !__LP64__ */ 6394 6395//********************************************************************************* 6396// [public] powerStateWillChangeTo 6397// 6398// Does nothing here. This should be implemented in a subclass driver. 6399//********************************************************************************* 6400 6401IOReturn IOService::powerStateWillChangeTo ( IOPMPowerFlags, unsigned long, IOService * ) 6402{ 6403 return kIOPMAckImplied; 6404} 6405 6406//********************************************************************************* 6407// [public] powerStateDidChangeTo 6408// 6409// Does nothing here. This should be implemented in a subclass driver. 6410//********************************************************************************* 6411 6412IOReturn IOService::powerStateDidChangeTo ( IOPMPowerFlags, unsigned long, IOService * ) 6413{ 6414 return kIOPMAckImplied; 6415} 6416 6417//********************************************************************************* 6418// [protected] powerChangeDone 6419// 6420// Called from PM work loop thread. 6421// Does nothing here. This should be implemented in a subclass policy-maker. 6422//********************************************************************************* 6423 6424void IOService::powerChangeDone ( unsigned long ) 6425{ 6426} 6427 6428#ifndef __LP64__ 6429//********************************************************************************* 6430// [deprecated] newTemperature 6431// 6432// Does nothing here. This should be implemented in a subclass driver. 6433//********************************************************************************* 6434 6435IOReturn IOService::newTemperature ( long currentTemp, IOService * whichZone ) 6436{ 6437 return IOPMNoErr; 6438} 6439#endif /* !__LP64__ */ 6440 6441//********************************************************************************* 6442// [public] systemWillShutdown 6443// 6444// System shutdown and restart notification. 6445//********************************************************************************* 6446 6447void IOService::systemWillShutdown( IOOptionBits specifier ) 6448{ 6449 IOPMrootDomain * rootDomain = IOService::getPMRootDomain(); 6450 if (rootDomain) 6451 rootDomain->acknowledgeSystemWillShutdown( this ); 6452} 6453 6454// MARK: - 6455// MARK: PM State Machine 6456 6457//********************************************************************************* 6458// [private static] acquirePMRequest 6459//********************************************************************************* 6460 6461IOPMRequest * 6462IOService::acquirePMRequest( IOService * target, IOOptionBits requestType, 6463 IOPMRequest * active ) 6464{ 6465 IOPMRequest * request; 6466 6467 assert(target); 6468 6469 request = IOPMRequest::create(); 6470 if (request) 6471 { 6472 request->init( target, requestType ); 6473 if (active) 6474 { 6475 IOPMRequest * root = active->getRootRequest(); 6476 if (root) request->attachRootRequest(root); 6477 } 6478 } 6479 else 6480 { 6481 PM_ERROR("%s: No memory for PM request type 0x%x\n", 6482 target->getName(), (uint32_t) requestType); 6483 } 6484 return request; 6485} 6486 6487//********************************************************************************* 6488// [private static] releasePMRequest 6489//********************************************************************************* 6490 6491void IOService::releasePMRequest( IOPMRequest * request ) 6492{ 6493 if (request) 6494 { 6495 request->reset(); 6496 request->release(); 6497 } 6498} 6499 6500//********************************************************************************* 6501// [private] submitPMRequest 6502//********************************************************************************* 6503 6504void IOService::submitPMRequest( IOPMRequest * request ) 6505{ 6506 assert( request ); 6507 assert( gIOPMReplyQueue ); 6508 assert( gIOPMRequestQueue ); 6509 6510 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n", 6511 (long)request->getType(), request, 6512 request->getTarget(), request->getTarget()->getName(), 6513 request->fArg0, request->fArg1, request->fArg2); 6514 6515 if (request->isReplyType()) 6516 gIOPMReplyQueue->queuePMRequest( request ); 6517 else 6518 gIOPMRequestQueue->queuePMRequest( request ); 6519} 6520 6521void IOService::submitPMRequest( IOPMRequest ** requests, IOItemCount count ) 6522{ 6523 assert( requests ); 6524 assert( count > 0 ); 6525 assert( gIOPMRequestQueue ); 6526 6527 for (IOItemCount i = 0; i < count; i++) 6528 { 6529 IOPMRequest * req = requests[i]; 6530 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n", 6531 (long)req->getType(), req, 6532 req->getTarget(), req->getTarget()->getName(), 6533 req->fArg0, req->fArg1, req->fArg2); 6534 } 6535 6536 gIOPMRequestQueue->queuePMRequestChain( requests, count ); 6537} 6538 6539//********************************************************************************* 6540// [private] servicePMRequestQueue 6541// 6542// Called from IOPMRequestQueue::checkForWork(). 6543//********************************************************************************* 6544 6545bool IOService::servicePMRequestQueue( 6546 IOPMRequest * request, 6547 IOPMRequestQueue * queue ) 6548{ 6549 bool more; 6550 6551 if (initialized) 6552 { 6553 // Work queue will immediately execute the queue'd request if possible. 6554 // If execution blocks, the work queue will wait for a producer signal. 6555 // Only need to signal more when completing attached requests. 6556 6557 more = gIOPMWorkQueue->queuePMRequest(request, pwrMgt); 6558 return more; 6559 } 6560 6561 // Calling PM without PMinit() is not allowed, fail the request. 6562 6563 PM_LOG("%s: PM not initialized\n", getName()); 6564 fAdjustPowerScheduled = false; 6565 more = gIOPMFreeQueue->queuePMRequest(request); 6566 if (more) gIOPMWorkQueue->incrementProducerCount(); 6567 return more; 6568} 6569 6570//********************************************************************************* 6571// [private] servicePMFreeQueue 6572// 6573// Called from IOPMCompletionQueue::checkForWork(). 6574//********************************************************************************* 6575 6576bool IOService::servicePMFreeQueue( 6577 IOPMRequest * request, 6578 IOPMCompletionQueue * queue ) 6579{ 6580 bool more = request->getNextRequest(); 6581 IOPMRequest * root = request->getRootRequest(); 6582 6583 if (root && (root != request)) 6584 more = true; 6585 if (more) 6586 gIOPMWorkQueue->incrementProducerCount(); 6587 6588 releasePMRequest( request ); 6589 return more; 6590} 6591 6592//********************************************************************************* 6593// [private] retirePMRequest 6594// 6595// Called by IOPMWorkQueue to retire a completed request. 6596//********************************************************************************* 6597 6598bool IOService::retirePMRequest( IOPMRequest * request, IOPMWorkQueue * queue ) 6599{ 6600 assert(request && queue); 6601 6602 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n", 6603 request->getType(), request, this, getName(), 6604 fMachineState, gIOPMBusyCount); 6605 6606 // Catch requests created by idleTimerExpired(). 6607 6608 if ((request->getType() == kIOPMRequestTypeActivityTickle) && 6609 (request->fArg1 == (void *) false)) 6610 { 6611 // Idle timer expiration - power drop request completed. 6612 // Restart the idle timer if deviceDesire can go lower, otherwise set 6613 // a flag so we know to restart idle timer when fDeviceDesire > 0. 6614 6615 if (fDeviceDesire > 0) 6616 { 6617 fActivityTickleCount = 0; 6618 clock_get_uptime(&fIdleTimerStartTime); 6619 start_PM_idle_timer(); 6620 } 6621 else if (fHasAdvisoryDesire) 6622 { 6623 start_PM_idle_timer(); 6624 } 6625 else 6626 { 6627 fIdleTimerStopped = true; 6628 } 6629 } 6630 6631 // If the request is linked, then Work queue has already incremented its 6632 // producer count. 6633 6634 return (gIOPMFreeQueue->queuePMRequest( request )); 6635} 6636 6637//********************************************************************************* 6638// [private] isPMBlocked 6639// 6640// Check if machine state transition is blocked. 6641//********************************************************************************* 6642 6643bool IOService::isPMBlocked ( IOPMRequest * request, int count ) 6644{ 6645 int reason = 0; 6646 6647 do { 6648 if (kIOPM_Finished == fMachineState) 6649 break; 6650 6651 if (kIOPM_DriverThreadCallDone == fMachineState) 6652 { 6653 // 5 = kDriverCallInformPreChange 6654 // 6 = kDriverCallInformPostChange 6655 // 7 = kDriverCallSetPowerState 6656 if (fDriverCallBusy) 6657 reason = 5 + fDriverCallReason; 6658 break; 6659 } 6660 6661 // Waiting on driver's setPowerState() timeout. 6662 if (fDriverTimer) 6663 { 6664 reason = 1; break; 6665 } 6666 6667 // Child or interested driver acks pending. 6668 if (fHeadNotePendingAcks) 6669 { 6670 reason = 2; break; 6671 } 6672 6673 // Waiting on apps or priority power interest clients. 6674 if (fResponseArray) 6675 { 6676 reason = 3; break; 6677 } 6678 6679 // Waiting on settle timer expiration. 6680 if (fSettleTimeUS) 6681 { 6682 reason = 4; break; 6683 } 6684 } while (false); 6685 6686 fWaitReason = reason; 6687 6688 if (reason) 6689 { 6690 if (count) 6691 { 6692 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n", 6693 request->getType(), request, this, getName(), 6694 fMachineState, reason); 6695 } 6696 6697 return true; 6698 } 6699 6700 return false; 6701} 6702 6703//********************************************************************************* 6704// [private] servicePMRequest 6705// 6706// Service a request from our work queue. 6707//********************************************************************************* 6708 6709bool IOService::servicePMRequest( IOPMRequest * request, IOPMWorkQueue * queue ) 6710{ 6711 bool done = false; 6712 int loop = 0; 6713 6714 assert(request && queue); 6715 6716 while (isPMBlocked(request, loop++) == false) 6717 { 6718 PM_LOG1("[W %02x] %p [%p %s] state %d\n", 6719 request->getType(), request, this, getName(), fMachineState); 6720 6721 gIOPMRequest = request; 6722 gIOPMWorkCount++; 6723 6724 // Every PM machine states must be handled in one of the cases below. 6725 6726 switch ( fMachineState ) 6727 { 6728 case kIOPM_Finished: 6729 executePMRequest( request ); 6730 break; 6731 6732 case kIOPM_OurChangeTellClientsPowerDown: 6733 // Root domain might self cancel due to assertions. 6734 if (IS_ROOT_DOMAIN) 6735 { 6736 bool cancel = (bool) fDoNotPowerDown; 6737 getPMRootDomain()->askChangeDownDone( 6738 &fHeadNoteChangeFlags, &cancel); 6739 fDoNotPowerDown = cancel; 6740 } 6741 6742 // askChangeDown() done, was it vetoed? 6743 if (!fDoNotPowerDown) 6744 { 6745 if (IS_ROOT_DOMAIN) { 6746 PMEventDetails *details = PMEventDetails::eventDetails( 6747 kIOPMEventTypeAppNotificationsFinished, 6748 NULL, 6749 0, 6750 0); 6751 6752 getPMRootDomain()->recordAndReleasePMEventGated( details ); 6753 } 6754 6755 // no, we can continue 6756 OurChangeTellClientsPowerDown(); 6757 } 6758 else 6759 { 6760 if (IS_ROOT_DOMAIN) { 6761 PMEventDetails *details = PMEventDetails::eventDetails( 6762 kIOPMEventTypeSleepDone, 6763 NULL, 6764 1, /* reason: 1 == Ask clients succeeded */ 6765 kIOReturnAborted); /* result */ 6766 6767 getPMRootDomain()->recordAndReleasePMEventGated( details ); 6768 } 6769 6770 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState); 6771 PM_ERROR("%s: idle cancel\n", fName); 6772 // yes, rescind the warning 6773 tellNoChangeDown(fHeadNotePowerState); 6774 // mark the change note un-actioned 6775 fHeadNoteChangeFlags |= kIOPMNotDone; 6776 // and we're done 6777 OurChangeFinish(); 6778 } 6779 break; 6780 6781 case kIOPM_OurChangeTellPriorityClientsPowerDown: 6782 // tellChangeDown(kNotifyApps) done, was it cancelled? 6783 if (fDoNotPowerDown) 6784 { 6785 if (IS_ROOT_DOMAIN) { 6786 PMEventDetails *details = PMEventDetails::eventDetails( 6787 kIOPMEventTypeSleepDone, 6788 NULL, 6789 2, /* reason: 2 == Client cancelled wake */ 6790 kIOReturnAborted); /* result */ 6791 6792 getPMRootDomain()->recordAndReleasePMEventGated( details ); 6793 } 6794 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState); 6795 PM_ERROR("%s: idle revert\n", fName); 6796 // no, tell clients we're back in the old state 6797 tellChangeUp(fCurrentPowerState); 6798 // mark the change note un-actioned 6799 fHeadNoteChangeFlags |= kIOPMNotDone; 6800 // and we're done 6801 OurChangeFinish(); 6802 } 6803 else 6804 { 6805 if (IS_ROOT_DOMAIN) { 6806 PMEventDetails *details = PMEventDetails::eventDetails( 6807 kIOPMEventTypeAppNotificationsFinished, 6808 NULL, 6809 2, /* reason: 2 == TellPriorityClientsDone */ 6810 kIOReturnSuccess); /* result */ 6811 6812 getPMRootDomain()->recordAndReleasePMEventGated( details ); 6813 } 6814 // yes, we can continue 6815 OurChangeTellPriorityClientsPowerDown(); 6816 } 6817 break; 6818 6819 case kIOPM_OurChangeNotifyInterestedDriversWillChange: 6820 OurChangeNotifyInterestedDriversWillChange(); 6821 break; 6822 6823 case kIOPM_OurChangeSetPowerState: 6824 OurChangeSetPowerState(); 6825 break; 6826 6827 case kIOPM_OurChangeWaitForPowerSettle: 6828 OurChangeWaitForPowerSettle(); 6829 break; 6830 6831 case kIOPM_OurChangeNotifyInterestedDriversDidChange: 6832 OurChangeNotifyInterestedDriversDidChange(); 6833 break; 6834 6835 case kIOPM_OurChangeTellCapabilityDidChange: 6836 OurChangeTellCapabilityDidChange(); 6837 break; 6838 6839 case kIOPM_OurChangeFinish: 6840 OurChangeFinish(); 6841 break; 6842 6843 case kIOPM_ParentChangeTellPriorityClientsPowerDown: 6844 ParentChangeTellPriorityClientsPowerDown(); 6845 break; 6846 6847 case kIOPM_ParentChangeNotifyInterestedDriversWillChange: 6848 ParentChangeNotifyInterestedDriversWillChange(); 6849 break; 6850 6851 case kIOPM_ParentChangeSetPowerState: 6852 ParentChangeSetPowerState(); 6853 break; 6854 6855 case kIOPM_ParentChangeWaitForPowerSettle: 6856 ParentChangeWaitForPowerSettle(); 6857 break; 6858 6859 case kIOPM_ParentChangeNotifyInterestedDriversDidChange: 6860 ParentChangeNotifyInterestedDriversDidChange(); 6861 break; 6862 6863 case kIOPM_ParentChangeTellCapabilityDidChange: 6864 ParentChangeTellCapabilityDidChange(); 6865 break; 6866 6867 case kIOPM_ParentChangeAcknowledgePowerChange: 6868 ParentChangeAcknowledgePowerChange(); 6869 break; 6870 6871 case kIOPM_DriverThreadCallDone: 6872 if (fDriverCallReason == kDriverCallSetPowerState) 6873 notifyControllingDriverDone(); 6874 else 6875 notifyInterestedDriversDone(); 6876 break; 6877 6878 case kIOPM_NotifyChildrenOrdered: 6879 notifyChildrenOrdered(); 6880 break; 6881 6882 case kIOPM_NotifyChildrenDelayed: 6883 notifyChildrenDelayed(); 6884 break; 6885 6886 case kIOPM_NotifyChildrenStart: 6887 PM_LOG2("%s: kIOPM_NotifyChildrenStart done\n", getName()); 6888 MS_POP(); // from notifyInterestedDriversDone() 6889 notifyChildren(); 6890 break; 6891 6892 case kIOPM_SyncTellClientsPowerDown: 6893 // Root domain might self cancel due to assertions. 6894 if (IS_ROOT_DOMAIN) 6895 { 6896 bool cancel = (bool) fDoNotPowerDown; 6897 getPMRootDomain()->askChangeDownDone( 6898 &fHeadNoteChangeFlags, &cancel); 6899 fDoNotPowerDown = cancel; 6900 } 6901 if (!fDoNotPowerDown) 6902 { 6903 fMachineState = kIOPM_SyncTellPriorityClientsPowerDown; 6904 fOutOfBandParameter = kNotifyApps; 6905 tellChangeDown(fHeadNotePowerState); 6906 } 6907 else 6908 { 6909 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState); 6910 PM_ERROR("%s: idle cancel\n", fName); 6911 tellNoChangeDown(fHeadNotePowerState); 6912 fHeadNoteChangeFlags |= kIOPMNotDone; 6913 OurChangeFinish(); 6914 } 6915 break; 6916 6917 case kIOPM_SyncTellPriorityClientsPowerDown: 6918 if (!fDoNotPowerDown) 6919 { 6920 fMachineState = kIOPM_SyncNotifyWillChange; 6921 fOutOfBandParameter = kNotifyPriority; 6922 tellChangeDown(fHeadNotePowerState); 6923 } 6924 else 6925 { 6926 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState); 6927 PM_ERROR("%s: idle revert\n", fName); 6928 tellChangeUp(fCurrentPowerState); 6929 fHeadNoteChangeFlags |= kIOPMNotDone; 6930 OurChangeFinish(); 6931 } 6932 break; 6933 6934 case kIOPM_SyncNotifyWillChange: 6935 if (kIOPMSyncNoChildNotify & fHeadNoteChangeFlags) 6936 { 6937 fMachineState = kIOPM_SyncFinish; 6938 continue; 6939 } 6940 fMachineState = kIOPM_SyncNotifyDidChange; 6941 fDriverCallReason = kDriverCallInformPreChange; 6942 notifyChildren(); 6943 break; 6944 6945 case kIOPM_SyncNotifyDidChange: 6946 fIsPreChange = false; 6947 6948 if (fHeadNoteChangeFlags & kIOPMParentInitiated) 6949 fMachineState = kIOPM_SyncFinish; 6950 else 6951 fMachineState = kIOPM_SyncTellCapabilityDidChange; 6952 6953 fDriverCallReason = kDriverCallInformPostChange; 6954 notifyChildren(); 6955 break; 6956 6957 case kIOPM_SyncTellCapabilityDidChange: 6958 tellSystemCapabilityChange( kIOPM_SyncFinish ); 6959 break; 6960 6961 case kIOPM_SyncFinish: 6962 if (fHeadNoteChangeFlags & kIOPMParentInitiated) 6963 ParentChangeAcknowledgePowerChange(); 6964 else 6965 OurChangeFinish(); 6966 break; 6967 6968 case kIOPM_TellCapabilityChangeDone: 6969 if (fIsPreChange) 6970 { 6971 if (fOutOfBandParameter == kNotifyCapabilityChangePriority) 6972 { 6973 MS_POP(); // tellSystemCapabilityChange() 6974 continue; 6975 } 6976 fOutOfBandParameter = kNotifyCapabilityChangePriority; 6977 } 6978 else 6979 { 6980 if (fOutOfBandParameter == kNotifyCapabilityChangeApps) 6981 { 6982 MS_POP(); // tellSystemCapabilityChange() 6983 continue; 6984 } 6985 fOutOfBandParameter = kNotifyCapabilityChangeApps; 6986 } 6987 tellClientsWithResponse( fOutOfBandMessage ); 6988 break; 6989 6990 default: 6991 panic("servicePMWorkQueue: unknown machine state %x", 6992 fMachineState); 6993 } 6994 6995 gIOPMRequest = 0; 6996 6997 if (fMachineState == kIOPM_Finished) 6998 { 6999 done = true; 7000 break; 7001 } 7002 } 7003 7004 return done; 7005} 7006 7007//********************************************************************************* 7008// [private] executePMRequest 7009//********************************************************************************* 7010 7011void IOService::executePMRequest( IOPMRequest * request ) 7012{ 7013 assert( kIOPM_Finished == fMachineState ); 7014 7015 switch (request->getType()) 7016 { 7017 case kIOPMRequestTypePMStop: 7018 handlePMstop( request ); 7019 break; 7020 7021 case kIOPMRequestTypeAddPowerChild1: 7022 addPowerChild1( request ); 7023 break; 7024 7025 case kIOPMRequestTypeAddPowerChild2: 7026 addPowerChild2( request ); 7027 break; 7028 7029 case kIOPMRequestTypeAddPowerChild3: 7030 addPowerChild3( request ); 7031 break; 7032 7033 case kIOPMRequestTypeRegisterPowerDriver: 7034 handleRegisterPowerDriver( request ); 7035 break; 7036 7037 case kIOPMRequestTypeAdjustPowerState: 7038 fAdjustPowerScheduled = false; 7039 adjustPowerState(); 7040 break; 7041 7042 case kIOPMRequestTypePowerDomainWillChange: 7043 handlePowerDomainWillChangeTo( request ); 7044 break; 7045 7046 case kIOPMRequestTypePowerDomainDidChange: 7047 handlePowerDomainDidChangeTo( request ); 7048 break; 7049 7050 case kIOPMRequestTypeRequestPowerState: 7051 case kIOPMRequestTypeRequestPowerStateOverride: 7052 handleRequestPowerState( request ); 7053 break; 7054 7055 case kIOPMRequestTypePowerOverrideOnPriv: 7056 case kIOPMRequestTypePowerOverrideOffPriv: 7057 handlePowerOverrideChanged( request ); 7058 break; 7059 7060 case kIOPMRequestTypeActivityTickle: 7061 handleActivityTickle( request ); 7062 break; 7063 7064 case kIOPMRequestTypeSynchronizePowerTree: 7065 handleSynchronizePowerTree( request ); 7066 break; 7067 7068 case kIOPMRequestTypeSetIdleTimerPeriod: 7069 { 7070 fIdleTimerPeriod = (uintptr_t) request->fArg0; 7071 7072 if ((false == fLockedFlags.PMStop) && (fIdleTimerPeriod > 0)) 7073 { 7074 fActivityTickleCount = 0; 7075 clock_get_uptime(&fIdleTimerStartTime); 7076 start_PM_idle_timer(); 7077 } 7078 } 7079 break; 7080 7081 case kIOPMRequestTypeIgnoreIdleTimer: 7082 fIdleTimerIgnored = request->fArg0 ? 1 : 0; 7083 break; 7084 7085 default: 7086 panic("executePMRequest: unknown request type %x", request->getType()); 7087 } 7088} 7089 7090//********************************************************************************* 7091// [private] servicePMReplyQueue 7092//********************************************************************************* 7093 7094bool IOService::servicePMReplyQueue( IOPMRequest * request, IOPMRequestQueue * queue ) 7095{ 7096 bool more = false; 7097 7098 assert( request && queue ); 7099 assert( request->isReplyType() ); 7100 7101 PM_LOG1("[A %02x] %p [%p %s] state %d\n", 7102 request->getType(), request, this, getName(), fMachineState); 7103 7104 switch ( request->getType() ) 7105 { 7106 case kIOPMRequestTypeAllowPowerChange: 7107 case kIOPMRequestTypeCancelPowerChange: 7108 // Check if we are expecting this response. 7109 if (responseValid((uint32_t)(uintptr_t) request->fArg0, 7110 (int)(uintptr_t) request->fArg1)) 7111 { 7112 if (kIOPMRequestTypeCancelPowerChange == request->getType()) 7113 { 7114 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown 7115 // flag is set. Only root domain will set this flag. 7116 7117 if ((fHeadNoteChangeFlags & kIOPMSkipAskPowerDown) == 0) 7118 { 7119 fDoNotPowerDown = true; 7120 7121 OSString * name = (OSString *) request->fArg2; 7122 getPMRootDomain()->pmStatsRecordApplicationResponse( 7123 gIOPMStatsApplicationResponseCancel, 7124 name ? name->getCStringNoCopy() : "", 0, 7125 0, (int)(uintptr_t) request->fArg1); 7126 } 7127 } 7128 7129 if (checkForDone()) 7130 { 7131 stop_ack_timer(); 7132 cleanClientResponses(false); 7133 more = true; 7134 } 7135 } 7136 // OSString containing app name in Arg2 must be released. 7137 if (request->getType() == kIOPMRequestTypeCancelPowerChange) 7138 { 7139 OSObject * obj = (OSObject *) request->fArg2; 7140 if (obj) obj->release(); 7141 } 7142 break; 7143 7144 case kIOPMRequestTypeAckPowerChange: 7145 more = handleAcknowledgePowerChange( request ); 7146 break; 7147 7148 case kIOPMRequestTypeAckSetPowerState: 7149 if (fDriverTimer == -1) 7150 { 7151 // driver acked while setPowerState() call is in-flight. 7152 // take this ack, return value from setPowerState() is irrelevant. 7153 OUR_PMLog(kPMLogDriverAcknowledgeSet, 7154 (uintptr_t) this, fDriverTimer); 7155 fDriverTimer = 0; 7156 } 7157 else if (fDriverTimer > 0) 7158 { 7159 // expected ack, stop the timer 7160 stop_ack_timer(); 7161 7162#if LOG_SETPOWER_TIMES 7163 uint64_t nsec = computeTimeDeltaNS(&fDriverCallStartTime); 7164 if (nsec > LOG_SETPOWER_TIMES) 7165 PM_LOG("%s::setPowerState(%p, %lu -> %lu) async took %d ms\n", 7166 fName, this, fCurrentPowerState, fHeadNotePowerState, NS_TO_MS(nsec)); 7167 7168 PMEventDetails *details = PMEventDetails::eventDetails( 7169 kIOPMEventTypeSetPowerStateDelayed, // type 7170 fName, // who 7171 (uintptr_t)this, // owner unique 7172 NULL, // interest name 7173 (uint8_t)getPowerState(), // old 7174 (uint8_t)fHeadNotePowerState, // new 7175 0, // result 7176 NS_TO_US(nsec)); // usec completion time 7177 7178 getPMRootDomain()->recordAndReleasePMEventGated( details ); 7179#endif 7180 OUR_PMLog(kPMLogDriverAcknowledgeSet, (uintptr_t) this, fDriverTimer); 7181 fDriverTimer = 0; 7182 more = true; 7183 } 7184 else 7185 { 7186 // unexpected ack 7187 OUR_PMLog(kPMLogAcknowledgeErr4, (uintptr_t) this, 0); 7188 } 7189 break; 7190 7191 case kIOPMRequestTypeInterestChanged: 7192 handleInterestChanged( request ); 7193 more = true; 7194 break; 7195 7196 case kIOPMRequestTypeIdleCancel: 7197 if ((fMachineState == kIOPM_OurChangeTellClientsPowerDown) 7198 || (fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown) 7199 || (fMachineState == kIOPM_SyncTellClientsPowerDown) 7200 || (fMachineState == kIOPM_SyncTellPriorityClientsPowerDown)) 7201 { 7202 OUR_PMLog(kPMLogIdleCancel, (uintptr_t) this, fMachineState); 7203 PM_LOG2("%s: cancel from machine state %d\n", 7204 getName(), fMachineState); 7205 fDoNotPowerDown = true; 7206 // Stop waiting for app replys. 7207 if ((fMachineState == kIOPM_OurChangeTellPriorityClientsPowerDown) || 7208 (fMachineState == kIOPM_SyncTellPriorityClientsPowerDown)) 7209 cleanClientResponses(false); 7210 more = true; 7211 } 7212 break; 7213 7214 case kIOPMRequestTypeChildNotifyDelayCancel: 7215 if (fMachineState == kIOPM_NotifyChildrenDelayed) 7216 { 7217 PM_LOG2("%s: delay notify cancelled\n", getName()); 7218 notifyChildrenDelayed(); 7219 } 7220 break; 7221 7222 default: 7223 panic("servicePMReplyQueue: unknown reply type %x", 7224 request->getType()); 7225 } 7226 7227 more |= gIOPMFreeQueue->queuePMRequest(request); 7228 if (more) 7229 gIOPMWorkQueue->incrementProducerCount(); 7230 7231 return more; 7232} 7233 7234//********************************************************************************* 7235// [private] assertPMDriverCall / deassertPMDriverCall 7236//********************************************************************************* 7237 7238bool IOService::assertPMDriverCall( 7239 IOPMDriverCallEntry * entry, 7240 IOOptionBits options, 7241 IOPMinformee * inform ) 7242{ 7243 IOService * target = 0; 7244 bool ok = false; 7245 7246 if (!initialized) 7247 return false; 7248 7249 PM_LOCK(); 7250 7251 if (fLockedFlags.PMStop) 7252 { 7253 goto fail; 7254 } 7255 7256 if (((options & kIOPMADC_NoInactiveCheck) == 0) && isInactive()) 7257 { 7258 goto fail; 7259 } 7260 7261 if (inform) 7262 { 7263 if (!inform->active) 7264 { 7265 goto fail; 7266 } 7267 target = inform->whatObject; 7268 if (target->isInactive()) 7269 { 7270 goto fail; 7271 } 7272 } 7273 7274 entry->thread = current_thread(); 7275 entry->target = target; 7276 queue_enter(&fPMDriverCallQueue, entry, IOPMDriverCallEntry *, link); 7277 ok = true; 7278 7279fail: 7280 PM_UNLOCK(); 7281 7282 return ok; 7283} 7284 7285void IOService::deassertPMDriverCall( IOPMDriverCallEntry * entry ) 7286{ 7287 bool wakeup = false; 7288 7289 PM_LOCK(); 7290 7291 assert( !queue_empty(&fPMDriverCallQueue) ); 7292 queue_remove(&fPMDriverCallQueue, entry, IOPMDriverCallEntry *, link); 7293 if (fLockedFlags.PMDriverCallWait) 7294 { 7295 wakeup = true; 7296 } 7297 7298 PM_UNLOCK(); 7299 7300 if (wakeup) 7301 PM_LOCK_WAKEUP(&fPMDriverCallQueue); 7302} 7303 7304void IOService::waitForPMDriverCall( IOService * target ) 7305{ 7306 const IOPMDriverCallEntry * entry; 7307 thread_t thread = current_thread(); 7308 AbsoluteTime deadline; 7309 int waitResult; 7310 bool log = true; 7311 bool wait; 7312 7313 do { 7314 wait = false; 7315 queue_iterate(&fPMDriverCallQueue, entry, const IOPMDriverCallEntry *, link) 7316 { 7317 // Target of interested driver call 7318 if (target && (target != entry->target)) 7319 continue; 7320 7321 if (entry->thread == thread) 7322 { 7323 if (log) 7324 { 7325 PM_LOG("%s: %s(%s) on PM thread\n", 7326 fName, __FUNCTION__, target ? target->getName() : ""); 7327 OSReportWithBacktrace("%s: %s(%s) on PM thread\n", 7328 fName, __FUNCTION__, target ? target->getName() : ""); 7329 log = false; 7330 } 7331 continue; 7332 } 7333 7334 wait = true; 7335 break; 7336 } 7337 7338 if (wait) 7339 { 7340 fLockedFlags.PMDriverCallWait = true; 7341 clock_interval_to_deadline(15, kSecondScale, &deadline); 7342 waitResult = PM_LOCK_SLEEP(&fPMDriverCallQueue, deadline); 7343 fLockedFlags.PMDriverCallWait = false; 7344 if (THREAD_TIMED_OUT == waitResult) 7345 { 7346 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName); 7347 wait = false; 7348 } 7349 } 7350 } while (wait); 7351} 7352 7353//********************************************************************************* 7354// [private] Debug helpers 7355//********************************************************************************* 7356 7357const char * IOService::getIOMessageString( uint32_t msg ) 7358{ 7359#define MSG_ENTRY(x) {x, #x} 7360 7361 static const IONamedValue msgNames[] = { 7362 MSG_ENTRY( kIOMessageCanDevicePowerOff ), 7363 MSG_ENTRY( kIOMessageDeviceWillPowerOff ), 7364 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff ), 7365 MSG_ENTRY( kIOMessageDeviceHasPoweredOn ), 7366 MSG_ENTRY( kIOMessageCanSystemPowerOff ), 7367 MSG_ENTRY( kIOMessageSystemWillPowerOff ), 7368 MSG_ENTRY( kIOMessageSystemWillNotPowerOff ), 7369 MSG_ENTRY( kIOMessageCanSystemSleep ), 7370 MSG_ENTRY( kIOMessageSystemWillSleep ), 7371 MSG_ENTRY( kIOMessageSystemWillNotSleep ), 7372 MSG_ENTRY( kIOMessageSystemHasPoweredOn ), 7373 MSG_ENTRY( kIOMessageSystemWillRestart ), 7374 MSG_ENTRY( kIOMessageSystemWillPowerOn ), 7375 MSG_ENTRY( kIOMessageSystemCapabilityChange ) 7376 }; 7377 7378 return IOFindNameForValue(msg, msgNames); 7379} 7380 7381// MARK: - 7382// MARK: IOPMRequest 7383 7384//********************************************************************************* 7385// IOPMRequest Class 7386// 7387// Requests from PM clients, and also used for inter-object messaging within PM. 7388//********************************************************************************* 7389 7390OSDefineMetaClassAndStructors( IOPMRequest, IOCommand ); 7391 7392IOPMRequest * IOPMRequest::create( void ) 7393{ 7394 IOPMRequest * me = OSTypeAlloc(IOPMRequest); 7395 if (me && !me->init(0, kIOPMRequestTypeInvalid)) 7396 { 7397 me->release(); 7398 me = 0; 7399 } 7400 return me; 7401} 7402 7403bool IOPMRequest::init( IOService * target, IOOptionBits type ) 7404{ 7405 if (!IOCommand::init()) 7406 return false; 7407 7408 fType = type; 7409 fTarget = target; 7410 fCompletionStatus = kIOReturnSuccess; 7411 7412 if (fTarget) 7413 fTarget->retain(); 7414 7415 return true; 7416} 7417 7418void IOPMRequest::reset( void ) 7419{ 7420 assert( fWorkWaitCount == 0 ); 7421 assert( fFreeWaitCount == 0 ); 7422 7423 detachNextRequest(); 7424 detachRootRequest(); 7425 7426 fType = kIOPMRequestTypeInvalid; 7427 7428 if (fCompletionAction) 7429 { 7430 fCompletionAction(fCompletionTarget, fCompletionParam, fCompletionStatus); 7431 } 7432 7433 if (fTarget) 7434 { 7435 fTarget->release(); 7436 fTarget = 0; 7437 } 7438} 7439 7440bool IOPMRequest::attachNextRequest( IOPMRequest * next ) 7441{ 7442 bool ok = false; 7443 7444 if (!fRequestNext) 7445 { 7446 // Postpone the execution of the next request after 7447 // this request. 7448 fRequestNext = next; 7449 fRequestNext->fWorkWaitCount++; 7450#if LOG_REQUEST_ATTACH 7451 kprintf("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n", 7452 this, (uint32_t) fType, fRequestNext, 7453 (uint32_t) fRequestNext->fType, 7454 (uint32_t) fRequestNext->fWorkWaitCount, 7455 fTarget->getName()); 7456#endif 7457 ok = true; 7458 } 7459 return ok; 7460} 7461 7462bool IOPMRequest::detachNextRequest( void ) 7463{ 7464 bool ok = false; 7465 7466 if (fRequestNext) 7467 { 7468 assert(fRequestNext->fWorkWaitCount); 7469 if (fRequestNext->fWorkWaitCount) 7470 fRequestNext->fWorkWaitCount--; 7471#if LOG_REQUEST_ATTACH 7472 kprintf("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n", 7473 this, (uint32_t) fType, fRequestNext, 7474 (uint32_t) fRequestNext->fType, 7475 (uint32_t) fRequestNext->fWorkWaitCount, 7476 fTarget->getName()); 7477#endif 7478 fRequestNext = 0; 7479 ok = true; 7480 } 7481 return ok; 7482} 7483 7484bool IOPMRequest::attachRootRequest( IOPMRequest * root ) 7485{ 7486 bool ok = false; 7487 7488 if (!fRequestRoot) 7489 { 7490 // Delay the completion of the root request after 7491 // this request. 7492 fRequestRoot = root; 7493 fRequestRoot->fFreeWaitCount++; 7494#if LOG_REQUEST_ATTACH 7495 kprintf("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n", 7496 this, (uint32_t) fType, fRequestRoot, 7497 (uint32_t) fRequestRoot->fType, 7498 (uint32_t) fRequestRoot->fFreeWaitCount, 7499 fTarget->getName()); 7500#endif 7501 ok = true; 7502 } 7503 return ok; 7504} 7505 7506bool IOPMRequest::detachRootRequest( void ) 7507{ 7508 bool ok = false; 7509 7510 if (fRequestRoot) 7511 { 7512 assert(fRequestRoot->fFreeWaitCount); 7513 if (fRequestRoot->fFreeWaitCount) 7514 fRequestRoot->fFreeWaitCount--; 7515#if LOG_REQUEST_ATTACH 7516 kprintf("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n", 7517 this, (uint32_t) fType, fRequestRoot, 7518 (uint32_t) fRequestRoot->fType, 7519 (uint32_t) fRequestRoot->fFreeWaitCount, 7520 fTarget->getName()); 7521#endif 7522 fRequestRoot = 0; 7523 ok = true; 7524 } 7525 return ok; 7526} 7527 7528// MARK: - 7529// MARK: IOPMRequestQueue 7530 7531//********************************************************************************* 7532// IOPMRequestQueue Class 7533// 7534// Global queues. Queues are created once and never released. 7535//********************************************************************************* 7536 7537OSDefineMetaClassAndStructors( IOPMRequestQueue, IOEventSource ); 7538 7539IOPMRequestQueue * IOPMRequestQueue::create( IOService * inOwner, Action inAction ) 7540{ 7541 IOPMRequestQueue * me = OSTypeAlloc(IOPMRequestQueue); 7542 if (me && !me->init(inOwner, inAction)) 7543 { 7544 me->release(); 7545 me = 0; 7546 } 7547 return me; 7548} 7549 7550bool IOPMRequestQueue::init( IOService * inOwner, Action inAction ) 7551{ 7552 if (!inAction || !IOEventSource::init(inOwner, (IOEventSourceAction)inAction)) 7553 return false; 7554 7555 queue_init(&fQueue); 7556 fLock = IOLockAlloc(); 7557 return (fLock != 0); 7558} 7559 7560void IOPMRequestQueue::free( void ) 7561{ 7562 if (fLock) 7563 { 7564 IOLockFree(fLock); 7565 fLock = 0; 7566 } 7567 return IOEventSource::free(); 7568} 7569 7570void IOPMRequestQueue::queuePMRequest( IOPMRequest * request ) 7571{ 7572 assert(request); 7573 IOLockLock(fLock); 7574 queue_enter(&fQueue, request, IOPMRequest *, fCommandChain); 7575 IOLockUnlock(fLock); 7576 if (workLoop) signalWorkAvailable(); 7577} 7578 7579void 7580IOPMRequestQueue::queuePMRequestChain( IOPMRequest ** requests, IOItemCount count ) 7581{ 7582 IOPMRequest * next; 7583 7584 assert(requests && count); 7585 IOLockLock(fLock); 7586 while (count--) 7587 { 7588 next = *requests; 7589 requests++; 7590 queue_enter(&fQueue, next, IOPMRequest *, fCommandChain); 7591 } 7592 IOLockUnlock(fLock); 7593 if (workLoop) signalWorkAvailable(); 7594} 7595 7596bool IOPMRequestQueue::checkForWork( void ) 7597{ 7598 Action dqAction = (Action) action; 7599 IOPMRequest * request; 7600 IOService * target; 7601 bool more = false; 7602 7603 IOLockLock( fLock ); 7604 7605 while (!queue_empty(&fQueue)) 7606 { 7607 queue_remove_first( &fQueue, request, IOPMRequest *, fCommandChain ); 7608 IOLockUnlock( fLock ); 7609 target = request->getTarget(); 7610 assert(target); 7611 more |= (*dqAction)( target, request, this ); 7612 IOLockLock( fLock ); 7613 } 7614 7615 IOLockUnlock( fLock ); 7616 return more; 7617} 7618 7619// MARK: - 7620// MARK: IOPMWorkQueue 7621 7622//********************************************************************************* 7623// IOPMWorkQueue Class 7624// 7625// Queue of IOServicePM objects with busy IOPMRequest(s). 7626//********************************************************************************* 7627 7628OSDefineMetaClassAndStructors( IOPMWorkQueue, IOEventSource ); 7629 7630IOPMWorkQueue * 7631IOPMWorkQueue::create( IOService * inOwner, Action work, Action retire ) 7632{ 7633 IOPMWorkQueue * me = OSTypeAlloc(IOPMWorkQueue); 7634 if (me && !me->init(inOwner, work, retire)) 7635 { 7636 me->release(); 7637 me = 0; 7638 } 7639 return me; 7640} 7641 7642bool IOPMWorkQueue::init( IOService * inOwner, Action work, Action retire ) 7643{ 7644 if (!work || !retire || 7645 !IOEventSource::init(inOwner, (IOEventSourceAction)0)) 7646 return false; 7647 7648 queue_init(&fWorkQueue); 7649 7650 fWorkAction = work; 7651 fRetireAction = retire; 7652 fConsumerCount = fProducerCount = 0; 7653 7654 return true; 7655} 7656 7657bool IOPMWorkQueue::queuePMRequest( IOPMRequest * request, IOServicePM * pwrMgt ) 7658{ 7659 bool more = false; 7660 bool empty; 7661 7662 assert( request ); 7663 assert( pwrMgt ); 7664 assert( onThread() ); 7665 assert( queue_next(&request->fCommandChain) == 7666 queue_prev(&request->fCommandChain) ); 7667 7668 gIOPMBusyCount++; 7669 7670 // Add new request to the tail of the per-service request queue. 7671 // Then immediately check the request queue to minimize latency 7672 // if the queue was empty. 7673 7674 empty = queue_empty(&pwrMgt->RequestHead); 7675 queue_enter(&pwrMgt->RequestHead, request, IOPMRequest *, fCommandChain); 7676 if (empty) 7677 { 7678 more = checkRequestQueue(&pwrMgt->RequestHead, &empty); 7679 if (!empty) 7680 { 7681 // New Request is blocked, add IOServicePM to work queue. 7682 assert( queue_next(&pwrMgt->WorkChain) == 7683 queue_prev(&pwrMgt->WorkChain) ); 7684 7685 queue_enter(&fWorkQueue, pwrMgt, IOServicePM *, WorkChain); 7686 fQueueLength++; 7687 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n", 7688 fQueueLength, pwrMgt->Name, pwrMgt); 7689 } 7690 } 7691 7692 return more; 7693} 7694 7695bool IOPMWorkQueue::checkRequestQueue( queue_head_t * queue, bool * empty ) 7696{ 7697 IOPMRequest * request; 7698 IOService * target; 7699 bool more = false; 7700 bool done = false; 7701 7702 assert(!queue_empty(queue)); 7703 do { 7704 request = (IOPMRequest *) queue_first(queue); 7705 if (request->isWorkBlocked()) 7706 break; // cannot start, blocked on attached request 7707 7708 target = request->getTarget(); 7709 done = (*fWorkAction)( target, request, this ); 7710 if (!done) 7711 break; // work started, blocked on PM state machine 7712 7713 assert(gIOPMBusyCount > 0); 7714 if (gIOPMBusyCount) 7715 gIOPMBusyCount--; 7716 7717 queue_remove_first(queue, request, IOPMRequest *, fCommandChain); 7718 more |= (*fRetireAction)( target, request, this ); 7719 done = queue_empty(queue); 7720 } while (!done); 7721 7722 *empty = done; 7723 7724 if (more) 7725 { 7726 // Retired request blocks another request, since the 7727 // blocked request may reside in the work queue, we 7728 // must bump the producer count to avoid work stall. 7729 fProducerCount++; 7730 } 7731 7732 return more; 7733} 7734 7735bool IOPMWorkQueue::checkForWork( void ) 7736{ 7737 IOServicePM * entry; 7738 IOServicePM * next; 7739 bool more = false; 7740 bool empty; 7741 7742#if WORK_QUEUE_STATS 7743 fStatCheckForWork++; 7744#endif 7745 7746 // Each producer signal triggers a full iteration over 7747 // all IOServicePM entries in the work queue. 7748 7749 while (fConsumerCount != fProducerCount) 7750 { 7751 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n", 7752 fProducerCount, fConsumerCount); 7753 7754 fConsumerCount = fProducerCount; 7755 7756#if WORK_QUEUE_STATS 7757 if (queue_empty(&fWorkQueue)) 7758 { 7759 fStatQueueEmpty++; 7760 break; 7761 } 7762 fStatScanEntries++; 7763 uint32_t cachedWorkCount = gIOPMWorkCount; 7764#endif 7765 7766 entry = (IOServicePM *) queue_first(&fWorkQueue); 7767 while (!queue_end(&fWorkQueue, (queue_entry_t) entry)) 7768 { 7769 more |= checkRequestQueue(&entry->RequestHead, &empty); 7770 7771 // Get next entry, points to head if current entry is last. 7772 next = (IOServicePM *) queue_next(&entry->WorkChain); 7773 7774 // if request queue is empty, remove IOServicePM from queue. 7775 if (empty) 7776 { 7777 assert(fQueueLength); 7778 if (fQueueLength) fQueueLength--; 7779 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n", 7780 fQueueLength, entry->Name, entry); 7781 queue_remove(&fWorkQueue, entry, IOServicePM *, WorkChain); 7782 } 7783 entry = next; 7784 } 7785 7786#if WORK_QUEUE_STATS 7787 if (cachedWorkCount == gIOPMWorkCount) 7788 fStatNoWorkDone++; 7789#endif 7790 } 7791 7792 return more; 7793} 7794 7795void IOPMWorkQueue::signalWorkAvailable( void ) 7796{ 7797 fProducerCount++; 7798 IOEventSource::signalWorkAvailable(); 7799} 7800 7801void IOPMWorkQueue::incrementProducerCount( void ) 7802{ 7803 fProducerCount++; 7804} 7805 7806// MARK: - 7807// MARK: IOPMCompletionQueue 7808 7809//********************************************************************************* 7810// IOPMCompletionQueue Class 7811//********************************************************************************* 7812 7813OSDefineMetaClassAndStructors( IOPMCompletionQueue, IOEventSource ); 7814 7815IOPMCompletionQueue * 7816IOPMCompletionQueue::create( IOService * inOwner, Action inAction ) 7817{ 7818 IOPMCompletionQueue * me = OSTypeAlloc(IOPMCompletionQueue); 7819 if (me && !me->init(inOwner, inAction)) 7820 { 7821 me->release(); 7822 me = 0; 7823 } 7824 return me; 7825} 7826 7827bool IOPMCompletionQueue::init( IOService * inOwner, Action inAction ) 7828{ 7829 if (!inAction || !IOEventSource::init(inOwner, (IOEventSourceAction)inAction)) 7830 return false; 7831 7832 queue_init(&fQueue); 7833 return true; 7834} 7835 7836bool IOPMCompletionQueue::queuePMRequest( IOPMRequest * request ) 7837{ 7838 bool more; 7839 7840 assert(request); 7841 // unblock dependent request 7842 more = request->detachNextRequest(); 7843 queue_enter(&fQueue, request, IOPMRequest *, fCommandChain); 7844 return more; 7845} 7846 7847bool IOPMCompletionQueue::checkForWork( void ) 7848{ 7849 Action dqAction = (Action) action; 7850 IOPMRequest * request; 7851 IOPMRequest * next; 7852 IOService * target; 7853 bool more = false; 7854 7855 request = (IOPMRequest *) queue_first(&fQueue); 7856 while (!queue_end(&fQueue, (queue_entry_t) request)) 7857 { 7858 next = (IOPMRequest *) queue_next(&request->fCommandChain); 7859 if (!request->isFreeBlocked()) 7860 { 7861 queue_remove(&fQueue, request, IOPMRequest *, fCommandChain); 7862 target = request->getTarget(); 7863 assert(target); 7864 more |= (*dqAction)( target, request, this ); 7865 } 7866 request = next; 7867 } 7868 7869 return more; 7870} 7871 7872// MARK: - 7873// MARK: IOServicePM 7874 7875OSDefineMetaClassAndStructors(IOServicePM, OSObject) 7876 7877//********************************************************************************* 7878// serialize 7879// 7880// Serialize IOServicePM for debugging. 7881//********************************************************************************* 7882 7883static void 7884setPMProperty( OSDictionary * dict, const char * key, uint64_t value ) 7885{ 7886 OSNumber * num = OSNumber::withNumber(value, sizeof(value) * 8); 7887 if (num) 7888 { 7889 dict->setObject(key, num); 7890 num->release(); 7891 } 7892} 7893 7894IOReturn IOServicePM::gatedSerialize( OSSerialize * s ) 7895{ 7896 OSDictionary * dict; 7897 bool ok = false; 7898 int dictSize = 5; 7899 7900 if (IdleTimerPeriod) 7901 dictSize += 4; 7902 7903#if WORK_QUEUE_STATS 7904 if (gIOPMRootNode == ControllingDriver) 7905 dictSize += 4; 7906#endif 7907 7908 if (PowerClients) 7909 dict = OSDictionary::withDictionary( 7910 PowerClients, PowerClients->getCount() + dictSize); 7911 else 7912 dict = OSDictionary::withCapacity(dictSize); 7913 7914 if (dict) 7915 { 7916 setPMProperty(dict, "CurrentPowerState", CurrentPowerState); 7917 if (NumberOfPowerStates) 7918 setPMProperty(dict, "MaxPowerState", NumberOfPowerStates-1); 7919 if (DesiredPowerState != CurrentPowerState) 7920 setPMProperty(dict, "DesiredPowerState", DesiredPowerState); 7921 if (kIOPM_Finished != MachineState) 7922 setPMProperty(dict, "MachineState", MachineState); 7923 if (DeviceOverrideEnabled) 7924 dict->setObject("PowerOverrideOn", kOSBooleanTrue); 7925 7926 if (IdleTimerPeriod) 7927 { 7928 AbsoluteTime now; 7929 AbsoluteTime delta; 7930 uint64_t nsecs; 7931 7932 clock_get_uptime(&now); 7933 7934 // The idle timer period in milliseconds. 7935 setPMProperty(dict, "IdleTimerPeriod", IdleTimerPeriod * 1000ULL); 7936 7937 // The number of activity tickles recorded since device idle 7938 setPMProperty(dict, "ActivityTickles", ActivityTickleCount); 7939 7940 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp)) 7941 { 7942 // The number of milliseconds since the last activity tickle. 7943 delta = now; 7944 SUB_ABSOLUTETIME(&delta, &DeviceActiveTimestamp); 7945 absolutetime_to_nanoseconds(delta, &nsecs); 7946 setPMProperty(dict, "TimeSinceLastTickle", NS_TO_MS(nsecs)); 7947 } 7948 7949 if (AbsoluteTime_to_scalar(&IdleTimerStartTime)) 7950 { 7951 // The number of milliseconds since the last device idle. 7952 delta = now; 7953 SUB_ABSOLUTETIME(&delta, &IdleTimerStartTime); 7954 absolutetime_to_nanoseconds(delta, &nsecs); 7955 setPMProperty(dict, "TimeSinceDeviceIdle", NS_TO_MS(nsecs)); 7956 } 7957 } 7958 7959#if WORK_QUEUE_STATS 7960 if (gIOPMRootNode == Owner) 7961 { 7962 setPMProperty(dict, "WQ-CheckForWork", 7963 gIOPMWorkQueue->fStatCheckForWork); 7964 setPMProperty(dict, "WQ-ScanEntries", 7965 gIOPMWorkQueue->fStatScanEntries); 7966 setPMProperty(dict, "WQ-QueueEmpty", 7967 gIOPMWorkQueue->fStatQueueEmpty); 7968 setPMProperty(dict, "WQ-NoWorkDone", 7969 gIOPMWorkQueue->fStatNoWorkDone); 7970 } 7971#endif 7972 7973 if (HasAdvisoryDesire && !gIOPMAdvisoryTickleEnabled) 7974 { 7975 // Don't report advisory tickle when it has no influence 7976 dict->removeObject(gIOPMPowerClientAdvisoryTickle); 7977 } 7978 7979 ok = dict->serialize(s); 7980 dict->release(); 7981 } 7982 7983 return (ok ? kIOReturnSuccess : kIOReturnNoMemory); 7984} 7985 7986bool IOServicePM::serialize( OSSerialize * s ) const 7987{ 7988 IOReturn ret = kIOReturnNotReady; 7989 7990 if (gIOPMWorkLoop) 7991 { 7992 ret = gIOPMWorkLoop->runAction( 7993 OSMemberFunctionCast(IOWorkLoop::Action, this, &IOServicePM::gatedSerialize), 7994 (OSObject *) this, (void *) s); 7995 } 7996 7997 return (kIOReturnSuccess == ret); 7998} 7999 8000void IOServicePM::pmPrint( 8001 uint32_t event, 8002 uintptr_t param1, 8003 uintptr_t param2 ) const 8004{ 8005 gPlatform->PMLog(Name, event, param1, param2); 8006} 8007 8008void IOServicePM::pmTrace( 8009 uint32_t event, 8010 uintptr_t param1, 8011 uintptr_t param2 ) const 8012{ 8013 const char * who = Name; 8014 uint64_t regId = Owner->getRegistryEntryID(); 8015 uintptr_t name = 0; 8016 8017 static const uint32_t sStartStopBitField[] = 8018 { 0x00000000, 0x00000040 }; // Only Program Hardware so far 8019 8020 // Arcane formula from Hacker's Delight by Warren 8021 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31)) 8022 uint32_t sgnevent = ((int) event >> 31); 8023 uint32_t absevent = sgnevent ^ (event + sgnevent); 8024 uint32_t code = IODBG_POWER(absevent); 8025 8026 uint32_t bit = 1 << (absevent & 0x1f); 8027 if ((absevent < (sizeof(sStartStopBitField) * 8)) && 8028 (sStartStopBitField[absevent >> 5] & bit)) 8029 { 8030 // Or in the START or END bits, Start = 1 & END = 2 8031 // If sgnevent == 0 then START - 0 => START 8032 // else if sgnevent == -1 then START - -1 => END 8033 code |= DBG_FUNC_START - sgnevent; 8034 } 8035 8036 // Copy the first characters of the name into an uintptr_t 8037 for (uint32_t i = 0; (i < sizeof(uintptr_t) && who[i] != 0); i++) 8038 { 8039 ((char *) &name)[sizeof(uintptr_t) - i - 1] = who[i]; 8040 } 8041 8042 IOTimeStampConstant(code, name, (uintptr_t) regId, param1, param2); 8043} 8044 8045PMEventDetails* PMEventDetails::eventDetails(uint32_t type, 8046 const char *ownerName, 8047 uintptr_t ownerUnique, 8048 const char *interestName, 8049 uint8_t oldState, 8050 uint8_t newState, 8051 uint32_t result, 8052 uint32_t elapsedTimeUS) { 8053 8054 PMEventDetails *myself; 8055 myself = new PMEventDetails; 8056 8057 if(myself) { 8058 myself->eventType = type; 8059 myself->ownerName = ownerName; 8060 myself->ownerUnique = ownerUnique; 8061 myself->interestName = interestName; 8062 myself->oldState = oldState; 8063 myself->newState = newState; 8064 myself->result = result; 8065 myself->elapsedTimeUS = elapsedTimeUS; 8066 8067 myself->eventClassifier = kIOPMEventClassDriverEvent; 8068 } 8069 8070 return myself; 8071} 8072 8073 8074PMEventDetails* PMEventDetails::eventDetails(uint32_t type, 8075 const char *uuid, 8076 uint32_t reason, 8077 uint32_t result) { 8078 8079 PMEventDetails *myself; 8080 myself = new PMEventDetails; 8081 8082 if(myself) { 8083 myself->eventType = type; 8084 myself->uuid = uuid; 8085 myself->reason = reason; 8086 myself->result = result; 8087 8088 myself->eventClassifier = kIOPMEventClassSystemEvent; 8089 } 8090 8091 return myself; 8092} 8093 8094