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