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