2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
32 #include <IOKit/assert.h>
33 #include <IOKit/IOKitDebug.h>
34 #include <IOKit/IOLib.h>
35 #include <IOKit/IOMessage.h>
36 #include <IOKit/IOPlatformExpert.h>
37 #include <IOKit/IOService.h>
38 #include <IOKit/IOEventSource.h>
39 #include <IOKit/IOWorkLoop.h>
40 #include <IOKit/IOCommand.h>
41 #include <IOKit/IOTimeStamp.h>
42 #include <IOKit/IOReportMacros.h>
44 #include <IOKit/pwr_mgt/IOPMlog.h>
45 #include <IOKit/pwr_mgt/IOPMinformee.h>
46 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
47 #include <IOKit/pwr_mgt/IOPowerConnection.h>
48 #include <IOKit/pwr_mgt/RootDomain.h>
49 #include <IOKit/pwr_mgt/IOPMPrivate.h>
52 #include <sys/proc_internal.h>
53 #include <libkern/OSDebug.h>
54 #include <kern/thread.h>
56 // Required for notification instrumentation
57 #include "IOServicePrivate.h"
58 #include "IOServicePMPrivate.h"
59 #include "IOKitKernelInternal.h"
62 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
63 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
64 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
65 static void tellAppClientApplier(OSObject
* object
, void * arg
);
67 static uint64_t computeTimeDeltaNS( const AbsoluteTime
* start
)
72 clock_get_uptime(&now
);
73 SUB_ABSOLUTETIME(&now
, start
);
74 absolutetime_to_nanoseconds(now
, &nsec
);
79 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
82 // Container class for recording system power events
83 OSDefineMetaClassAndStructors( PMEventDetails
, OSObject
);
85 //******************************************************************************
87 //******************************************************************************
89 static bool gIOPMInitialized
= false;
90 static uint32_t gIOPMBusyCount
= 0;
91 static uint32_t gIOPMWorkCount
= 0;
92 static uint32_t gIOPMTickleGeneration
= 0;
93 static IOWorkLoop
* gIOPMWorkLoop
= 0;
94 static IOPMRequestQueue
* gIOPMRequestQueue
= 0;
95 static IOPMRequestQueue
* gIOPMReplyQueue
= 0;
96 static IOPMWorkQueue
* gIOPMWorkQueue
= 0;
97 static IOPMCompletionQueue
* gIOPMFreeQueue
= 0;
98 static IOPMRequest
* gIOPMRequest
= 0;
99 static IOService
* gIOPMRootNode
= 0;
100 static IOPlatformExpert
* gPlatform
= 0;
102 const OSSymbol
* gIOPMPowerClientDevice
= 0;
103 const OSSymbol
* gIOPMPowerClientDriver
= 0;
104 const OSSymbol
* gIOPMPowerClientChildProxy
= 0;
105 const OSSymbol
* gIOPMPowerClientChildren
= 0;
106 const OSSymbol
* gIOPMPowerClientRootDomain
= 0;
108 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= 0;
109 static bool gIOPMAdvisoryTickleEnabled
= true;
110 static thread_t gIOPMWatchDogThread
= NULL
;
112 static uint32_t getPMRequestType( void )
114 uint32_t type
= kIOPMRequestTypeInvalid
;
116 type
= gIOPMRequest
->getType();
120 static IOPMRequestTag
getPMRequestTag( void )
122 IOPMRequestTag tag
= 0;
124 (gIOPMRequest
->getType() == kIOPMRequestTypeRequestPowerStateOverride
))
126 tag
= gIOPMRequest
->fRequestTag
;
131 //******************************************************************************
133 //******************************************************************************
135 #define OBFUSCATE(x) ((void *)(VM_KERNEL_ADDRPERM(x)))
137 #define PM_ERROR(x...) do { kprintf(x);IOLog(x); \
138 IOService::getPMRootDomain()->sleepWakeDebugLog(x); \
140 #define PM_LOG(x...) do { kprintf(x); } while (false)
142 #define PM_LOG1(x...) do { \
143 if (kIOLogDebugPower & gIOKitDebug) \
144 kprintf(x); } while (false)
146 #define PM_LOG2(x...) do { \
147 if (kIOLogDebugPower & gIOKitDebug) \
148 kprintf(x); } while (false)
151 #define PM_LOG3(x...) do { kprintf(x); } while (false)
153 #define PM_LOG3(x...)
156 #define RD_LOG(x...) do { \
157 if ((kIOLogPMRootDomain & gIOKitDebug) && \
158 (getPMRootDomain() == this)) { \
159 kprintf("PMRD: " x); \
160 getPMRootDomain()->sleepWakeDebugLog(x); \
162 #define PM_ASSERT_IN_GATE(x) \
164 assert(gIOPMWorkLoop->inGate()); \
167 #define PM_LOCK() IOLockLock(fPMLock)
168 #define PM_UNLOCK() IOLockUnlock(fPMLock)
169 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
170 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
172 #define ns_per_us 1000
173 #define k30Seconds (30*1000000)
174 #define kMinAckTimeoutTicks (10*1000000)
175 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
176 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
177 #define kPwrMgtKey "IOPowerManagement"
179 #define OUR_PMLog(t, a, b) do { \
180 if (gIOKitDebug & kIOLogPower) \
181 pwrMgt->pmPrint(t, a, b); \
182 if (gIOKitTrace & kIOTracePowerMgmt) \
183 pwrMgt->pmTrace(t, a, b); \
186 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
187 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
189 #define SUPPORT_IDLE_CANCEL 1
191 #define kIOPMPowerStateMax 0xFFFFFFFF
192 #define kInvalidTicklePowerState kIOPMPowerStateMax
194 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
196 #define IS_PM_ROOT (this == gIOPMRootNode)
197 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
198 #define IS_POWER_DROP (StateOrder(fHeadNotePowerState) < StateOrder(fCurrentPowerState))
199 #define IS_POWER_RISE (StateOrder(fHeadNotePowerState) > StateOrder(fCurrentPowerState))
201 // log setPowerStates longer than (ns):
202 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
203 // log app responses longer than (ns):
204 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
205 // use message tracer to log messages longer than (ns):
206 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
209 kReserveDomainPower
= 1
213 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
214 assert(kIOPM_BadMachineState != n); \
215 fSavedMachineState = n; } while (false)
218 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
219 fMachineState = fSavedMachineState; \
220 fSavedMachineState = kIOPM_BadMachineState; } while (false)
222 #define PM_ACTION_0(a) \
223 do { if (fPMActions.a) { \
224 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
227 #define PM_ACTION_2(a, x, y) \
228 do { if (fPMActions.a) { \
229 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, \
230 getPMRequestTag()); } \
233 #define PM_ACTION_3(a, x, y, z) \
234 do { if (fPMActions.a) { \
235 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, z); } \
238 static OSNumber
* copyClientIDForNotification(
240 IOPMInterestContext
*context
);
242 static void logClientIDForNotification(
244 IOPMInterestContext
*context
,
245 const char *logString
);
247 //*********************************************************************************
250 // Check kgmacros after modifying machine states.
251 //*********************************************************************************
256 kIOPM_OurChangeTellClientsPowerDown
= 1,
257 kIOPM_OurChangeTellUserPMPolicyPowerDown
= 2,
258 kIOPM_OurChangeTellPriorityClientsPowerDown
= 3,
259 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 4,
260 kIOPM_OurChangeSetPowerState
= 5,
261 kIOPM_OurChangeWaitForPowerSettle
= 6,
262 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 7,
263 kIOPM_OurChangeTellCapabilityDidChange
= 8,
264 kIOPM_OurChangeFinish
= 9,
266 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
267 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
268 kIOPM_ParentChangeSetPowerState
= 12,
269 kIOPM_ParentChangeWaitForPowerSettle
= 13,
270 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
271 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
272 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
274 kIOPM_NotifyChildrenStart
= 17,
275 kIOPM_NotifyChildrenOrdered
= 18,
276 kIOPM_NotifyChildrenDelayed
= 19,
277 kIOPM_SyncTellClientsPowerDown
= 20,
278 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
279 kIOPM_SyncNotifyWillChange
= 22,
280 kIOPM_SyncNotifyDidChange
= 23,
281 kIOPM_SyncTellCapabilityDidChange
= 24,
282 kIOPM_SyncFinish
= 25,
283 kIOPM_TellCapabilityChangeDone
= 26,
284 kIOPM_DriverThreadCallDone
= 27,
286 kIOPM_BadMachineState
= 0xFFFFFFFF
289 //*********************************************************************************
292 // Initialize power management.
293 //*********************************************************************************
295 void IOService::PMinit( void )
299 if ( !gIOPMInitialized
)
301 gPlatform
= getPlatform();
302 gIOPMWorkLoop
= IOWorkLoop::workLoop();
305 gIOPMRequestQueue
= IOPMRequestQueue::create(
306 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
307 this, &IOService::servicePMRequestQueue
));
309 gIOPMReplyQueue
= IOPMRequestQueue::create(
310 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
311 this, &IOService::servicePMReplyQueue
));
313 gIOPMWorkQueue
= IOPMWorkQueue::create(
315 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
316 &IOService::servicePMRequest
),
317 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
318 &IOService::retirePMRequest
));
320 gIOPMFreeQueue
= IOPMCompletionQueue::create(
321 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
322 this, &IOService::servicePMFreeQueue
));
324 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
327 gIOPMRequestQueue
->release();
328 gIOPMRequestQueue
= 0;
331 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
334 gIOPMReplyQueue
->release();
338 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
341 gIOPMWorkQueue
->release();
345 if (gIOPMWorkLoop
->addEventSource(gIOPMFreeQueue
) !=
348 gIOPMFreeQueue
->release();
352 gIOPMPowerClientDevice
=
353 OSSymbol::withCStringNoCopy( "DevicePowerState" );
355 gIOPMPowerClientDriver
=
356 OSSymbol::withCStringNoCopy( "DriverPowerState" );
358 gIOPMPowerClientChildProxy
=
359 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
361 gIOPMPowerClientChildren
=
362 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
364 gIOPMPowerClientAdvisoryTickle
=
365 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
367 gIOPMPowerClientRootDomain
=
368 OSSymbol::withCStringNoCopy( "RootDomainPower" );
371 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMFreeQueue
)
372 gIOPMInitialized
= true;
374 if (!gIOPMInitialized
)
377 pwrMgt
= new IOServicePM
;
379 setProperty(kPwrMgtKey
, pwrMgt
);
381 queue_init(&pwrMgt
->WorkChain
);
382 queue_init(&pwrMgt
->RequestHead
);
383 queue_init(&pwrMgt
->PMDriverCallQueue
);
386 fPMLock
= IOLockAlloc();
387 fInterestedDrivers
= new IOPMinformeeList
;
388 fInterestedDrivers
->initialize();
389 fDesiredPowerState
= kPowerStateZero
;
390 fDeviceDesire
= kPowerStateZero
;
391 fInitialPowerChange
= true;
392 fInitialSetPowerState
= true;
393 fPreviousRequestPowerFlags
= 0;
394 fDeviceOverrideEnabled
= false;
395 fMachineState
= kIOPM_Finished
;
396 fSavedMachineState
= kIOPM_BadMachineState
;
397 fIdleTimerMinPowerState
= kPowerStateZero
;
398 fActivityLock
= IOLockAlloc();
399 fStrictTreeOrder
= false;
400 fActivityTicklePowerState
= kInvalidTicklePowerState
;
401 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
402 fControllingDriver
= NULL
;
404 fNumberOfPowerStates
= 0;
405 fCurrentPowerState
= kPowerStateZero
;
406 fParentsCurrentPowerFlags
= 0;
407 fMaxPowerState
= kPowerStateZero
;
409 fParentsKnowState
= false;
411 fResponseArray
= NULL
;
412 fNotifyClientArray
= NULL
;
413 fCurrentPowerConsumption
= kIOPMUnknown
;
414 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
416 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot()))
418 gIOPMRootNode
= this;
419 fParentsKnowState
= true;
421 else if (getProperty(kIOPMResetPowerStateOnWakeKey
) == kOSBooleanTrue
)
423 fResetPowerStateOnWake
= true;
428 fWatchdogTimer
= thread_call_allocate(
429 &IOService::watchdog_timer_expired
, (thread_call_param_t
)this);
432 fAckTimer
= thread_call_allocate(
433 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
434 fSettleTimer
= thread_call_allocate(
435 &settle_timer_expired
, (thread_call_param_t
)this);
436 fIdleTimer
= thread_call_allocate(
437 &idle_timer_expired
, (thread_call_param_t
)this);
438 fDriverCallEntry
= thread_call_allocate(
439 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
440 assert(fDriverCallEntry
);
442 // Check for powerChangeDone override.
443 if (OSMemberFunctionCast(void (*)(void),
444 getResourceService(), &IOService::powerChangeDone
) !=
445 OSMemberFunctionCast(void (*)(void),
446 this, &IOService::powerChangeDone
))
448 fPCDFunctionOverride
= true;
452 IOPMprot
* prot
= new IOPMprot
;
456 prot
->ourName
= fName
;
457 prot
->thePlatform
= gPlatform
;
462 pm_vars
= (void *) (uintptr_t) true;
469 //*********************************************************************************
472 // Free the data created by PMinit. Only called from IOService::free().
473 //*********************************************************************************
475 void IOService::PMfree( void )
482 assert(fMachineState
== kIOPM_Finished
);
483 assert(fInsertInterestSet
== NULL
);
484 assert(fRemoveInterestSet
== NULL
);
485 assert(fNotifyChildArray
== NULL
);
486 assert(queue_empty(&pwrMgt
->RequestHead
));
487 assert(queue_empty(&fPMDriverCallQueue
));
489 if (fWatchdogTimer
) {
490 thread_call_cancel(fWatchdogTimer
);
491 thread_call_free(fWatchdogTimer
);
492 fWatchdogTimer
= NULL
;
495 if ( fSettleTimer
) {
496 thread_call_cancel(fSettleTimer
);
497 thread_call_free(fSettleTimer
);
501 thread_call_cancel(fAckTimer
);
502 thread_call_free(fAckTimer
);
506 thread_call_cancel(fIdleTimer
);
507 thread_call_free(fIdleTimer
);
510 if ( fDriverCallEntry
) {
511 thread_call_free(fDriverCallEntry
);
512 fDriverCallEntry
= NULL
;
518 if ( fActivityLock
) {
519 IOLockFree(fActivityLock
);
520 fActivityLock
= NULL
;
522 if ( fInterestedDrivers
) {
523 fInterestedDrivers
->release();
524 fInterestedDrivers
= NULL
;
526 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
527 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
528 fDriverCallParamPtr
= 0;
529 fDriverCallParamSlots
= 0;
531 if ( fResponseArray
) {
532 fResponseArray
->release();
533 fResponseArray
= NULL
;
535 if ( fNotifyClientArray
) {
536 fNotifyClientArray
->release();
537 fNotifyClientArray
= NULL
;
539 if (fPowerStates
&& fNumberOfPowerStates
) {
540 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
541 fNumberOfPowerStates
= 0;
545 fPowerClients
->release();
562 void IOService::PMDebug( uint32_t event
, uintptr_t param1
, uintptr_t param2
)
564 OUR_PMLog(event
, param1
, param2
);
567 //*********************************************************************************
568 // [public] joinPMtree
570 // A policy-maker calls its nub here when initializing, to be attached into
571 // the power management hierarchy. The default function is to call the
572 // platform expert, which knows how to do it. This method is overridden
573 // by a nub subclass which may either know how to do it, or may need to
574 // take other action.
576 // This may be the only "power management" method used in a nub,
577 // meaning it may not be initialized for power management.
578 //*********************************************************************************
580 void IOService::joinPMtree( IOService
* driver
)
582 IOPlatformExpert
* platform
;
584 platform
= getPlatform();
585 assert(platform
!= 0);
586 platform
->PMRegisterDevice(this, driver
);
590 //*********************************************************************************
591 // [deprecated] youAreRoot
593 // Power Managment is informing us that we are the root power domain.
594 //*********************************************************************************
596 IOReturn
IOService::youAreRoot( void )
600 #endif /* !__LP64__ */
602 //*********************************************************************************
605 // Immediately stop driver callouts. Schedule an async stop request to detach
607 //*********************************************************************************
609 void IOService::PMstop( void )
611 IOPMRequest
* request
;
618 if (fLockedFlags
.PMStop
)
620 PM_LOG2("%s: PMstop() already stopped\n", fName
);
625 // Inhibit future driver calls.
626 fLockedFlags
.PMStop
= true;
628 // Wait for all prior driver calls to finish.
629 waitForPMDriverCall();
633 // The rest of the work is performed async.
634 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
637 PM_LOG2("%s: %p PMstop\n", getName(), OBFUSCATE(this));
638 submitPMRequest( request
);
642 //*********************************************************************************
643 // [private] handlePMstop
645 // Disconnect the node from all parents and children in the power plane.
646 //*********************************************************************************
648 void IOService::handlePMstop( IOPMRequest
* request
)
652 IOPowerConnection
* connection
;
653 IOService
* theChild
;
654 IOService
* theParent
;
657 PM_LOG2("%s: %p %s start\n", getName(), OBFUSCATE(this), __FUNCTION__
);
659 // remove driver from prevent system sleep lists
660 getPMRootDomain()->updatePreventIdleSleepList(this, false);
661 getPMRootDomain()->updatePreventSystemSleepList(this, false);
663 // remove the property
664 removeProperty(kPwrMgtKey
);
667 iter
= getParentIterator(gIOPowerPlane
);
670 while ( (next
= iter
->getNextObject()) )
672 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
674 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
677 theParent
->removePowerChild(connection
);
678 theParent
->release();
685 // detach IOConnections
686 detachAbove( gIOPowerPlane
);
688 // no more power state changes
689 fParentsKnowState
= false;
692 iter
= getChildIterator(gIOPowerPlane
);
695 while ( (next
= iter
->getNextObject()) )
697 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
699 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
702 // detach nub from child
703 connection
->detachFromChild(theChild
, gIOPowerPlane
);
706 // detach us from nub
707 detachFromChild(connection
, gIOPowerPlane
);
713 // Remove all interested drivers from the list, including the power
714 // controlling driver.
716 // Usually, the controlling driver and the policy-maker functionality
717 // are implemented by the same object, and without the deregistration,
718 // the object will be holding an extra retain on itself, and cannot
721 if ( fInterestedDrivers
)
723 IOPMinformeeList
* list
= fInterestedDrivers
;
727 while ((item
= list
->firstInList()))
729 list
->removeFromList(item
->whatObject
);
734 // Clear idle period to prevent idleTimerExpired() from servicing
735 // idle timer expirations.
737 fIdleTimerPeriod
= 0;
738 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
741 PM_LOG2("%s: %p %s done\n", getName(), OBFUSCATE(this), __FUNCTION__
);
744 //*********************************************************************************
745 // [public] addPowerChild
747 // Power Management is informing us who our children are.
748 //*********************************************************************************
750 IOReturn
IOService::addPowerChild( IOService
* child
)
752 IOPowerConnection
* connection
= 0;
753 IOPMRequest
* requests
[3] = {0, 0, 0};
758 return kIOReturnBadArgument
;
760 if (!initialized
|| !child
->initialized
)
761 return IOPMNotYetInitialized
;
763 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
766 // Is this child already one of our children?
768 iter
= child
->getParentIterator( gIOPowerPlane
);
771 IORegistryEntry
* entry
;
774 while ((next
= iter
->getNextObject()))
776 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
777 isChild(entry
, gIOPowerPlane
))
787 PM_LOG("%s: %s (%p) is already a child\n",
788 getName(), child
->getName(), OBFUSCATE(child
));
792 // Add the child to the power plane immediately, but the
793 // joining connection is marked as not ready.
794 // We want the child to appear in the power plane before
795 // returning to the caller, but don't want the caller to
796 // block on the PM work loop.
798 connection
= new IOPowerConnection
;
802 // Create a chain of PM requests to perform the bottom-half
803 // work from the PM work loop.
805 requests
[0] = acquirePMRequest(
807 /* type */ kIOPMRequestTypeAddPowerChild1
);
809 requests
[1] = acquirePMRequest(
811 /* type */ kIOPMRequestTypeAddPowerChild2
);
813 requests
[2] = acquirePMRequest(
815 /* type */ kIOPMRequestTypeAddPowerChild3
);
817 if (!requests
[0] || !requests
[1] || !requests
[2])
820 requests
[0]->attachNextRequest( requests
[1] );
821 requests
[1]->attachNextRequest( requests
[2] );
824 connection
->start(this);
825 connection
->setAwaitingAck(false);
826 connection
->setReadyFlag(false);
828 attachToChild( connection
, gIOPowerPlane
);
829 connection
->attachToChild( child
, gIOPowerPlane
);
831 // connection needs to be released
832 requests
[0]->fArg0
= connection
;
833 requests
[1]->fArg0
= connection
;
834 requests
[2]->fArg0
= connection
;
836 submitPMRequest( requests
, 3 );
837 return kIOReturnSuccess
;
841 if (connection
) connection
->release();
842 if (requests
[0]) releasePMRequest(requests
[0]);
843 if (requests
[1]) releasePMRequest(requests
[1]);
844 if (requests
[2]) releasePMRequest(requests
[2]);
846 // Silent failure, to prevent platform drivers from adding the child
847 // to the root domain.
849 return kIOReturnSuccess
;
852 //*********************************************************************************
853 // [private] addPowerChild1
855 // Step 1/3 of adding a power child. Called on the power parent.
856 //*********************************************************************************
858 void IOService::addPowerChild1( IOPMRequest
* request
)
860 IOPMPowerStateIndex tempDesire
= kPowerStateZero
;
862 // Make us temporary usable before adding the child.
865 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
867 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
869 tempDesire
= fHighestPowerState
;
872 if ((tempDesire
!= kPowerStateZero
) &&
873 (IS_PM_ROOT
|| (StateOrder(fMaxPowerState
) >= StateOrder(tempDesire
))))
875 adjustPowerState(tempDesire
);
879 //*********************************************************************************
880 // [private] addPowerChild2
882 // Step 2/3 of adding a power child. Called on the joining child.
883 // Execution blocked behind addPowerChild1.
884 //*********************************************************************************
886 void IOService::addPowerChild2( IOPMRequest
* request
)
888 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
890 IOPMPowerFlags powerFlags
;
892 unsigned long powerState
;
893 unsigned long tempDesire
;
896 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
898 if (!parent
|| !inPlane(gIOPowerPlane
))
900 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
904 // Parent will be waiting for us to complete this stage.
905 // It is safe to directly access parent's vars.
907 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
908 powerState
= parent
->fCurrentPowerState
;
911 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
915 // Set our power parent.
917 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
919 setParentInfo( powerFlags
, connection
, knowsState
);
921 connection
->setReadyFlag(true);
923 if ( fControllingDriver
&& fParentsKnowState
)
925 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
926 // initially change into the state we are already in
927 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
928 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
929 adjustPowerState(tempDesire
);
932 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
935 //*********************************************************************************
936 // [private] addPowerChild3
938 // Step 3/3 of adding a power child. Called on the parent.
939 // Execution blocked behind addPowerChild2.
940 //*********************************************************************************
942 void IOService::addPowerChild3( IOPMRequest
* request
)
944 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
946 IOPMrootDomain
* rootDomain
= getPMRootDomain();
949 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
951 if (child
&& inPlane(gIOPowerPlane
))
953 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder"))
955 PM_LOG1("%s: strict PM order enforced\n", getName());
956 fStrictTreeOrder
= true;
960 rootDomain
->joinAggressiveness( child
);
964 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
967 connection
->release();
971 //*********************************************************************************
972 // [deprecated] setPowerParent
974 // Power Management is informing us who our parent is.
975 // If we have a controlling driver, find out, given our newly-informed
976 // power domain state, what state it would be in, and then tell it
977 // to assume that state.
978 //*********************************************************************************
980 IOReturn
IOService::setPowerParent(
981 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
983 return kIOReturnUnsupported
;
985 #endif /* !__LP64__ */
987 //*********************************************************************************
988 // [public] removePowerChild
990 // Called on a parent whose child is being removed by PMstop().
991 //*********************************************************************************
993 IOReturn
IOService::removePowerChild( IOPowerConnection
* theNub
)
995 IORegistryEntry
* theChild
;
998 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1002 // detach nub from child
1003 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1006 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1007 theChild
->release();
1009 // detach from the nub
1010 detachFromChild(theNub
, gIOPowerPlane
);
1012 // Are we awaiting an ack from this child?
1013 if ( theNub
->getAwaitingAck() )
1015 // yes, pretend we got one
1016 theNub
->setAwaitingAck(false);
1017 if (fHeadNotePendingAcks
!= 0 )
1019 // that's one fewer ack to worry about
1020 fHeadNotePendingAcks
--;
1022 // is that the last?
1023 if ( fHeadNotePendingAcks
== 0 )
1027 // Request unblocked, work queue
1028 // should re-scan all busy requests.
1029 gIOPMWorkQueue
->incrementProducerCount();
1036 // A child has gone away, re-scan children desires and clamp bits.
1037 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1039 if (!fAdjustPowerScheduled
)
1041 IOPMRequest
* request
;
1042 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1045 submitPMRequest( request
);
1046 fAdjustPowerScheduled
= true;
1053 //*********************************************************************************
1054 // [public] registerPowerDriver
1056 // A driver has called us volunteering to control power to our device.
1057 //*********************************************************************************
1059 IOReturn
IOService::registerPowerDriver(
1060 IOService
* powerDriver
,
1061 IOPMPowerState
* powerStates
,
1062 unsigned long numberOfStates
)
1064 IOPMRequest
* request
;
1065 IOPMPSEntry
* powerStatesCopy
= 0;
1066 IOPMPowerStateIndex stateOrder
;
1067 IOReturn error
= kIOReturnSuccess
;
1070 return IOPMNotYetInitialized
;
1072 if (!powerStates
|| (numberOfStates
< 2))
1074 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1075 return kIOReturnBadArgument
;
1078 if (!powerDriver
|| !powerDriver
->initialized
)
1080 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1081 return kIOReturnBadArgument
;
1084 if (powerStates
[0].version
> kIOPMPowerStateVersion2
)
1086 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1087 return kIOReturnBadArgument
;
1091 // Make a copy of the supplied power state array.
1092 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1093 if (!powerStatesCopy
)
1095 error
= kIOReturnNoMemory
;
1099 // Initialize to bogus values
1100 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1101 powerStatesCopy
[i
].stateOrderToIndex
= kIOPMPowerStateMax
;
1103 for (uint32_t i
= 0; i
< numberOfStates
; i
++)
1105 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1106 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1107 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1108 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1109 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1110 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1111 if (powerStates
[i
].version
>= kIOPMPowerStateVersion2
)
1112 stateOrder
= powerStates
[i
].stateOrder
;
1116 if (stateOrder
< numberOfStates
)
1118 powerStatesCopy
[i
].stateOrder
= stateOrder
;
1119 powerStatesCopy
[stateOrder
].stateOrderToIndex
= i
;
1123 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1125 if (powerStatesCopy
[i
].stateOrderToIndex
== kIOPMPowerStateMax
)
1127 // power state order missing
1128 error
= kIOReturnBadArgument
;
1132 if (kIOReturnSuccess
!= error
)
1135 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1138 error
= kIOReturnNoMemory
;
1142 powerDriver
->retain();
1143 request
->fArg0
= (void *) powerDriver
;
1144 request
->fArg1
= (void *) powerStatesCopy
;
1145 request
->fArg2
= (void *) numberOfStates
;
1147 submitPMRequest( request
);
1148 return kIOReturnSuccess
;
1152 if (powerStatesCopy
)
1153 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1158 //*********************************************************************************
1159 // [private] handleRegisterPowerDriver
1160 //*********************************************************************************
1162 void IOService::handleRegisterPowerDriver( IOPMRequest
* request
)
1164 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1165 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1166 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1167 unsigned long i
, stateIndex
;
1168 unsigned long lowestPowerState
;
1172 PM_ASSERT_IN_GATE();
1173 assert(powerStates
);
1174 assert(powerDriver
);
1175 assert(numberOfStates
> 1);
1177 if ( !fNumberOfPowerStates
)
1179 OUR_PMLog(kPMLogControllingDriver
,
1180 (unsigned long) numberOfStates
,
1181 (unsigned long) kIOPMPowerStateVersion1
);
1183 fPowerStates
= powerStates
;
1184 fNumberOfPowerStates
= numberOfStates
;
1185 fControllingDriver
= powerDriver
;
1186 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1188 lowestPowerState
= fPowerStates
[0].stateOrderToIndex
;
1189 fHighestPowerState
= fPowerStates
[numberOfStates
- 1].stateOrderToIndex
;
1191 // OR'in all the output power flags
1192 fMergedOutputPowerFlags
= 0;
1193 fDeviceUsablePowerState
= lowestPowerState
;
1194 for ( i
= 0; i
< numberOfStates
; i
++ )
1196 fMergedOutputPowerFlags
|= fPowerStates
[i
].outputPowerFlags
;
1198 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
1199 assert(stateIndex
< numberOfStates
);
1200 if ((fDeviceUsablePowerState
== lowestPowerState
) &&
1201 (fPowerStates
[stateIndex
].capabilityFlags
& IOPMDeviceUsable
))
1203 // The minimum power state that the device is usable
1204 fDeviceUsablePowerState
= stateIndex
;
1208 // Register powerDriver as interested, unless already done.
1209 // We don't want to register the default implementation since
1210 // it does nothing. One ramification of not always registering
1211 // is the one fewer retain count held.
1213 root
= getPlatform()->getProvider();
1216 ((OSMemberFunctionCast(void (*)(void),
1217 root
, &IOService::powerStateDidChangeTo
)) !=
1218 ((OSMemberFunctionCast(void (*)(void),
1219 this, &IOService::powerStateDidChangeTo
)))) ||
1220 ((OSMemberFunctionCast(void (*)(void),
1221 root
, &IOService::powerStateWillChangeTo
)) !=
1222 ((OSMemberFunctionCast(void (*)(void),
1223 this, &IOService::powerStateWillChangeTo
)))))
1225 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
)
1228 fInterestedDrivers
->appendNewInformee(powerDriver
);
1233 // Examine all existing power clients and perform limit check.
1235 if (fPowerClients
&&
1236 (iter
= OSCollectionIterator::withCollection(fPowerClients
)))
1238 const OSSymbol
* client
;
1239 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
1241 IOPMPowerStateIndex powerState
= getPowerStateForClient(client
);
1242 if (powerState
>= numberOfStates
)
1244 updatePowerClient(client
, fHighestPowerState
);
1250 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1252 IOPMPowerStateIndex tempDesire
;
1253 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1254 // initially change into the state we are already in
1255 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1256 adjustPowerState(tempDesire
);
1261 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1262 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1265 powerDriver
->release();
1268 //*********************************************************************************
1269 // [public] registerInterestedDriver
1271 // Add the caller to our list of interested drivers and return our current
1272 // power state. If we don't have a power-controlling driver yet, we will
1273 // call this interested driver again later when we do get a driver and find
1274 // out what the current power state of the device is.
1275 //*********************************************************************************
1277 IOPMPowerFlags
IOService::registerInterestedDriver( IOService
* driver
)
1279 IOPMRequest
* request
;
1282 if (!driver
|| !initialized
|| !fInterestedDrivers
)
1286 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1287 if (fInsertInterestSet
== NULL
)
1288 fInsertInterestSet
= OSSet::withCapacity(4);
1289 if (fInsertInterestSet
)
1291 fInsertInterestSet
->setObject(driver
);
1292 if (fRemoveInterestSet
)
1293 fRemoveInterestSet
->removeObject(driver
);
1299 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1301 submitPMRequest( request
);
1304 // This return value cannot be trusted, but return a value
1305 // for those clients that care.
1307 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1308 return kIOPMDeviceUsable
;
1311 //*********************************************************************************
1312 // [public] deRegisterInterestedDriver
1313 //*********************************************************************************
1315 IOReturn
IOService::deRegisterInterestedDriver( IOService
* driver
)
1317 IOPMinformeeList
* list
;
1318 IOPMinformee
* item
;
1319 IOPMRequest
* request
;
1323 return kIOReturnBadArgument
;
1324 if (!initialized
|| !fInterestedDrivers
)
1325 return IOPMNotPowerManaged
;
1328 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1329 if (fRemoveInterestSet
== NULL
)
1330 fRemoveInterestSet
= OSSet::withCapacity(4);
1331 if (fRemoveInterestSet
)
1333 fRemoveInterestSet
->setObject(driver
);
1334 if (fInsertInterestSet
)
1335 fInsertInterestSet
->removeObject(driver
);
1337 list
= fInterestedDrivers
;
1338 item
= list
->findItem(driver
);
1339 if (item
&& item
->active
)
1341 item
->active
= false;
1342 waitForPMDriverCall( driver
);
1349 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1351 submitPMRequest( request
);
1357 //*********************************************************************************
1358 // [private] handleInterestChanged
1360 // Handle interest added or removed.
1361 //*********************************************************************************
1363 void IOService::handleInterestChanged( IOPMRequest
* request
)
1366 IOPMinformee
* informee
;
1367 IOPMinformeeList
* list
= fInterestedDrivers
;
1371 if (fInsertInterestSet
)
1373 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject()))
1375 if (list
->findItem(driver
) == NULL
)
1377 informee
= list
->appendNewInformee(driver
);
1379 fInsertInterestSet
->removeObject(driver
);
1381 fInsertInterestSet
->release();
1382 fInsertInterestSet
= 0;
1385 if (fRemoveInterestSet
)
1387 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject()))
1389 informee
= list
->findItem(driver
);
1392 // Clean-up async interest acknowledgement
1393 if (fHeadNotePendingAcks
&& informee
->timer
)
1395 informee
->timer
= 0;
1396 fHeadNotePendingAcks
--;
1398 list
->removeFromList(driver
);
1400 fRemoveInterestSet
->removeObject(driver
);
1402 fRemoveInterestSet
->release();
1403 fRemoveInterestSet
= 0;
1409 //*********************************************************************************
1410 // [public] acknowledgePowerChange
1412 // After we notified one of the interested drivers or a power-domain child
1413 // of an impending change in power, it has called to say it is now
1414 // prepared for the change. If this object is the last to
1415 // acknowledge this change, we take whatever action we have been waiting
1417 // That may include acknowledging to our parent. In this case, we do it
1418 // last of all to insure that this doesn't cause the parent to call us some-
1419 // where else and alter data we are relying on here (like the very existance
1420 // of a "current change note".)
1421 //*********************************************************************************
1423 IOReturn
IOService::acknowledgePowerChange( IOService
* whichObject
)
1425 IOPMRequest
* request
;
1428 return IOPMNotYetInitialized
;
1430 return kIOReturnBadArgument
;
1432 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1434 return kIOReturnNoMemory
;
1436 whichObject
->retain();
1437 request
->fArg0
= whichObject
;
1439 submitPMRequest( request
);
1443 //*********************************************************************************
1444 // [private] handleAcknowledgePowerChange
1445 //*********************************************************************************
1447 bool IOService::handleAcknowledgePowerChange( IOPMRequest
* request
)
1449 IOPMinformee
* informee
;
1450 unsigned long childPower
= kIOPMUnknown
;
1451 IOService
* theChild
;
1452 IOService
* whichObject
;
1453 bool all_acked
= false;
1455 PM_ASSERT_IN_GATE();
1456 whichObject
= (IOService
*) request
->fArg0
;
1457 assert(whichObject
);
1459 // one of our interested drivers?
1460 informee
= fInterestedDrivers
->findItem( whichObject
);
1461 if ( informee
== NULL
)
1463 if ( !isChild(whichObject
, gIOPowerPlane
) )
1465 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1468 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1471 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1474 if ( fHeadNotePendingAcks
!= 0 )
1476 assert(fPowerStates
!= NULL
);
1478 // yes, make sure we're expecting acks
1479 if ( informee
!= NULL
)
1481 // it's an interested driver
1482 // make sure we're expecting this ack
1483 if ( informee
->timer
!= 0 )
1485 #if LOG_SETPOWER_TIMES
1486 if (informee
->timer
> 0)
1488 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1489 if (nsec
> LOG_SETPOWER_TIMES
)
1490 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) async took %d ms\n",
1491 informee
->whatObject
->getName(),
1492 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
1493 OBFUSCATE(informee
->whatObject
),
1494 fName
, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_US(nsec
));
1496 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
1497 ? kIOPMEventTypePSWillChangeTo
1498 : kIOPMEventTypePSDidChangeTo
;
1500 PMEventDetails
*details
= PMEventDetails::eventDetails(
1504 informee
->whatObject
->getName(),
1508 getPMRootDomain()->recordAndReleasePMEvent( details
);
1512 informee
->timer
= 0;
1513 // that's one fewer to worry about
1514 fHeadNotePendingAcks
--;
1516 // this driver has already acked
1517 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1521 // make sure we're expecting this ack
1522 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1524 // that's one fewer to worry about
1525 fHeadNotePendingAcks
--;
1526 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1527 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1530 childPower
= theChild
->currentPowerConsumption();
1531 theChild
->release();
1533 if ( childPower
== kIOPMUnknown
)
1535 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1537 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
1539 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1545 if ( fHeadNotePendingAcks
== 0 ) {
1546 // yes, stop the timer
1548 // and now we can continue
1552 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1557 whichObject
->release();
1562 //*********************************************************************************
1563 // [public] acknowledgeSetPowerState
1565 // After we instructed our controlling driver to change power states,
1566 // it has called to say it has finished doing so.
1567 // We continue to process the power state change.
1568 //*********************************************************************************
1570 IOReturn
IOService::acknowledgeSetPowerState( void )
1572 IOPMRequest
* request
;
1575 return IOPMNotYetInitialized
;
1577 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1579 return kIOReturnNoMemory
;
1581 submitPMRequest( request
);
1582 return kIOReturnSuccess
;
1585 //*********************************************************************************
1586 // [private] adjustPowerState
1587 //*********************************************************************************
1589 void IOService::adjustPowerState( uint32_t clamp
)
1591 PM_ASSERT_IN_GATE();
1592 computeDesiredState(clamp
, false);
1593 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
))
1595 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1597 // Indicate that children desires must be ignored, and do not ask
1598 // apps for permission to drop power. This is used by root domain
1599 // for demand sleep.
1601 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
1602 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1605 /* flags */ changeFlags
,
1606 /* power state */ fDesiredPowerState
,
1607 /* domain flags */ 0,
1609 /* parent flags */ 0);
1613 //*********************************************************************************
1614 // [public] synchronizePowerTree
1615 //*********************************************************************************
1617 IOReturn
IOService::synchronizePowerTree(
1618 IOOptionBits options
,
1619 IOService
* notifyRoot
)
1621 IOPMRequest
* request_c
= 0;
1622 IOPMRequest
* request_s
;
1624 if (this != getPMRootDomain())
1625 return kIOReturnBadArgument
;
1627 return kIOPMNotYetInitialized
;
1629 OUR_PMLog(kPMLogCSynchronizePowerTree
, options
, (notifyRoot
!= 0));
1635 // Cancels don't need to be synchronized.
1636 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1637 if (nr
) submitPMRequest(nr
);
1638 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1639 if (nr
) submitPMRequest(nr
);
1642 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1644 goto error_no_memory
;
1646 if (options
& kIOPMSyncCancelPowerDown
)
1647 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1650 request_c
->attachNextRequest( request_s
);
1651 submitPMRequest(request_c
);
1654 request_s
->fArg0
= (void *)(uintptr_t) options
;
1655 submitPMRequest(request_s
);
1657 return kIOReturnSuccess
;
1660 if (request_c
) releasePMRequest(request_c
);
1661 if (request_s
) releasePMRequest(request_s
);
1662 return kIOReturnNoMemory
;
1665 //*********************************************************************************
1666 // [private] handleSynchronizePowerTree
1667 //*********************************************************************************
1669 void IOService::handleSynchronizePowerTree( IOPMRequest
* request
)
1671 PM_ASSERT_IN_GATE();
1672 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1673 (fCurrentPowerState
== fHighestPowerState
))
1675 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1678 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1679 (options
& kIOPMSyncNoChildNotify
),
1680 /* power state */ fCurrentPowerState
,
1681 /* domain flags */ 0,
1683 /* parent flags */ 0);
1688 //*********************************************************************************
1689 // [deprecated] powerDomainWillChangeTo
1691 // Called by the power-hierarchy parent notifying of a new power state
1692 // in the power domain.
1693 // We enqueue a parent power-change to our queue of power changes.
1694 // This may or may not cause us to change power, depending on what
1695 // kind of change is occuring in the domain.
1696 //*********************************************************************************
1698 IOReturn
IOService::powerDomainWillChangeTo(
1699 IOPMPowerFlags newPowerFlags
,
1700 IOPowerConnection
* whichParent
)
1703 return kIOReturnUnsupported
;
1705 #endif /* !__LP64__ */
1707 //*********************************************************************************
1708 // [private] handlePowerDomainWillChangeTo
1709 //*********************************************************************************
1711 void IOService::handlePowerDomainWillChangeTo( IOPMRequest
* request
)
1713 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1714 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1715 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1716 IOPMPowerChangeFlags myChangeFlags
;
1719 IOPowerConnection
* connection
;
1720 IOPMPowerStateIndex maxPowerState
;
1721 IOPMPowerFlags combinedPowerFlags
;
1722 bool savedParentsKnowState
;
1723 IOReturn result
= IOPMAckImplied
;
1725 PM_ASSERT_IN_GATE();
1726 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1728 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1730 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1734 savedParentsKnowState
= fParentsKnowState
;
1736 // Combine parents' output power flags.
1738 combinedPowerFlags
= 0;
1740 iter
= getParentIterator(gIOPowerPlane
);
1743 while ( (next
= iter
->getNextObject()) )
1745 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1747 if ( connection
== whichParent
)
1748 combinedPowerFlags
|= parentPowerFlags
;
1750 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1756 // If our initial change has yet to occur, then defer the power change
1757 // until after the power domain has completed its power transition.
1759 if ( fControllingDriver
&& !fInitialPowerChange
)
1761 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1762 combinedPowerFlags
);
1764 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1765 // to avoid propagating the root change flags if any service must
1766 // change power state due to root's will-change notification.
1767 // Root does not change power state for kIOPMSynchronize.
1769 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1770 (parentChangeFlags
& kIOPMSynchronize
);
1772 result
= startPowerChange(
1773 /* flags */ myChangeFlags
,
1774 /* power state */ maxPowerState
,
1775 /* domain flags */ combinedPowerFlags
,
1776 /* connection */ whichParent
,
1777 /* parent flags */ parentPowerFlags
);
1780 // If parent is dropping power, immediately update the parent's
1781 // capability flags. Any future merging of parent(s) combined
1782 // power flags should account for this power drop.
1784 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1786 setParentInfo(parentPowerFlags
, whichParent
, true);
1789 // Parent is expecting an ACK from us. If we did not embark on a state
1790 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1791 // still required to issue an ACK to our parent.
1793 if (IOPMAckImplied
== result
)
1796 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1800 parent
->acknowledgePowerChange( whichParent
);
1806 // Drop the retain from notifyChild().
1807 if (whichParent
) whichParent
->release();
1811 //*********************************************************************************
1812 // [deprecated] powerDomainDidChangeTo
1814 // Called by the power-hierarchy parent after the power state of the power domain
1815 // has settled at a new level.
1816 // We enqueue a parent power-change to our queue of power changes.
1817 // This may or may not cause us to change power, depending on what
1818 // kind of change is occuring in the domain.
1819 //*********************************************************************************
1821 IOReturn
IOService::powerDomainDidChangeTo(
1822 IOPMPowerFlags newPowerFlags
,
1823 IOPowerConnection
* whichParent
)
1826 return kIOReturnUnsupported
;
1828 #endif /* !__LP64__ */
1830 //*********************************************************************************
1831 // [private] handlePowerDomainDidChangeTo
1832 //*********************************************************************************
1834 void IOService::handlePowerDomainDidChangeTo( IOPMRequest
* request
)
1836 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1837 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1838 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1839 IOPMPowerChangeFlags myChangeFlags
;
1840 IOPMPowerStateIndex maxPowerState
;
1841 IOPMPowerStateIndex initialDesire
= kPowerStateZero
;
1842 bool computeDesire
= false;
1843 bool desireChanged
= false;
1844 bool savedParentsKnowState
;
1845 IOReturn result
= IOPMAckImplied
;
1847 PM_ASSERT_IN_GATE();
1848 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1850 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1852 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1856 savedParentsKnowState
= fParentsKnowState
;
1858 setParentInfo(parentPowerFlags
, whichParent
, true);
1860 if ( fControllingDriver
)
1862 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1863 fParentsCurrentPowerFlags
);
1865 if (fInitialPowerChange
)
1867 computeDesire
= true;
1868 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1869 fParentsCurrentPowerFlags
);
1871 else if (parentChangeFlags
& kIOPMRootChangeUp
)
1873 if (fAdvisoryTickleUsed
)
1875 // On system wake, re-compute the desired power state since
1876 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1877 // which is an input to computeDesiredState(). This is not
1878 // necessary for a dark wake because powerChangeDone() will
1879 // handle the dark to full wake case, but it does no harm.
1881 desireChanged
= true;
1884 if (fResetPowerStateOnWake
)
1886 // Query the driver for the desired power state on system wake.
1887 // Default implementation returns the lowest power state.
1889 IOPMPowerStateIndex wakePowerState
=
1890 fControllingDriver
->initialPowerStateForDomainState(
1891 kIOPMRootDomainState
| kIOPMPowerOn
);
1893 // fDesiredPowerState was adjusted before going to sleep
1894 // with fDeviceDesire at min.
1896 if (StateOrder(wakePowerState
) > StateOrder(fDesiredPowerState
))
1898 // Must schedule a power adjustment if we changed the
1899 // device desire. That will update the desired domain
1900 // power on the parent power connection and ping the
1901 // power parent if necessary.
1903 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1904 desireChanged
= true;
1909 if (computeDesire
|| desireChanged
)
1910 computeDesiredState(initialDesire
, false);
1912 // Absorb and propagate parent's broadcast flags
1913 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1914 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1916 result
= startPowerChange(
1917 /* flags */ myChangeFlags
,
1918 /* power state */ maxPowerState
,
1919 /* domain flags */ fParentsCurrentPowerFlags
,
1920 /* connection */ whichParent
,
1921 /* parent flags */ 0);
1924 // Parent is expecting an ACK from us. If we did not embark on a state
1925 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1926 // still required to issue an ACK to our parent.
1928 if (IOPMAckImplied
== result
)
1931 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1935 parent
->acknowledgePowerChange( whichParent
);
1940 // If the parent registers its power driver late, then this is the
1941 // first opportunity to tell our parent about our desire. Or if the
1942 // child's desire changed during a parent change notify.
1944 if ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
)
1946 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
1947 getName(), fParentsKnowState
);
1948 requestDomainPower( fDesiredPowerState
);
1952 // Drop the retain from notifyChild().
1953 if (whichParent
) whichParent
->release();
1956 //*********************************************************************************
1957 // [private] setParentInfo
1959 // Set our connection data for one specific parent, and then combine all the parent
1961 //*********************************************************************************
1963 void IOService::setParentInfo(
1964 IOPMPowerFlags newPowerFlags
,
1965 IOPowerConnection
* whichParent
,
1970 IOPowerConnection
* conn
;
1972 PM_ASSERT_IN_GATE();
1974 // set our connection data
1975 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
1976 whichParent
->setParentKnowsState(knowsState
);
1978 // recompute our parent info
1979 fParentsCurrentPowerFlags
= 0;
1980 fParentsKnowState
= true;
1982 iter
= getParentIterator(gIOPowerPlane
);
1985 while ( (next
= iter
->getNextObject()) )
1987 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
1989 fParentsKnowState
&= conn
->parentKnowsState();
1990 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
1997 //******************************************************************************
1998 // [private] trackSystemSleepPreventers
1999 //******************************************************************************
2001 void IOService::trackSystemSleepPreventers(
2002 IOPMPowerStateIndex oldPowerState
,
2003 IOPMPowerStateIndex newPowerState
,
2004 IOPMPowerChangeFlags changeFlags __unused
)
2006 IOPMPowerFlags oldCapability
, newCapability
;
2008 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2009 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2010 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2011 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2013 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)
2015 if (oldCapability
== newCapability
)
2018 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
)
2020 bool idleCancelAllowed
= getPMRootDomain()->updatePreventIdleSleepList(this,
2021 ((oldCapability
& kIOPMPreventIdleSleep
) == 0));
2022 if(!idleCancelAllowed
)
2023 PM_LOG2("Idle cancel was disallowed for %s\n", getName());
2024 #if SUPPORT_IDLE_CANCEL
2025 if (idleCancelAllowed
&& (oldCapability
& kIOPMPreventIdleSleep
) == 0)
2027 IOPMRequest
* cancelRequest
;
2029 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2032 submitPMRequest( cancelRequest
);
2039 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
)
2042 getPMRootDomain()->updatePreventSystemSleepList(this,
2043 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2047 //*********************************************************************************
2048 // [public] requestPowerDomainState
2050 // Called on a power parent when a child's power requirement changes.
2051 //*********************************************************************************
2053 IOReturn
IOService::requestPowerDomainState(
2054 IOPMPowerFlags childRequestPowerFlags
,
2055 IOPowerConnection
* childConnection
,
2056 unsigned long specification
)
2058 IOPMPowerStateIndex order
, powerState
;
2059 IOPMPowerFlags outputPowerFlags
;
2061 IOPMRequest
* subRequest
;
2062 bool adjustPower
= false;
2065 return IOPMNotYetInitialized
;
2067 if (gIOPMWorkLoop
->onThread() == false)
2069 PM_LOG("%s::requestPowerDomainState\n", getName());
2070 return kIOReturnSuccess
;
2073 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2075 if (!isChild(childConnection
, gIOPowerPlane
))
2076 return kIOReturnNotAttached
;
2078 if (!fControllingDriver
|| !fNumberOfPowerStates
)
2079 return kIOReturnNotReady
;
2081 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2084 // Remove flags from child request which we can't possibly supply
2085 childRequestPowerFlags
&= fMergedOutputPowerFlags
;
2087 // Merge in the power flags contributed by this power parent
2088 // at its current or impending power state.
2090 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2091 if (fMachineState
!= kIOPM_Finished
)
2093 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
)
2095 // Use the lower power state when dropping power.
2096 // Must be careful since a power drop can be cancelled
2097 // from the following states:
2098 // - kIOPM_OurChangeTellClientsPowerDown
2099 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2101 // The child must not wait for this parent to raise power
2102 // if the power drop was cancelled. The solution is to cancel
2103 // the power drop if possible, then schedule an adjustment to
2104 // re-evaluate the parent's power state.
2106 // Root domain is excluded to avoid idle sleep issues. And allow
2107 // root domain children to pop up when system is going to sleep.
2109 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2110 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
2112 fDoNotPowerDown
= true; // cancel power drop
2113 adjustPower
= true; // schedule an adjustment
2114 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2115 getName(), fMachineState
, child
->getName());
2119 // Beyond cancellation point, report the impending state.
2121 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2124 else if (IS_POWER_RISE
)
2126 // When raising power, must report the output power flags from
2127 // child's perspective. A child power request may arrive while
2128 // parent is transitioning upwards. If a request arrives after
2129 // setParentInfo() has already recorded the output power flags
2130 // for the next power state, then using the power supplied by
2131 // fCurrentPowerState is incorrect, and might cause the child
2132 // to wait when it should not.
2134 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2137 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2139 // Map child's requested power flags to one of our power state.
2141 for (order
= 0; order
< fNumberOfPowerStates
; order
++)
2143 powerState
= fPowerStates
[order
].stateOrderToIndex
;
2144 if ((fPowerStates
[powerState
].outputPowerFlags
& childRequestPowerFlags
)
2145 == childRequestPowerFlags
)
2148 if (order
>= fNumberOfPowerStates
)
2150 powerState
= kPowerStateZero
;
2153 // Conditions that warrants a power adjustment on this parent.
2154 // Adjust power will also propagate any changes to the child's
2155 // prevent idle/sleep flags towards the root domain.
2157 if (!childConnection
->childHasRequestedPower() ||
2158 (powerState
!= childConnection
->getDesiredDomainState()))
2161 #if ENABLE_DEBUG_LOGS
2164 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2165 getName(), child
->getName(),
2166 !childConnection
->childHasRequestedPower(),
2167 (uint32_t) childConnection
->getDesiredDomainState(),
2168 (uint32_t) powerState
);
2172 // Record the child's desires on the connection.
2173 childConnection
->setChildHasRequestedPower();
2174 childConnection
->setDesiredDomainState( powerState
);
2176 // Schedule a request to re-evaluate all children desires and
2177 // adjust power state. Submit a request if one wasn't pending,
2178 // or if the current request is part of a call tree.
2180 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2181 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest()))
2183 subRequest
= acquirePMRequest(
2184 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2187 submitPMRequest( subRequest
);
2188 fAdjustPowerScheduled
= true;
2192 return kIOReturnSuccess
;
2195 //*********************************************************************************
2196 // [public] temporaryPowerClampOn
2198 // A power domain wants to clamp its power on till it has children which
2199 // will thendetermine the power domain state.
2201 // We enter the highest state until addPowerChild is called.
2202 //*********************************************************************************
2204 IOReturn
IOService::temporaryPowerClampOn( void )
2206 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2209 //*********************************************************************************
2210 // [public] makeUsable
2212 // Some client of our device is asking that we become usable. Although
2213 // this has not come from a subclassed device object, treat it exactly
2214 // as if it had. In this way, subsequent requests for lower power from
2215 // a subclassed device object will pre-empt this request.
2217 // We treat this as a subclass object request to switch to the
2218 // highest power state.
2219 //*********************************************************************************
2221 IOReturn
IOService::makeUsable( void )
2223 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2224 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2227 //*********************************************************************************
2228 // [public] currentCapability
2229 //*********************************************************************************
2231 IOPMPowerFlags
IOService::currentCapability( void )
2234 return IOPMNotPowerManaged
;
2236 return fCurrentCapabilityFlags
;
2239 //*********************************************************************************
2240 // [public] changePowerStateTo
2242 // Called by our power-controlling driver to change power state. The new desired
2243 // power state is computed and compared against the current power state. If those
2244 // power states differ, then a power state change is initiated.
2245 //*********************************************************************************
2247 IOReturn
IOService::changePowerStateTo( unsigned long ordinal
)
2249 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2250 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2253 //*********************************************************************************
2254 // [protected] changePowerStateToPriv
2256 // Called by our driver subclass to change power state. The new desired power
2257 // state is computed and compared against the current power state. If those
2258 // power states differ, then a power state change is initiated.
2259 //*********************************************************************************
2261 IOReturn
IOService::changePowerStateToPriv( unsigned long ordinal
)
2263 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2264 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2267 //*********************************************************************************
2268 // [public] changePowerStateWithOverrideTo
2270 // Called by our driver subclass to change power state. The new desired power
2271 // state is computed and compared against the current power state. If those
2272 // power states differ, then a power state change is initiated.
2273 // Override enforced - Children and Driver desires are ignored.
2274 //*********************************************************************************
2276 IOReturn
IOService::changePowerStateWithOverrideTo( IOPMPowerStateIndex ordinal
,
2277 IOPMRequestTag tag
)
2279 IOPMRequest
* request
;
2282 return kIOPMNotYetInitialized
;
2284 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2286 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2288 return kIOReturnNoMemory
;
2290 gIOPMPowerClientDevice
->retain();
2291 request
->fRequestTag
= tag
;
2292 request
->fArg0
= (void *) ordinal
;
2293 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2297 request
->installCompletionAction( action
, target
, param
);
2300 // Prevent needless downwards power transitions by clamping power
2301 // until the scheduled request is executed.
2303 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
))
2305 fTempClampPowerState
= StateMax(fTempClampPowerState
, ordinal
);
2307 fOverrideMaxPowerState
= ordinal
;
2308 request
->fArg2
= (void *) (uintptr_t) true;
2311 submitPMRequest( request
);
2315 //*********************************************************************************
2316 // [public] changePowerStateForRootDomain
2318 // Adjust the root domain's power desire on the target
2319 //*********************************************************************************
2321 IOReturn
IOService::changePowerStateForRootDomain( IOPMPowerStateIndex ordinal
)
2323 OUR_PMLog(kPMLogChangeStateForRootDomain
, ordinal
, 0);
2324 return requestPowerState( gIOPMPowerClientRootDomain
, ordinal
);
2327 //*********************************************************************************
2328 // [private] requestPowerState
2329 //*********************************************************************************
2331 IOReturn
IOService::requestPowerState(
2332 const OSSymbol
* client
,
2335 IOPMRequest
* request
;
2338 return kIOReturnBadArgument
;
2340 return kIOPMNotYetInitialized
;
2342 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2344 return kIOReturnNoMemory
;
2347 request
->fArg0
= (void *)(uintptr_t) state
;
2348 request
->fArg1
= (void *) client
;
2352 request
->installCompletionAction( action
, target
, param
);
2355 // Prevent needless downwards power transitions by clamping power
2356 // until the scheduled request is executed.
2358 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
))
2360 fTempClampPowerState
= StateMax(fTempClampPowerState
, state
);
2362 request
->fArg2
= (void *) (uintptr_t) true;
2365 submitPMRequest( request
);
2369 //*********************************************************************************
2370 // [private] handleRequestPowerState
2371 //*********************************************************************************
2373 void IOService::handleRequestPowerState( IOPMRequest
* request
)
2375 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2376 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2378 PM_ASSERT_IN_GATE();
2381 assert(fTempClampCount
!= 0);
2382 if (fTempClampCount
) fTempClampCount
--;
2383 if (!fTempClampCount
) fTempClampPowerState
= kPowerStateZero
;
2386 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
))
2387 state
= fHighestPowerState
;
2389 // The power suppression due to changePowerStateWithOverrideTo() expires
2390 // upon the next "device" power request - changePowerStateToPriv().
2392 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2393 (client
== gIOPMPowerClientDevice
))
2394 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2396 if ((state
== kPowerStateZero
) &&
2397 (client
!= gIOPMPowerClientDevice
) &&
2398 (client
!= gIOPMPowerClientDriver
) &&
2399 (client
!= gIOPMPowerClientChildProxy
))
2400 removePowerClient(client
);
2402 updatePowerClient(client
, state
);
2408 //*********************************************************************************
2409 // [private] Helper functions to update/remove power clients.
2410 //*********************************************************************************
2412 void IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2414 IOPMPowerStateIndex oldPowerState
= kPowerStateZero
;
2417 fPowerClients
= OSDictionary::withCapacity(4);
2418 if (fPowerClients
&& client
)
2420 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2423 oldPowerState
= num
->unsigned32BitValue();
2424 num
->setValue(powerState
);
2428 num
= OSNumber::withNumber(powerState
, 32);
2431 fPowerClients
->setObject(client
, num
);
2436 PM_ACTION_3(actionUpdatePowerClient
, client
, oldPowerState
, powerState
);
2440 void IOService::removePowerClient( const OSSymbol
* client
)
2442 if (fPowerClients
&& client
)
2443 fPowerClients
->removeObject(client
);
2446 uint32_t IOService::getPowerStateForClient( const OSSymbol
* client
)
2448 uint32_t powerState
= kPowerStateZero
;
2450 if (fPowerClients
&& client
)
2452 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2453 if (num
) powerState
= num
->unsigned32BitValue();
2458 //*********************************************************************************
2459 // [protected] powerOverrideOnPriv
2460 //*********************************************************************************
2462 IOReturn
IOService::powerOverrideOnPriv( void )
2464 IOPMRequest
* request
;
2467 return IOPMNotYetInitialized
;
2469 if (gIOPMWorkLoop
->inGate())
2471 fDeviceOverrideEnabled
= true;
2475 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2477 return kIOReturnNoMemory
;
2479 submitPMRequest( request
);
2483 //*********************************************************************************
2484 // [protected] powerOverrideOffPriv
2485 //*********************************************************************************
2487 IOReturn
IOService::powerOverrideOffPriv( void )
2489 IOPMRequest
* request
;
2492 return IOPMNotYetInitialized
;
2494 if (gIOPMWorkLoop
->inGate())
2496 fDeviceOverrideEnabled
= false;
2500 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2502 return kIOReturnNoMemory
;
2504 submitPMRequest( request
);
2508 //*********************************************************************************
2509 // [private] handlePowerOverrideChanged
2510 //*********************************************************************************
2512 void IOService::handlePowerOverrideChanged( IOPMRequest
* request
)
2514 PM_ASSERT_IN_GATE();
2515 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
)
2517 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2518 fDeviceOverrideEnabled
= true;
2522 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2523 fDeviceOverrideEnabled
= false;
2529 //*********************************************************************************
2530 // [private] computeDesiredState
2531 //*********************************************************************************
2533 void IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2537 IOPowerConnection
* connection
;
2538 uint32_t desiredState
= kPowerStateZero
;
2539 uint32_t newPowerState
= kPowerStateZero
;
2540 bool hasChildren
= false;
2542 // Desired power state is always 0 without a controlling driver.
2544 if (!fNumberOfPowerStates
)
2546 fDesiredPowerState
= kPowerStateZero
;
2550 // Examine the children's desired power state.
2552 iter
= getChildIterator(gIOPowerPlane
);
2555 while ((next
= iter
->getNextObject()))
2557 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
2559 if (connection
->getReadyFlag() == false)
2561 PM_LOG3("[%s] %s: connection not ready\n",
2562 getName(), __FUNCTION__
);
2565 if (connection
->childHasRequestedPower())
2567 desiredState
= StateMax(connection
->getDesiredDomainState(), desiredState
);
2573 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2575 removePowerClient(gIOPMPowerClientChildren
);
2577 // Iterate through all power clients to determine the min power state.
2579 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2582 const OSSymbol
* client
;
2583 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
2585 // Ignore child and driver when override is in effect.
2586 if ((fDeviceOverrideEnabled
||
2587 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2588 ((client
== gIOPMPowerClientChildren
) ||
2589 (client
== gIOPMPowerClientDriver
)))
2592 // Ignore child proxy when children are present.
2593 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
))
2596 // Advisory tickles are irrelevant unless system is in full wake
2597 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2598 !gIOPMAdvisoryTickleEnabled
)
2601 desiredState
= getPowerStateForClient(client
);
2602 assert(desiredState
< fNumberOfPowerStates
);
2604 desiredState
, client
->getCStringNoCopy());
2606 newPowerState
= StateMax(newPowerState
, desiredState
);
2608 if (client
== gIOPMPowerClientDevice
)
2609 fDeviceDesire
= desiredState
;
2614 // Factor in the temporary power desires.
2616 newPowerState
= StateMax(newPowerState
, localClamp
);
2617 newPowerState
= StateMax(newPowerState
, fTempClampPowerState
);
2619 // Limit check against max power override.
2621 newPowerState
= StateMin(newPowerState
, fOverrideMaxPowerState
);
2623 // Limit check against number of power states.
2625 if (newPowerState
>= fNumberOfPowerStates
)
2626 newPowerState
= fHighestPowerState
;
2628 fDesiredPowerState
= newPowerState
;
2630 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2631 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2632 (uint32_t) fCurrentPowerState
, newPowerState
);
2636 // Restart idle timer if possible when device desire has increased.
2637 // Or if an advisory desire exists.
2639 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
2644 // Invalidate cached tickle power state when desires change, and not
2645 // due to a tickle request. In case the driver has requested a lower
2646 // power state, but the tickle is caching a higher power state which
2647 // will drop future tickles until the cached value is lowered or in-
2648 // validated. The invalidation must occur before the power transition
2649 // to avoid dropping a necessary tickle.
2651 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2652 (fActivityTicklePowerState
!= kInvalidTicklePowerState
))
2654 IOLockLock(fActivityLock
);
2655 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2656 IOLockUnlock(fActivityLock
);
2661 //*********************************************************************************
2662 // [public] currentPowerConsumption
2664 //*********************************************************************************
2666 unsigned long IOService::currentPowerConsumption( void )
2669 return kIOPMUnknown
;
2671 return fCurrentPowerConsumption
;
2674 //*********************************************************************************
2675 // [deprecated] getPMworkloop
2676 //*********************************************************************************
2678 IOWorkLoop
* IOService::getPMworkloop( void )
2680 return gIOPMWorkLoop
;
2685 //*********************************************************************************
2686 // Power Parent/Children Applier
2687 //*********************************************************************************
2690 applyToPowerChildren(
2691 IOService
* service
,
2692 IOServiceApplierFunction applier
,
2694 IOOptionBits options
)
2696 PM_ASSERT_IN_GATE();
2698 IORegistryEntry
* entry
;
2699 IORegistryIterator
* iter
;
2700 IOPowerConnection
* connection
;
2703 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2706 while ((entry
= iter
->getNextObject()))
2708 // Get child of IOPowerConnection objects
2709 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2711 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2714 (*applier
)(child
, context
);
2725 IOService
* service
,
2726 IOServiceApplierFunction applier
,
2728 IOOptionBits options
)
2730 PM_ASSERT_IN_GATE();
2732 IORegistryEntry
* entry
;
2733 IORegistryIterator
* iter
;
2734 IOPowerConnection
* connection
;
2737 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2738 options
| kIORegistryIterateParents
);
2741 while ((entry
= iter
->getNextObject()))
2743 // Get child of IOPowerConnection objects
2744 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2746 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2749 (*applier
)(parent
, context
);
2758 #endif /* NOT_YET */
2761 // MARK: Activity Tickle & Idle Timer
2763 void IOService::setAdvisoryTickleEnable( bool enable
)
2765 gIOPMAdvisoryTickleEnabled
= enable
;
2768 //*********************************************************************************
2769 // [public] activityTickle
2771 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2772 // flag to be set, and the device state checked. If the device has been
2773 // powered down, it is powered up again.
2774 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2775 // should be intercepted by a subclass.
2776 //*********************************************************************************
2778 bool IOService::activityTickle( unsigned long type
, unsigned long stateNumber
)
2780 IOPMRequest
* request
;
2781 bool noPowerChange
= true;
2782 uint32_t tickleFlags
;
2785 return true; // no power change
2787 if ((type
== kIOPMSuperclassPolicy1
) && StateOrder(stateNumber
))
2789 IOLockLock(fActivityLock
);
2791 // Record device activity for the idle timer handler.
2793 fDeviceWasActive
= true;
2794 fActivityTickleCount
++;
2795 clock_get_uptime(&fDeviceActiveTimestamp
);
2797 PM_ACTION_0(actionActivityTickle
);
2799 // Record the last tickle power state.
2800 // This helps to filter out redundant tickles as
2801 // this function may be called from the data path.
2803 if ((fActivityTicklePowerState
== kInvalidTicklePowerState
)
2804 || StateOrder(fActivityTicklePowerState
) < StateOrder(stateNumber
))
2806 fActivityTicklePowerState
= stateNumber
;
2807 noPowerChange
= false;
2809 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2810 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2813 request
->fArg0
= (void *) stateNumber
;
2814 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2815 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2816 submitPMRequest(request
);
2820 IOLockUnlock(fActivityLock
);
2823 else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2824 ((stateNumber
= fDeviceUsablePowerState
) != kPowerStateZero
))
2826 IOLockLock(fActivityLock
);
2828 fAdvisoryTickled
= true;
2830 if (fAdvisoryTicklePowerState
!= stateNumber
)
2832 fAdvisoryTicklePowerState
= stateNumber
;
2833 noPowerChange
= false;
2835 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2836 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2839 request
->fArg0
= (void *) stateNumber
;
2840 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2841 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2842 submitPMRequest(request
);
2846 IOLockUnlock(fActivityLock
);
2849 // Returns false if the activityTickle might cause a transition to a
2850 // higher powered state, true otherwise.
2852 return noPowerChange
;
2855 //*********************************************************************************
2856 // [private] handleActivityTickle
2857 //*********************************************************************************
2859 void IOService::handleActivityTickle( IOPMRequest
* request
)
2861 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2862 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
2863 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
2864 bool adjustPower
= false;
2866 PM_ASSERT_IN_GATE();
2867 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
))
2869 // Drivers that don't want power restored on wake will drop any
2870 // tickles that pre-dates the current system wake. The model is
2871 // that each wake is a fresh start, with power state depressed
2872 // until a new tickle or an explicit power up request from the
2873 // driver. It is possible for the PM work loop to enter the
2874 // system sleep path with tickle requests queued.
2879 if (tickleFlags
& kTickleTypeActivity
)
2881 IOPMPowerStateIndex deviceDesireOrder
= StateOrder(fDeviceDesire
);
2883 if (tickleFlags
& kTickleTypePowerRise
)
2885 if ((StateOrder(ticklePowerState
) > deviceDesireOrder
) &&
2886 (ticklePowerState
< fNumberOfPowerStates
))
2888 fIdleTimerMinPowerState
= ticklePowerState
;
2889 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2893 else if (deviceDesireOrder
> StateOrder(fIdleTimerMinPowerState
))
2895 // Power drop due to idle timer expiration.
2896 // Do not allow idle timer to reduce power below tickle power.
2897 // This prevents the idle timer from decreasing the device desire
2898 // to zero and cancelling the effect of a pre-sleep tickle when
2899 // system wakes up to doze state, while the device is unable to
2900 // raise its power state to satisfy the tickle.
2902 deviceDesireOrder
--;
2903 if (deviceDesireOrder
< fNumberOfPowerStates
)
2905 ticklePowerState
= fPowerStates
[deviceDesireOrder
].stateOrderToIndex
;
2906 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2911 else // advisory tickle
2913 if (tickleFlags
& kTickleTypePowerRise
)
2915 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
2916 (ticklePowerState
< fNumberOfPowerStates
))
2918 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
2919 fHasAdvisoryDesire
= true;
2920 fAdvisoryTickleUsed
= true;
2925 IOLockLock(fActivityLock
);
2926 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
2927 IOLockUnlock(fActivityLock
);
2930 else if (fHasAdvisoryDesire
)
2932 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
2933 fHasAdvisoryDesire
= false;
2944 //******************************************************************************
2945 // [public] setIdleTimerPeriod
2947 // A subclass policy-maker is using our standard idleness detection service.
2948 // Start the idle timer. Period is in seconds.
2949 //******************************************************************************
2951 IOReturn
IOService::setIdleTimerPeriod( unsigned long period
)
2954 return IOPMNotYetInitialized
;
2956 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
2958 IOPMRequest
* request
=
2959 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
2961 return kIOReturnNoMemory
;
2963 request
->fArg0
= (void *) period
;
2964 submitPMRequest( request
);
2966 return kIOReturnSuccess
;
2969 IOReturn
IOService::setIgnoreIdleTimer( bool ignore
)
2972 return IOPMNotYetInitialized
;
2974 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
2976 IOPMRequest
* request
=
2977 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
2979 return kIOReturnNoMemory
;
2981 request
->fArg0
= (void *) ignore
;
2982 submitPMRequest( request
);
2984 return kIOReturnSuccess
;
2987 //******************************************************************************
2988 // [public] nextIdleTimeout
2990 // Returns how many "seconds from now" the device should idle into its
2991 // next lowest power state.
2992 //******************************************************************************
2994 SInt32
IOService::nextIdleTimeout(
2995 AbsoluteTime currentTime
,
2996 AbsoluteTime lastActivity
,
2997 unsigned int powerState
)
3004 // Calculate time difference using funky macro from clock.h.
3005 delta
= currentTime
;
3006 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
3008 // Figure it in seconds.
3009 absolutetime_to_nanoseconds(delta
, &delta_ns
);
3010 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
3012 // Be paranoid about delta somehow exceeding timer period.
3013 if (delta_secs
< (int) fIdleTimerPeriod
)
3014 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3016 delay_secs
= (int) fIdleTimerPeriod
;
3018 return (SInt32
)delay_secs
;
3021 //*********************************************************************************
3022 // [public] start_PM_idle_timer
3023 //*********************************************************************************
3025 void IOService::start_PM_idle_timer( void )
3027 static const int maxTimeout
= 100000;
3028 static const int minTimeout
= 1;
3029 AbsoluteTime uptime
, deadline
;
3033 if (!initialized
|| !fIdleTimerPeriod
)
3036 IOLockLock(fActivityLock
);
3038 clock_get_uptime(&uptime
);
3040 // Subclasses may modify idle sleep algorithm
3041 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3043 // Check for out-of range responses
3044 if (idle_in
> maxTimeout
)
3046 // use standard implementation
3047 idle_in
= IOService::nextIdleTimeout(uptime
,
3048 fDeviceActiveTimestamp
,
3049 fCurrentPowerState
);
3050 } else if (idle_in
< minTimeout
) {
3051 idle_in
= fIdleTimerPeriod
;
3054 IOLockUnlock(fActivityLock
);
3057 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3058 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3059 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3060 if (pending
) release();
3063 //*********************************************************************************
3064 // [private] restartIdleTimer
3065 //*********************************************************************************
3067 void IOService::restartIdleTimer( void )
3069 if (fDeviceDesire
!= kPowerStateZero
)
3071 fIdleTimerStopped
= false;
3072 fActivityTickleCount
= 0;
3073 clock_get_uptime(&fIdleTimerStartTime
);
3074 start_PM_idle_timer();
3076 else if (fHasAdvisoryDesire
)
3078 fIdleTimerStopped
= false;
3079 start_PM_idle_timer();
3083 fIdleTimerStopped
= true;
3087 //*********************************************************************************
3088 // idle_timer_expired
3089 //*********************************************************************************
3093 thread_call_param_t arg0
, thread_call_param_t arg1
)
3095 IOService
* me
= (IOService
*) arg0
;
3098 gIOPMWorkLoop
->runAction(
3099 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3100 &IOService::idleTimerExpired
),
3106 //*********************************************************************************
3107 // [private] idleTimerExpired
3109 // The idle timer has expired. If there has been activity since the last
3110 // expiration, just restart the timer and return. If there has not been
3111 // activity, switch to the next lower power state and restart the timer.
3112 //*********************************************************************************
3114 void IOService::idleTimerExpired( void )
3116 IOPMRequest
* request
;
3117 bool restartTimer
= true;
3118 uint32_t tickleFlags
;
3120 if ( !initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3121 fLockedFlags
.PMStop
)
3124 IOLockLock(fActivityLock
);
3126 // Check for device activity (tickles) over last timer period.
3128 if (fDeviceWasActive
)
3130 // Device was active - do not drop power, restart timer.
3131 fDeviceWasActive
= false;
3133 else if (!fIdleTimerIgnored
)
3135 // No device activity - drop power state by one level.
3136 // Decrement the cached tickle power state when possible.
3137 // This value may be kInvalidTicklePowerState before activityTickle()
3138 // is called, but the power drop request must be issued regardless.
3140 if ((fActivityTicklePowerState
!= kInvalidTicklePowerState
) &&
3141 (fActivityTicklePowerState
!= kPowerStateZero
))
3142 fActivityTicklePowerState
--;
3144 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3145 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3148 request
->fArg0
= (void *) kPowerStateZero
; // irrelevant
3149 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3150 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3151 submitPMRequest( request
);
3153 // Do not restart timer until after the tickle request has been
3156 restartTimer
= false;
3160 if (fAdvisoryTickled
)
3162 fAdvisoryTickled
= false;
3164 else if (fHasAdvisoryDesire
)
3166 // Want new tickles to turn into pm request after we drop the lock
3167 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3169 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3170 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3173 request
->fArg0
= (void *) kPowerStateZero
; // irrelevant
3174 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3175 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3176 submitPMRequest( request
);
3178 // Do not restart timer until after the tickle request has been
3181 restartTimer
= false;
3185 IOLockUnlock(fActivityLock
);
3188 start_PM_idle_timer();
3192 //*********************************************************************************
3193 // [deprecated] PM_idle_timer_expiration
3194 //*********************************************************************************
3196 void IOService::PM_idle_timer_expiration( void )
3200 //*********************************************************************************
3201 // [deprecated] command_received
3202 //*********************************************************************************
3204 void IOService::command_received( void *statePtr
, void *, void * , void * )
3207 #endif /* !__LP64__ */
3209 //*********************************************************************************
3210 // [public] setAggressiveness
3212 // Pass on the input parameters to all power domain children. All those which are
3213 // power domains will pass it on to their children, etc.
3214 //*********************************************************************************
3216 IOReturn
IOService::setAggressiveness( unsigned long type
, unsigned long newLevel
)
3218 return kIOReturnSuccess
;
3221 //*********************************************************************************
3222 // [public] getAggressiveness
3224 // Called by the user client.
3225 //*********************************************************************************
3227 IOReturn
IOService::getAggressiveness( unsigned long type
, unsigned long * currentLevel
)
3229 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3232 return kIOReturnNotReady
;
3234 return rootDomain
->getAggressiveness( type
, currentLevel
);
3237 //*********************************************************************************
3238 // [public] getPowerState
3240 //*********************************************************************************
3242 UInt32
IOService::getPowerState( void )
3245 return kPowerStateZero
;
3247 return fCurrentPowerState
;
3251 //*********************************************************************************
3252 // [deprecated] systemWake
3254 // Pass this to all power domain children. All those which are
3255 // power domains will pass it on to their children, etc.
3256 //*********************************************************************************
3258 IOReturn
IOService::systemWake( void )
3262 IOPowerConnection
* connection
;
3263 IOService
* theChild
;
3265 iter
= getChildIterator(gIOPowerPlane
);
3268 while ( (next
= iter
->getNextObject()) )
3270 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
3272 if (connection
->getReadyFlag() == false)
3274 PM_LOG3("[%s] %s: connection not ready\n",
3275 getName(), __FUNCTION__
);
3279 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3282 theChild
->systemWake();
3283 theChild
->release();
3290 if ( fControllingDriver
!= NULL
)
3292 if ( fControllingDriver
->didYouWakeSystem() )
3301 //*********************************************************************************
3302 // [deprecated] temperatureCriticalForZone
3303 //*********************************************************************************
3305 IOReturn
IOService::temperatureCriticalForZone( IOService
* whichZone
)
3307 IOService
* theParent
;
3310 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3312 if ( inPlane(gIOPowerPlane
) && !IS_PM_ROOT
)
3314 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3317 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3321 theParent
->temperatureCriticalForZone(whichZone
);
3322 theParent
->release();
3328 #endif /* !__LP64__ */
3331 // MARK: Power Change (Common)
3333 //*********************************************************************************
3334 // [private] startPowerChange
3336 // All power state changes starts here.
3337 //*********************************************************************************
3339 IOReturn
IOService::startPowerChange(
3340 IOPMPowerChangeFlags changeFlags
,
3341 IOPMPowerStateIndex powerState
,
3342 IOPMPowerFlags domainFlags
,
3343 IOPowerConnection
* parentConnection
,
3344 IOPMPowerFlags parentFlags
)
3346 PM_ASSERT_IN_GATE();
3347 assert( fMachineState
== kIOPM_Finished
);
3348 assert( powerState
< fNumberOfPowerStates
);
3350 if (powerState
>= fNumberOfPowerStates
)
3351 return IOPMAckImplied
;
3353 fIsPreChange
= true;
3354 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3356 if (changeFlags
& kIOPMExpireIdleTimer
)
3358 // Root domain requested removal of tickle influence
3359 if (StateOrder(fDeviceDesire
) > StateOrder(powerState
))
3361 // Reset device desire down to the clamped power state
3362 updatePowerClient(gIOPMPowerClientDevice
, powerState
);
3363 computeDesiredState(kPowerStateZero
, true);
3365 // Invalidate tickle cache so the next tickle will issue a request
3366 IOLockLock(fActivityLock
);
3367 fDeviceWasActive
= false;
3368 fActivityTicklePowerState
= kInvalidTicklePowerState
;
3369 IOLockUnlock(fActivityLock
);
3371 fIdleTimerMinPowerState
= kPowerStateZero
;
3375 // Root domain's override handler may cancel the power change by
3376 // setting the kIOPMNotDone flag.
3378 if (changeFlags
& kIOPMNotDone
)
3379 return IOPMAckImplied
;
3381 // Forks to either Driver or Parent initiated power change paths.
3383 fHeadNoteChangeFlags
= changeFlags
;
3384 fHeadNotePowerState
= powerState
;
3385 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
3386 fHeadNoteParentConnection
= NULL
;
3388 if (changeFlags
& kIOPMSelfInitiated
)
3390 if (changeFlags
& kIOPMSynchronize
)
3398 assert(changeFlags
& kIOPMParentInitiated
);
3399 fHeadNoteDomainFlags
= domainFlags
;
3400 fHeadNoteParentFlags
= parentFlags
;
3401 fHeadNoteParentConnection
= parentConnection
;
3402 return ParentChangeStart();
3406 //*********************************************************************************
3407 // [private] notifyInterestedDrivers
3408 //*********************************************************************************
3410 bool IOService::notifyInterestedDrivers( void )
3412 IOPMinformee
* informee
;
3413 IOPMinformeeList
* list
= fInterestedDrivers
;
3414 DriverCallParam
* param
;
3417 PM_ASSERT_IN_GATE();
3418 assert( fDriverCallParamCount
== 0 );
3419 assert( fHeadNotePendingAcks
== 0 );
3421 fHeadNotePendingAcks
= 0;
3423 count
= list
->numberOfItems();
3425 goto done
; // no interested drivers
3427 // Allocate an array of interested drivers and their return values
3428 // for the callout thread. Everything else is still "owned" by the
3429 // PM work loop, which can run to process acknowledgePowerChange()
3432 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3433 if (count
> fDriverCallParamSlots
)
3435 if (fDriverCallParamSlots
)
3437 assert(fDriverCallParamPtr
);
3438 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3439 fDriverCallParamPtr
= 0;
3440 fDriverCallParamSlots
= 0;
3443 param
= IONew(DriverCallParam
, count
);
3445 goto done
; // no memory
3447 fDriverCallParamPtr
= (void *) param
;
3448 fDriverCallParamSlots
= count
;
3451 informee
= list
->firstInList();
3453 for (IOItemCount i
= 0; i
< count
; i
++)
3455 informee
->timer
= -1;
3456 param
[i
].Target
= informee
;
3458 informee
= list
->nextInList( informee
);
3461 fDriverCallParamCount
= count
;
3462 fHeadNotePendingAcks
= count
;
3464 // Block state machine and wait for callout completion.
3465 assert(!fDriverCallBusy
);
3466 fDriverCallBusy
= true;
3467 thread_call_enter( fDriverCallEntry
);
3471 // Return false if there are no interested drivers or could not schedule
3472 // callout thread due to error.
3476 //*********************************************************************************
3477 // [private] notifyInterestedDriversDone
3478 //*********************************************************************************
3480 void IOService::notifyInterestedDriversDone( void )
3482 IOPMinformee
* informee
;
3484 DriverCallParam
* param
;
3487 PM_ASSERT_IN_GATE();
3488 assert( fDriverCallBusy
== false );
3489 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3491 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3492 count
= fDriverCallParamCount
;
3496 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3498 informee
= (IOPMinformee
*) param
->Target
;
3499 result
= param
->Result
;
3501 if ((result
== IOPMAckImplied
) || (result
< 0))
3503 // Interested driver return IOPMAckImplied.
3504 // If informee timer is zero, it must have de-registered
3505 // interest during the thread callout. That also drops
3506 // the pending ack count.
3508 if (fHeadNotePendingAcks
&& informee
->timer
)
3509 fHeadNotePendingAcks
--;
3511 informee
->timer
= 0;
3513 else if (informee
->timer
)
3515 assert(informee
->timer
== -1);
3517 // Driver has not acked, and has returned a positive result.
3518 // Enforce a minimum permissible timeout value.
3519 // Make the min value large enough so timeout is less likely
3520 // to occur if a driver misinterpreted that the return value
3521 // should be in microsecond units. And make it large enough
3522 // to be noticeable if a driver neglects to ack.
3524 if (result
< kMinAckTimeoutTicks
)
3525 result
= kMinAckTimeoutTicks
;
3527 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3529 // else, child has already acked or driver has removed interest,
3530 // and head_note_pendingAcks decremented.
3531 // informee may have been removed from the interested drivers list,
3532 // thus the informee must be retained across the callout.
3534 informee
->release();
3537 fDriverCallParamCount
= 0;
3539 if ( fHeadNotePendingAcks
)
3541 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3546 MS_POP(); // pop the machine state passed to notifyAll()
3548 // If interest acks are outstanding, block the state machine until
3549 // fHeadNotePendingAcks drops to zero before notifying root domain.
3550 // Otherwise notify root domain directly.
3552 if (!fHeadNotePendingAcks
)
3558 MS_PUSH(fMachineState
);
3559 fMachineState
= kIOPM_NotifyChildrenStart
;
3563 //*********************************************************************************
3564 // [private] notifyRootDomain
3565 //*********************************************************************************
3567 void IOService::notifyRootDomain( void )
3569 assert( fDriverCallBusy
== false );
3571 // Only for root domain in the will-change phase
3572 if (!IS_ROOT_DOMAIN
|| (fMachineState
!= kIOPM_OurChangeSetPowerState
))
3578 MS_PUSH(fMachineState
); // push notifyAll() machine state
3579 fMachineState
= kIOPM_DriverThreadCallDone
;
3581 // Call IOPMrootDomain::willNotifyPowerChildren() on a thread call
3582 // to avoid a deadlock.
3583 fDriverCallReason
= kRootDomainInformPreChange
;
3584 fDriverCallBusy
= true;
3585 thread_call_enter( fDriverCallEntry
);
3588 void IOService::notifyRootDomainDone( void )
3590 assert( fDriverCallBusy
== false );
3591 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3593 MS_POP(); // pop notifyAll() machine state
3597 //*********************************************************************************
3598 // [private] notifyChildren
3599 //*********************************************************************************
3601 void IOService::notifyChildren( void )
3605 IOPowerConnection
* connection
;
3606 OSArray
* children
= 0;
3607 IOPMrootDomain
* rootDomain
;
3608 bool delayNotify
= false;
3610 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3611 (IS_POWER_DROP
== fIsPreChange
) &&
3612 ((rootDomain
= getPMRootDomain()) == this))
3614 rootDomain
->tracePoint( IS_POWER_DROP
?
3615 kIOPMTracePointSleepPowerPlaneDrivers
:
3616 kIOPMTracePointWakePowerPlaneDrivers
);
3619 if (fStrictTreeOrder
)
3620 children
= OSArray::withCapacity(8);
3622 // Sum child power consumption in notifyChild()
3623 fHeadNotePowerArrayEntry
->staticPower
= 0;
3625 iter
= getChildIterator(gIOPowerPlane
);
3628 while ((next
= iter
->getNextObject()))
3630 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3632 if (connection
->getReadyFlag() == false)
3634 PM_LOG3("[%s] %s: connection not ready\n",
3635 getName(), __FUNCTION__
);
3639 // Mechanism to postpone the did-change notification to
3640 // certain power children to order those children last.
3641 // Cannot be used together with strict tree ordering.
3643 if (!fIsPreChange
&&
3644 connection
->delayChildNotification
&&
3645 getPMRootDomain()->shouldDelayChildNotification(this))
3649 children
= OSArray::withCapacity(8);
3655 children
->setObject( connection
);
3660 if (!delayNotify
&& children
)
3661 children
->setObject( connection
);
3663 notifyChild( connection
);
3669 if (children
&& (children
->getCount() == 0))
3671 children
->release();
3676 assert(fNotifyChildArray
== 0);
3677 fNotifyChildArray
= children
;
3678 MS_PUSH(fMachineState
);
3682 // Block until all non-delayed children have acked their
3683 // notification. Then notify the remaining delayed child
3684 // in the array. This is used to hold off graphics child
3685 // notification while the rest of the system powers up.
3686 // If a hid tickle arrives during this time, the delayed
3687 // children are immediately notified and root domain will
3688 // not clamp power for dark wake.
3690 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3691 PM_LOG2("%s: %d children in delayed array\n",
3692 getName(), children
->getCount());
3696 // Child array created to support strict notification order.
3697 // Notify children in the array one at a time.
3699 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3704 //*********************************************************************************
3705 // [private] notifyChildrenOrdered
3706 //*********************************************************************************
3708 void IOService::notifyChildrenOrdered( void )
3710 PM_ASSERT_IN_GATE();
3711 assert(fNotifyChildArray
);
3712 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3714 // Notify one child, wait for it to ack, then repeat for next child.
3715 // This is a workaround for some drivers with multiple instances at
3716 // the same branch in the power tree, but the driver is slow to power
3717 // up unless the tree ordering is observed. Problem observed only on
3718 // system wake, not on system sleep.
3720 // We have the ability to power off in reverse child index order.
3721 // That works nicely on some machines, but not on all HW configs.
3723 if (fNotifyChildArray
->getCount())
3725 IOPowerConnection
* connection
;
3726 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3727 notifyChild( connection
);
3728 fNotifyChildArray
->removeObject(0);
3732 fNotifyChildArray
->release();
3733 fNotifyChildArray
= 0;
3735 MS_POP(); // pushed by notifyChildren()
3739 //*********************************************************************************
3740 // [private] notifyChildrenDelayed
3741 //*********************************************************************************
3743 void IOService::notifyChildrenDelayed( void )
3745 IOPowerConnection
* connection
;
3747 PM_ASSERT_IN_GATE();
3748 assert(fNotifyChildArray
);
3749 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3751 // Wait after all non-delayed children and interested drivers have ack'ed,
3752 // then notify all delayed children. If notify delay is canceled, child
3753 // acks may be outstanding with PM blocked on fHeadNotePendingAcks != 0.
3754 // But the handling for either case is identical.
3756 for (int i
= 0; ; i
++)
3758 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3762 notifyChild( connection
);
3765 PM_LOG2("%s: notified delayed children\n", getName());
3766 fNotifyChildArray
->release();
3767 fNotifyChildArray
= 0;
3769 MS_POP(); // pushed by notifyChildren()
3772 //*********************************************************************************
3773 // [private] notifyAll
3774 //*********************************************************************************
3776 IOReturn
IOService::notifyAll( uint32_t nextMS
)
3778 // Save the machine state to be restored by notifyInterestedDriversDone()
3780 PM_ASSERT_IN_GATE();
3782 fMachineState
= kIOPM_DriverThreadCallDone
;
3783 fDriverCallReason
= fIsPreChange
?
3784 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3786 if (!notifyInterestedDrivers())
3787 notifyInterestedDriversDone();
3789 return IOPMWillAckLater
;
3792 //*********************************************************************************
3793 // [private, static] pmDriverCallout
3795 // Thread call context
3796 //*********************************************************************************
3798 IOReturn
IOService::actionDriverCalloutDone(
3800 void * arg0
, void * arg1
,
3801 void * arg2
, void * arg3
)
3803 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3805 assert( fDriverCallBusy
);
3806 fDriverCallBusy
= false;
3808 assert(gIOPMWorkQueue
);
3809 gIOPMWorkQueue
->signalWorkAvailable();
3811 return kIOReturnSuccess
;
3814 void IOService::pmDriverCallout( IOService
* from
)
3817 switch (from
->fDriverCallReason
)
3819 case kDriverCallSetPowerState
:
3820 from
->driverSetPowerState();
3823 case kDriverCallInformPreChange
:
3824 case kDriverCallInformPostChange
:
3825 from
->driverInformPowerChange();
3828 case kRootDomainInformPreChange
:
3829 getPMRootDomain()->willNotifyPowerChildren(from
->fHeadNotePowerState
);
3833 panic("IOService::pmDriverCallout bad machine state %x",
3834 from
->fDriverCallReason
);
3837 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3839 /* arg0 */ (void *) from
->pwrMgt
);
3842 //*********************************************************************************
3843 // [private] driverSetPowerState
3845 // Thread call context
3846 //*********************************************************************************
3848 void IOService::driverSetPowerState( void )
3850 IOPMPowerStateIndex powerState
;
3851 DriverCallParam
* param
;
3852 IOPMDriverCallEntry callEntry
;
3855 uint32_t oldPowerState
= getPowerState();
3857 assert( fDriverCallBusy
);
3858 assert( fDriverCallParamPtr
);
3859 assert( fDriverCallParamCount
== 1 );
3861 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3862 powerState
= fHeadNotePowerState
;
3864 if (assertPMDriverCall(&callEntry
))
3866 OUR_PMLog( kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3867 clock_get_uptime(&fDriverCallStartTime
);
3868 result
= fControllingDriver
->setPowerState( powerState
, this );
3869 clock_get_uptime(&end
);
3870 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3872 deassertPMDriverCall(&callEntry
);
3876 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
3877 fName
, this, fCurrentPowerState
, powerState
, result
);
3880 #if LOG_SETPOWER_TIMES
3881 if ((result
== IOPMAckImplied
) || (result
< 0))
3885 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
3886 absolutetime_to_nanoseconds(end
, &nsec
);
3887 if (nsec
> LOG_SETPOWER_TIMES
)
3888 PM_LOG("%s::setPowerState(%p, %lu -> %lu) took %d ms\n",
3889 fName
, this, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3891 PMEventDetails
*details
= PMEventDetails::eventDetails(
3892 kIOPMEventTypeSetPowerStateImmediate
, // type
3894 (uintptr_t)this, // owner unique
3895 NULL
, // interest name
3896 (uint8_t)oldPowerState
, // old
3897 (uint8_t)powerState
, // new
3899 NS_TO_US(nsec
)); // usec completion time
3901 getPMRootDomain()->recordAndReleasePMEvent( details
);
3906 result
= kIOPMAckImplied
;
3908 param
->Result
= result
;
3911 //*********************************************************************************
3912 // [private] driverInformPowerChange
3914 // Thread call context
3915 //*********************************************************************************
3917 void IOService::driverInformPowerChange( void )
3919 IOPMinformee
* informee
;
3921 DriverCallParam
* param
;
3922 IOPMDriverCallEntry callEntry
;
3923 IOPMPowerFlags powerFlags
;
3924 IOPMPowerStateIndex powerState
;
3929 assert( fDriverCallBusy
);
3930 assert( fDriverCallParamPtr
);
3931 assert( fDriverCallParamCount
);
3933 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3934 count
= fDriverCallParamCount
;
3936 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
3937 powerState
= fHeadNotePowerState
;
3939 for (IOItemCount i
= 0; i
< count
; i
++)
3941 informee
= (IOPMinformee
*) param
->Target
;
3942 driver
= informee
->whatObject
;
3944 if (assertPMDriverCall(&callEntry
, 0, informee
))
3946 if (fDriverCallReason
== kDriverCallInformPreChange
)
3948 OUR_PMLog(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
3949 clock_get_uptime(&informee
->startTime
);
3950 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
3951 clock_get_uptime(&end
);
3952 OUR_PMLog((UInt32
)-kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
3956 OUR_PMLog(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
3957 clock_get_uptime(&informee
->startTime
);
3958 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
3959 clock_get_uptime(&end
);
3960 OUR_PMLog((UInt32
)-kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
3963 deassertPMDriverCall(&callEntry
);
3965 #if LOG_SETPOWER_TIMES
3966 if ((result
== IOPMAckImplied
) || (result
< 0))
3970 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
3971 absolutetime_to_nanoseconds(end
, &nsec
);
3972 if (nsec
> LOG_SETPOWER_TIMES
)
3973 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) took %d ms\n",
3975 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
3976 driver
, fName
, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3978 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
3979 ? kIOPMEventTypePSWillChangeTo
3980 : kIOPMEventTypePSDidChangeTo
;
3982 PMEventDetails
*details
= PMEventDetails::eventDetails(
3985 (uintptr_t)this, // owner unique
3986 driver
->getName(), // interest name
3987 (uint8_t)fCurrentPowerState
, // old
3988 (uint8_t)fHeadNotePowerState
, // new
3990 NS_TO_US(nsec
)); // usec completion time
3992 getPMRootDomain()->recordAndReleasePMEvent( details
);
3997 result
= kIOPMAckImplied
;
3999 param
->Result
= result
;
4004 //*********************************************************************************
4005 // [private] notifyChild
4007 // Notify a power domain child of an upcoming power change.
4008 // If the object acknowledges the current change, we return TRUE.
4009 //*********************************************************************************
4011 bool IOService::notifyChild( IOPowerConnection
* theNub
)
4013 IOReturn ret
= IOPMAckImplied
;
4014 unsigned long childPower
;
4015 IOService
* theChild
;
4016 IOPMRequest
* childRequest
;
4017 IOPMPowerChangeFlags requestArg2
;
4020 PM_ASSERT_IN_GATE();
4021 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
4027 // Unless the child handles the notification immediately and returns
4028 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4029 fHeadNotePendingAcks
++;
4030 theNub
->setAwaitingAck(true);
4032 requestArg2
= fHeadNoteChangeFlags
;
4033 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
))
4034 requestArg2
|= kIOPMDomainPowerDrop
;
4036 requestType
= fIsPreChange
?
4037 kIOPMRequestTypePowerDomainWillChange
:
4038 kIOPMRequestTypePowerDomainDidChange
;
4040 childRequest
= acquirePMRequest( theChild
, requestType
);
4044 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4045 childRequest
->fArg1
= (void *) theNub
;
4046 childRequest
->fArg2
= (void *)(uintptr_t) requestArg2
;
4047 theChild
->submitPMRequest( childRequest
);
4048 ret
= IOPMWillAckLater
;
4052 ret
= IOPMAckImplied
;
4053 fHeadNotePendingAcks
--;
4054 theNub
->setAwaitingAck(false);
4055 childPower
= theChild
->currentPowerConsumption();
4056 if ( childPower
== kIOPMUnknown
)
4058 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4060 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
4061 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4065 theChild
->release();
4066 return (IOPMAckImplied
== ret
);
4069 //*********************************************************************************
4070 // [private] notifyControllingDriver
4071 //*********************************************************************************
4073 bool IOService::notifyControllingDriver( void )
4075 DriverCallParam
* param
;
4077 PM_ASSERT_IN_GATE();
4078 assert( fDriverCallParamCount
== 0 );
4079 assert( fControllingDriver
);
4081 if (fInitialSetPowerState
)
4083 fInitialSetPowerState
= false;
4084 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4086 // Driver specified flag to skip the inital setPowerState()
4087 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)
4093 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4096 param
= IONew(DriverCallParam
, 1);
4098 return false; // no memory
4100 fDriverCallParamPtr
= (void *) param
;
4101 fDriverCallParamSlots
= 1;
4104 param
->Target
= fControllingDriver
;
4105 fDriverCallParamCount
= 1;
4108 // Block state machine and wait for callout completion.
4109 assert(!fDriverCallBusy
);
4110 fDriverCallBusy
= true;
4111 thread_call_enter( fDriverCallEntry
);
4116 //*********************************************************************************
4117 // [private] notifyControllingDriverDone
4118 //*********************************************************************************
4120 void IOService::notifyControllingDriverDone( void )
4122 DriverCallParam
* param
;
4125 PM_ASSERT_IN_GATE();
4126 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4128 assert( fDriverCallBusy
== false );
4129 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4131 if (param
&& fDriverCallParamCount
)
4133 assert(fDriverCallParamCount
== 1);
4135 // the return value from setPowerState()
4136 result
= param
->Result
;
4138 if ((result
== IOPMAckImplied
) || (result
< 0))
4142 else if (fDriverTimer
)
4144 assert(fDriverTimer
== -1);
4146 // Driver has not acked, and has returned a positive result.
4147 // Enforce a minimum permissible timeout value.
4148 // Make the min value large enough so timeout is less likely
4149 // to occur if a driver misinterpreted that the return value
4150 // should be in microsecond units. And make it large enough
4151 // to be noticeable if a driver neglects to ack.
4153 if (result
< kMinAckTimeoutTicks
)
4154 result
= kMinAckTimeoutTicks
;
4156 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4158 // else, child has already acked and driver_timer reset to 0.
4160 fDriverCallParamCount
= 0;
4164 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4169 MS_POP(); // pushed by OurChangeSetPowerState()
4170 fIsPreChange
= false;
4173 //*********************************************************************************
4174 // [private] all_done
4176 // A power change is done.
4177 //*********************************************************************************
4179 void IOService::all_done( void )
4181 IOPMPowerStateIndex prevPowerState
;
4182 const IOPMPSEntry
* powerStatePtr
;
4183 IOPMDriverCallEntry callEntry
;
4184 uint32_t prevMachineState
= fMachineState
;
4185 bool callAction
= false;
4188 fMachineState
= kIOPM_Finished
;
4190 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4191 ((prevMachineState
== kIOPM_Finished
) ||
4192 (prevMachineState
== kIOPM_SyncFinish
)))
4194 // Sync operation and no power change occurred.
4195 // Do not inform driver and clients about this request completion,
4196 // except for the originator (root domain).
4198 PM_ACTION_2(actionPowerChangeDone
,
4199 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4201 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
4203 powerChangeDone(fCurrentPowerState
);
4205 else if (fAdvisoryTickleUsed
)
4207 // Not root domain and advisory tickle target.
4208 // Re-adjust power after power tree sync at the 'did' pass
4209 // to recompute desire and adjust power state between dark
4210 // and full wake transitions. Root domain is responsible
4211 // for calling setAdvisoryTickleEnable() before starting
4212 // the kIOPMSynchronize power change.
4214 if (!fAdjustPowerScheduled
&&
4215 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
))
4217 IOPMRequest
* request
;
4218 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4221 submitPMRequest( request
);
4222 fAdjustPowerScheduled
= true;
4231 if ( fHeadNoteChangeFlags
& kIOPMSelfInitiated
)
4233 // could our driver switch to the new state?
4234 if ( !( fHeadNoteChangeFlags
& kIOPMNotDone
) )
4236 trackSystemSleepPreventers(
4237 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4239 // we changed, tell our parent
4240 requestDomainPower(fHeadNotePowerState
);
4242 // yes, did power raise?
4243 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4245 // yes, inform clients and apps
4246 tellChangeUp (fHeadNotePowerState
);
4248 prevPowerState
= fCurrentPowerState
;
4250 fCurrentPowerState
= fHeadNotePowerState
;
4253 ts
= mach_absolute_time();
4254 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4258 fPMVars
->myCurrentState
= fCurrentPowerState
;
4260 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4261 PM_ACTION_2(actionPowerChangeDone
,
4262 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4265 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4266 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4267 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4268 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4270 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4272 // Bump tickle generation count once the entire tree is down
4273 gIOPMTickleGeneration
++;
4276 // inform subclass policy-maker
4277 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4278 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4280 powerChangeDone(prevPowerState
);
4281 deassertPMDriverCall(&callEntry
);
4284 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
4286 // changePowerStateWithOverrideTo() was cancelled
4287 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4291 // parent's power change
4292 if ( fHeadNoteChangeFlags
& kIOPMParentInitiated
)
4294 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4295 ParentChangeRootChangeDown();
4297 if (((fHeadNoteChangeFlags
& kIOPMDomainWillChange
) &&
4298 (StateOrder(fCurrentPowerState
) >= StateOrder(fHeadNotePowerState
))) ||
4299 ((fHeadNoteChangeFlags
& kIOPMDomainDidChange
) &&
4300 (StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
))))
4302 trackSystemSleepPreventers(
4303 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4306 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4308 // yes, inform clients and apps
4309 tellChangeUp (fHeadNotePowerState
);
4312 prevPowerState
= fCurrentPowerState
;
4313 fCurrentPowerState
= fHeadNotePowerState
;
4316 ts
= mach_absolute_time();
4317 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4321 fPMVars
->myCurrentState
= fCurrentPowerState
;
4323 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fHeadNoteDomainFlags
);
4325 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4326 PM_ACTION_2(actionPowerChangeDone
,
4327 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4330 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4331 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4332 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4333 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4335 // inform subclass policy-maker
4336 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4337 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4339 powerChangeDone(prevPowerState
);
4340 deassertPMDriverCall(&callEntry
);
4345 // When power rises enough to satisfy the tickle's desire for more power,
4346 // the condition preventing idle-timer from dropping power is removed.
4348 if (StateOrder(fCurrentPowerState
) >= StateOrder(fIdleTimerMinPowerState
))
4350 fIdleTimerMinPowerState
= kPowerStateZero
;
4355 PM_ACTION_2(actionPowerChangeDone
,
4356 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4361 // MARK: Power Change Initiated by Driver
4363 //*********************************************************************************
4364 // [private] OurChangeStart
4366 // Begin the processing of a power change initiated by us.
4367 //*********************************************************************************
4369 void IOService::OurChangeStart( void )
4371 PM_ASSERT_IN_GATE();
4372 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4374 // fMaxPowerState is our maximum possible power state based on the current
4375 // power state of our parents. If we are trying to raise power beyond the
4376 // maximum, send an async request for more power to all parents.
4378 if (!IS_PM_ROOT
&& (StateOrder(fMaxPowerState
) < StateOrder(fHeadNotePowerState
)))
4380 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4381 requestDomainPower(fHeadNotePowerState
);
4386 // Redundant power changes skips to the end of the state machine.
4388 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
4393 fInitialPowerChange
= false;
4395 // Change started, but may not complete...
4396 // Can be canceled (power drop) or deferred (power rise).
4398 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4400 // Two separate paths, depending if power is being raised or lowered.
4401 // Lowering power is subject to approval by clients of this service.
4405 fDoNotPowerDown
= false;
4407 // Ask for persmission to drop power state
4408 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4409 fOutOfBandParameter
= kNotifyApps
;
4410 askChangeDown(fHeadNotePowerState
);
4414 // This service is raising power and parents are able to support the
4415 // new power state. However a parent may have already committed to
4416 // drop power, which might force this object to temporarily drop power.
4417 // This results in "oscillations" before the state machines converge
4418 // to a steady state.
4420 // To prevent this, a child must make a power reservation against all
4421 // parents before raising power. If the reservation fails, indicating
4422 // that the child will be unable to sustain the higher power state,
4423 // then the child will signal the parent to adjust power, and the child
4424 // will defer its power change.
4428 // Reserve parent power necessary to achieve fHeadNotePowerState.
4429 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4430 if (ret
!= kIOReturnSuccess
)
4432 // Reservation failed, defer power rise.
4433 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4438 OurChangeTellCapabilityWillChange();
4442 //*********************************************************************************
4443 // [private] requestDomainPowerApplier
4445 // Call requestPowerDomainState() on all power parents.
4446 //*********************************************************************************
4448 struct IOPMRequestDomainPowerContext
{
4449 IOService
* child
; // the requesting child
4450 IOPMPowerFlags requestPowerFlags
; // power flags requested by child
4454 requestDomainPowerApplier(
4455 IORegistryEntry
* entry
,
4458 IOPowerConnection
* connection
;
4460 IOPMRequestDomainPowerContext
* context
;
4462 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0)
4464 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4469 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4471 if (connection
->parentKnowsState() && connection
->getReadyFlag())
4473 parent
->requestPowerDomainState(
4474 context
->requestPowerFlags
,
4482 //*********************************************************************************
4483 // [private] requestDomainPower
4485 // Called by a power child to broadcast its desired power state to all parents.
4486 // If the child self-initiates a power change, it must call this function to
4487 // allow its parents to adjust power state.
4488 //*********************************************************************************
4490 IOReturn
IOService::requestDomainPower(
4491 IOPMPowerStateIndex ourPowerState
,
4492 IOOptionBits options
)
4494 IOPMPowerFlags requestPowerFlags
;
4495 IOPMPowerStateIndex maxPowerState
;
4496 IOPMRequestDomainPowerContext context
;
4498 PM_ASSERT_IN_GATE();
4499 assert(ourPowerState
< fNumberOfPowerStates
);
4500 if (ourPowerState
>= fNumberOfPowerStates
)
4501 return kIOReturnBadArgument
;
4503 return kIOReturnSuccess
;
4505 // Fetch our input power flags for the requested power state.
4506 // Parent request is stated in terms of required power flags.
4508 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4510 // Disregard the "previous request" for power reservation.
4512 if (((options
& kReserveDomainPower
) == 0) &&
4513 (fPreviousRequestPowerFlags
== requestPowerFlags
))
4515 // skip if domain already knows our requirements
4518 fPreviousRequestPowerFlags
= requestPowerFlags
;
4520 // The results will be collected by fHeadNoteDomainTargetFlags
4521 context
.child
= this;
4522 context
.requestPowerFlags
= requestPowerFlags
;
4523 fHeadNoteDomainTargetFlags
= 0;
4524 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4526 if (options
& kReserveDomainPower
)
4528 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4529 fHeadNoteDomainTargetFlags
);
4531 if (StateOrder(maxPowerState
) < StateOrder(ourPowerState
))
4533 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4535 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4536 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4537 return kIOReturnNoPower
;
4542 return kIOReturnSuccess
;
4545 //*********************************************************************************
4546 // [private] OurSyncStart
4547 //*********************************************************************************
4549 void IOService::OurSyncStart( void )
4551 PM_ASSERT_IN_GATE();
4553 if (fInitialPowerChange
)
4556 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4558 if (fHeadNoteChangeFlags
& kIOPMNotDone
)
4564 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
)
4566 fDoNotPowerDown
= false;
4568 // Ask for permission to drop power state
4569 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4570 fOutOfBandParameter
= kNotifyApps
;
4571 askChangeDown(fHeadNotePowerState
);
4575 // Only inform capability app and clients.
4576 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4580 //*********************************************************************************
4581 // [private] OurChangeTellClientsPowerDown
4583 // All applications and kernel clients have acknowledged our permission to drop
4584 // power. Here we notify them that we will lower the power and wait for acks.
4585 //*********************************************************************************
4587 void IOService::OurChangeTellClientsPowerDown( void )
4590 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4593 fMachineState
= kIOPM_OurChangeTellUserPMPolicyPowerDown
;
4595 tellChangeDown1(fHeadNotePowerState
);
4598 //*********************************************************************************
4599 // [private] OurChangeTellUserPMPolicyPowerDown
4601 // All applications and kernel clients have acknowledged our permission to drop
4602 // power. Here we notify power management policy in user-space and wait for acks
4603 // one last time before we lower power
4604 //*********************************************************************************
4605 void IOService::OurChangeTellUserPMPolicyPowerDown ( void )
4607 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4608 fOutOfBandParameter
= kNotifyApps
;
4610 tellClientsWithResponse(kIOPMMessageLastCallBeforeSleep
);
4613 //*********************************************************************************
4614 // [private] OurChangeTellPriorityClientsPowerDown
4616 // All applications and kernel clients have acknowledged our intention to drop
4617 // power. Here we notify "priority" clients that we are lowering power.
4618 //*********************************************************************************
4620 void IOService::OurChangeTellPriorityClientsPowerDown( void )
4622 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4623 tellChangeDown2(fHeadNotePowerState
);
4626 //*********************************************************************************
4627 // [private] OurChangeTellCapabilityWillChange
4629 // Extra stage for root domain to notify apps and drivers about the
4630 // system capability change when raising power state.
4631 //*********************************************************************************
4633 void IOService::OurChangeTellCapabilityWillChange( void )
4635 if (!IS_ROOT_DOMAIN
)
4636 return OurChangeNotifyInterestedDriversWillChange();
4638 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4641 //*********************************************************************************
4642 // [private] OurChangeNotifyInterestedDriversWillChange
4644 // All applications and kernel clients have acknowledged our power state change.
4645 // Here we notify interested drivers pre-change.
4646 //*********************************************************************************
4648 void IOService::OurChangeNotifyInterestedDriversWillChange( void )
4650 IOPMrootDomain
* rootDomain
;
4651 if ((rootDomain
= getPMRootDomain()) == this)
4655 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4657 PMEventDetails
*details
= PMEventDetails::eventDetails(
4658 kIOPMEventTypeAppNotificationsFinished
,
4662 rootDomain
->recordAndReleasePMEvent( details
);
4665 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4668 notifyAll( kIOPM_OurChangeSetPowerState
);
4671 //*********************************************************************************
4672 // [private] OurChangeSetPowerState
4674 // Instruct our controlling driver to program the hardware for the power state
4675 // change. Wait for async completions.
4676 //*********************************************************************************
4678 void IOService::OurChangeSetPowerState( void )
4680 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4681 fMachineState
= kIOPM_DriverThreadCallDone
;
4682 fDriverCallReason
= kDriverCallSetPowerState
;
4684 if (notifyControllingDriver() == false)
4685 notifyControllingDriverDone();
4688 //*********************************************************************************
4689 // [private] OurChangeWaitForPowerSettle
4691 // Our controlling driver has completed the power state change we initiated.
4692 // Wait for the driver specified settle time to expire.
4693 //*********************************************************************************
4695 void IOService::OurChangeWaitForPowerSettle( void )
4697 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4701 //*********************************************************************************
4702 // [private] OurChangeNotifyInterestedDriversDidChange
4704 // Power has settled on a power change we initiated. Here we notify
4705 // all our interested drivers post-change.
4706 //*********************************************************************************
4708 void IOService::OurChangeNotifyInterestedDriversDidChange( void )
4710 IOPMrootDomain
* rootDomain
;
4711 if ((rootDomain
= getPMRootDomain()) == this)
4713 rootDomain
->tracePoint( IS_POWER_DROP
?
4714 kIOPMTracePointSleepDidChangeInterests
:
4715 kIOPMTracePointWakeDidChangeInterests
);
4718 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4721 //*********************************************************************************
4722 // [private] OurChangeTellCapabilityDidChange
4724 // For root domain to notify capability power-change.
4725 //*********************************************************************************
4727 void IOService::OurChangeTellCapabilityDidChange( void )
4729 if (!IS_ROOT_DOMAIN
)
4730 return OurChangeFinish();
4732 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4733 kIOPMTracePointSleepCapabilityClients
:
4734 kIOPMTracePointWakeCapabilityClients
);
4736 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4739 //*********************************************************************************
4740 // [private] OurChangeFinish
4742 // Done with this self-induced power state change.
4743 //*********************************************************************************
4745 void IOService::OurChangeFinish( void )
4751 // MARK: Power Change Initiated by Parent
4753 //*********************************************************************************
4754 // [private] ParentChangeStart
4756 // Here we begin the processing of a power change initiated by our parent.
4757 //*********************************************************************************
4759 IOReturn
IOService::ParentChangeStart( void )
4761 PM_ASSERT_IN_GATE();
4762 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4764 // Root power domain has transitioned to its max power state
4765 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4766 (kIOPMDomainDidChange
| kIOPMRootChangeUp
))
4768 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4769 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
4775 // Power domain is forcing us to lower power
4776 if ( StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
) )
4778 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4780 // Tell apps and kernel clients
4781 fInitialPowerChange
= false;
4782 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4783 tellChangeDown1(fHeadNotePowerState
);
4784 return IOPMWillAckLater
;
4787 // Power domain is allowing us to raise power up to fHeadNotePowerState
4788 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4790 if ( StateOrder(fDesiredPowerState
) > StateOrder(fCurrentPowerState
) )
4792 if ( StateOrder(fDesiredPowerState
) < StateOrder(fHeadNotePowerState
) )
4794 // We power up, but not all the way
4795 fHeadNotePowerState
= fDesiredPowerState
;
4796 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4797 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4800 // We don't need to change
4801 fHeadNotePowerState
= fCurrentPowerState
;
4802 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4803 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4807 if ( fHeadNoteChangeFlags
& kIOPMDomainDidChange
)
4809 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4811 PM_ACTION_2(actionPowerChangeStart
,
4812 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4814 // Parent did change up - start our change up
4815 fInitialPowerChange
= false;
4816 ParentChangeTellCapabilityWillChange();
4817 return IOPMWillAckLater
;
4819 else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
)
4821 // No need to change power state, but broadcast change
4823 fMachineState
= kIOPM_SyncNotifyDidChange
;
4824 fDriverCallReason
= kDriverCallInformPreChange
;
4826 return IOPMWillAckLater
;
4831 return IOPMAckImplied
;
4834 //******************************************************************************
4835 // [private] ParentChangeRootChangeDown
4837 // Root domain has finished the transition to the system sleep state. And all
4838 // drivers in the power plane should have powered down. Cancel the idle timer,
4839 // and also reset the device desire for those drivers that don't want power
4840 // automatically restored on wake.
4841 //******************************************************************************
4843 void IOService::ParentChangeRootChangeDown( void )
4845 // Always stop the idle timer before root power down
4846 if (fIdleTimerPeriod
&& !fIdleTimerStopped
)
4848 fIdleTimerStopped
= true;
4849 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
4853 if (fResetPowerStateOnWake
)
4855 // Reset device desire down to the lowest power state.
4856 // Advisory tickle desire is intentionally untouched since
4857 // it has no effect until system is promoted to full wake.
4859 if (fDeviceDesire
!= kPowerStateZero
)
4861 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4862 computeDesiredState(kPowerStateZero
, true);
4863 PM_LOG1("%s: tickle desire removed\n", fName
);
4866 // Invalidate tickle cache so the next tickle will issue a request
4867 IOLockLock(fActivityLock
);
4868 fDeviceWasActive
= false;
4869 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4870 IOLockUnlock(fActivityLock
);
4872 fIdleTimerMinPowerState
= kPowerStateZero
;
4874 else if (fAdvisoryTickleUsed
)
4876 // Less aggressive mechanism to accelerate idle timer expiration
4877 // before system sleep. May not always allow the driver to wake
4878 // up from system sleep in the min power state.
4882 bool dropTickleDesire
= false;
4884 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
4885 (fIdleTimerMinPowerState
== kPowerStateZero
) &&
4886 (fDeviceDesire
!= kPowerStateZero
))
4888 IOLockLock(fActivityLock
);
4890 if (!fDeviceWasActive
)
4892 // No tickles since the last idle timer expiration.
4893 // Safe to drop the device desire to zero.
4894 dropTickleDesire
= true;
4898 // Was tickled since the last idle timer expiration,
4899 // but not in the last minute.
4900 clock_get_uptime(&now
);
4901 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
4902 absolutetime_to_nanoseconds(now
, &nsec
);
4903 if (nsec
>= kNoTickleCancelWindow
)
4905 dropTickleDesire
= true;
4909 if (dropTickleDesire
)
4911 // Force the next tickle to raise power state
4912 fDeviceWasActive
= false;
4913 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4916 IOLockUnlock(fActivityLock
);
4919 if (dropTickleDesire
)
4921 // Advisory tickle desire is intentionally untouched since
4922 // it has no effect until system is promoted to full wake.
4924 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4925 computeDesiredState(kPowerStateZero
, true);
4926 PM_LOG1("%s: tickle desire dropped\n", fName
);
4931 //*********************************************************************************
4932 // [private] ParentChangeTellPriorityClientsPowerDown
4934 // All applications and kernel clients have acknowledged our intention to drop
4935 // power. Here we notify "priority" clients that we are lowering power.
4936 //*********************************************************************************
4938 void IOService::ParentChangeTellPriorityClientsPowerDown( void )
4940 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
4941 tellChangeDown2(fHeadNotePowerState
);
4944 //*********************************************************************************
4945 // [private] ParentChangeTellCapabilityWillChange
4947 // All (legacy) applications and kernel clients have acknowledged, extra stage for
4948 // root domain to notify apps and drivers about the system capability change.
4949 //*********************************************************************************
4951 void IOService::ParentChangeTellCapabilityWillChange( void )
4953 if (!IS_ROOT_DOMAIN
)
4954 return ParentChangeNotifyInterestedDriversWillChange();
4956 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
4959 //*********************************************************************************
4960 // [private] ParentChangeNotifyInterestedDriversWillChange
4962 // All applications and kernel clients have acknowledged our power state change.
4963 // Here we notify interested drivers pre-change.
4964 //*********************************************************************************
4966 void IOService::ParentChangeNotifyInterestedDriversWillChange( void )
4968 notifyAll( kIOPM_ParentChangeSetPowerState
);
4971 //*********************************************************************************
4972 // [private] ParentChangeSetPowerState
4974 // Instruct our controlling driver to program the hardware for the power state
4975 // change. Wait for async completions.
4976 //*********************************************************************************
4978 void IOService::ParentChangeSetPowerState( void )
4980 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
4981 fMachineState
= kIOPM_DriverThreadCallDone
;
4982 fDriverCallReason
= kDriverCallSetPowerState
;
4984 if (notifyControllingDriver() == false)
4985 notifyControllingDriverDone();
4988 //*********************************************************************************
4989 // [private] ParentChangeWaitForPowerSettle
4991 // Our controlling driver has completed the power state change initiated by our
4992 // parent. Wait for the driver specified settle time to expire.
4993 //*********************************************************************************
4995 void IOService::ParentChangeWaitForPowerSettle( void )
4997 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
5001 //*********************************************************************************
5002 // [private] ParentChangeNotifyInterestedDriversDidChange
5004 // Power has settled on a power change initiated by our parent. Here we notify
5005 // all our interested drivers post-change.
5006 //*********************************************************************************
5008 void IOService::ParentChangeNotifyInterestedDriversDidChange( void )
5010 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
5013 //*********************************************************************************
5014 // [private] ParentChangeTellCapabilityDidChange
5016 // For root domain to notify capability power-change.
5017 //*********************************************************************************
5019 void IOService::ParentChangeTellCapabilityDidChange( void )
5021 if (!IS_ROOT_DOMAIN
)
5022 return ParentChangeAcknowledgePowerChange();
5024 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
5027 //*********************************************************************************
5028 // [private] ParentAcknowledgePowerChange
5030 // Acknowledge our power parent that our power change is done.
5031 //*********************************************************************************
5033 void IOService::ParentChangeAcknowledgePowerChange( void )
5035 IORegistryEntry
* nub
;
5038 nub
= fHeadNoteParentConnection
;
5041 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
5044 parent
->acknowledgePowerChange((IOService
*)nub
);
5051 // MARK: Ack and Settle timers
5053 //*********************************************************************************
5054 // [private] settleTimerExpired
5056 // Power has settled after our last change. Notify interested parties that
5057 // there is a new power state.
5058 //*********************************************************************************
5060 void IOService::settleTimerExpired( void )
5063 gIOPMWorkQueue
->signalWorkAvailable();
5066 //*********************************************************************************
5067 // settle_timer_expired
5069 // Holds a retain while the settle timer callout is in flight.
5070 //*********************************************************************************
5073 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5075 IOService
* me
= (IOService
*) arg0
;
5077 if (gIOPMWorkLoop
&& gIOPMWorkQueue
)
5079 gIOPMWorkLoop
->runAction(
5080 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5086 //*********************************************************************************
5087 // [private] startSettleTimer
5089 // Calculate a power-settling delay in microseconds and start a timer.
5090 //*********************************************************************************
5092 void IOService::startSettleTimer( void )
5095 // This function is broken and serves no useful purpose since it never
5096 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5097 // yet it starts a delay timer. It appears no driver relies on a delay
5098 // from settleUpTime and settleDownTime in the power state table.
5100 AbsoluteTime deadline
;
5101 IOPMPowerStateIndex stateIndex
;
5102 IOPMPowerStateIndex currentOrder
, newOrder
, i
;
5103 uint32_t settleTime
= 0;
5106 PM_ASSERT_IN_GATE();
5108 currentOrder
= StateOrder(fCurrentPowerState
);
5109 newOrder
= StateOrder(fHeadNotePowerState
);
5114 if ( newOrder
< currentOrder
)
5116 while ( i
> newOrder
)
5118 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
5119 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleDownTime
;
5125 if ( newOrder
> currentOrder
)
5127 while ( i
< newOrder
)
5129 stateIndex
= fPowerStates
[i
+1].stateOrderToIndex
;
5130 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleUpTime
;
5138 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5139 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5140 if (pending
) release();
5145 //*********************************************************************************
5146 // [private] ackTimerTick
5148 // The acknowledgement timeout periodic timer has ticked.
5149 // If we are awaiting acks for a power change notification,
5150 // we decrement the timer word of each interested driver which hasn't acked.
5151 // If a timer word becomes zero, we pretend the driver aknowledged.
5152 // If we are waiting for the controlling driver to change the power
5153 // state of the hardware, we decrement its timer word, and if it becomes
5154 // zero, we pretend the driver acknowledged.
5156 // Returns true if the timer tick made it possible to advance to the next
5157 // machine state, false otherwise.
5158 //*********************************************************************************
5161 void IOService::ack_timer_ticked ( void )
5165 #endif /* !__LP64__ */
5167 bool IOService::ackTimerTick( void )
5169 IOPMinformee
* nextObject
;
5172 PM_ASSERT_IN_GATE();
5173 switch (fMachineState
) {
5174 case kIOPM_OurChangeWaitForPowerSettle
:
5175 case kIOPM_ParentChangeWaitForPowerSettle
:
5176 // are we waiting for controlling driver to acknowledge?
5177 if ( fDriverTimer
> 0 )
5179 // yes, decrement timer tick
5181 if ( fDriverTimer
== 0 )
5183 // controlling driver is tardy
5184 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5185 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
5186 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
5187 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5188 fName
, OBFUSCATE(this), fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5190 #if LOG_SETPOWER_TIMES
5191 PMEventDetails
*details
= PMEventDetails::eventDetails(
5192 kIOPMEventTypeSetPowerStateDelayed
, // type
5194 (uintptr_t)this, // owner unique
5195 NULL
, // interest name
5196 (uint8_t)getPowerState(), // old
5198 kIOReturnTimeout
, // result
5199 NS_TO_US(nsec
)); // usec completion time
5201 getPMRootDomain()->recordAndReleasePMEvent( details
);
5204 if (gIOKitDebug
& kIOLogDebugPower
)
5206 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5207 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5211 // Unblock state machine and pretend driver has acked.
5215 // still waiting, set timer again
5221 case kIOPM_NotifyChildrenStart
:
5222 // are we waiting for interested parties to acknowledge?
5223 if ( fHeadNotePendingAcks
!= 0 )
5225 // yes, go through the list of interested drivers
5226 nextObject
= fInterestedDrivers
->firstInList();
5227 // and check each one
5228 while ( nextObject
!= NULL
)
5230 if ( nextObject
->timer
> 0 )
5232 nextObject
->timer
--;
5233 // this one should have acked by now
5234 if ( nextObject
->timer
== 0 )
5236 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5237 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5238 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5239 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5240 nextObject
->whatObject
->getName(),
5241 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5242 OBFUSCATE(nextObject
->whatObject
), fName
, fCurrentPowerState
, fHeadNotePowerState
,
5245 #if LOG_SETPOWER_TIMES
5246 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
5247 ? kIOPMEventTypePSWillChangeTo
5248 : kIOPMEventTypePSDidChangeTo
;
5250 PMEventDetails
*details
= PMEventDetails::eventDetails(
5253 (uintptr_t)this, // owner unique
5254 nextObject
->whatObject
->getName(), // interest name
5255 (uint8_t)fCurrentPowerState
, // old
5256 (uint8_t)fHeadNotePowerState
, // new
5257 kIOReturnTimeout
, // result
5258 NS_TO_US(nsec
)); // usec completion time
5260 getPMRootDomain()->recordAndReleasePMEvent( details
);
5263 // Pretend driver has acked.
5264 fHeadNotePendingAcks
--;
5267 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5270 // is that the last?
5271 if ( fHeadNotePendingAcks
== 0 )
5273 // yes, we can continue
5276 // no, set timer again
5282 // TODO: aggreggate this
5283 case kIOPM_OurChangeTellClientsPowerDown
:
5284 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
5285 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5286 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5287 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5288 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5289 case kIOPM_SyncTellClientsPowerDown
:
5290 case kIOPM_SyncTellPriorityClientsPowerDown
:
5291 case kIOPM_SyncNotifyWillChange
:
5292 case kIOPM_TellCapabilityChangeDone
:
5293 // apps didn't respond in time
5294 cleanClientResponses(true);
5295 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5296 // tardy equates to approval
5301 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5302 getName(), fMachineState
);
5308 //*********************************************************************************
5309 // [private] start_watchdog_timer
5310 //*********************************************************************************
5311 void IOService::start_watchdog_timer( void )
5313 AbsoluteTime deadline
;
5316 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
) ||
5317 (getPMRootDomain()->sleepWakeDebugIsWdogEnabled() == false))
5320 if (thread_call_isactive(fWatchdogTimer
)) return;
5322 clock_interval_to_deadline(WATCHDOG_TIMER_PERIOD
, kSecondScale
, &deadline
);
5325 pending
= thread_call_enter_delayed(fWatchdogTimer
, deadline
);
5326 if (pending
) release();
5330 //*********************************************************************************
5331 // [private] stop_watchdog_timer
5332 // Returns true if watchdog was enabled and stopped now
5333 //*********************************************************************************
5335 bool IOService::stop_watchdog_timer( void )
5339 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
) ||
5340 (getPMRootDomain()->sleepWakeDebugIsWdogEnabled() == false))
5343 pending
= thread_call_cancel(fWatchdogTimer
);
5344 if (pending
) release();
5349 //*********************************************************************************
5350 // reset_watchdog_timer
5351 //*********************************************************************************
5353 void IOService::reset_watchdog_timer( void )
5355 if (stop_watchdog_timer())
5356 start_watchdog_timer();
5360 //*********************************************************************************
5361 // [static] watchdog_timer_expired
5363 // Inside PM work loop's gate.
5364 //*********************************************************************************
5367 IOService::watchdog_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5369 IOService
* me
= (IOService
*) arg0
;
5372 gIOPMWatchDogThread
= current_thread();
5373 getPMRootDomain()->sleepWakeDebugTrig(true);
5374 gIOPMWatchDogThread
= 0;
5381 //*********************************************************************************
5382 // [private] start_ack_timer
5383 //*********************************************************************************
5385 void IOService::start_ack_timer( void )
5387 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5390 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
5392 AbsoluteTime deadline
;
5395 clock_interval_to_deadline(interval
, scale
, &deadline
);
5398 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5399 if (pending
) release();
5401 // Stop watchdog if ack is delayed by more than a sec
5402 if (interval
* scale
> kSecondScale
) {
5403 stop_watchdog_timer();
5407 //*********************************************************************************
5408 // [private] stop_ack_timer
5409 //*********************************************************************************
5411 void IOService::stop_ack_timer( void )
5415 pending
= thread_call_cancel(fAckTimer
);
5416 if (pending
) release();
5418 start_watchdog_timer();
5421 //*********************************************************************************
5422 // [static] actionAckTimerExpired
5424 // Inside PM work loop's gate.
5425 //*********************************************************************************
5428 IOService::actionAckTimerExpired(
5430 void * arg0
, void * arg1
,
5431 void * arg2
, void * arg3
)
5433 IOService
* me
= (IOService
*) target
;
5436 // done will be true if the timer tick unblocks the machine state,
5437 // otherwise no need to signal the work loop.
5439 done
= me
->ackTimerTick();
5440 if (done
&& gIOPMWorkQueue
)
5442 gIOPMWorkQueue
->signalWorkAvailable();
5443 me
->start_watchdog_timer();
5446 return kIOReturnSuccess
;
5449 //*********************************************************************************
5450 // ack_timer_expired
5452 // Thread call function. Holds a retain while the callout is in flight.
5453 //*********************************************************************************
5456 IOService::ack_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5458 IOService
* me
= (IOService
*) arg0
;
5462 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5468 // MARK: Client Messaging
5470 //*********************************************************************************
5471 // [private] tellSystemCapabilityChange
5472 //*********************************************************************************
5474 void IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5477 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5478 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5482 // Notify app first on pre-change.
5483 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5487 // Notify kernel clients first on post-change.
5488 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5491 tellClientsWithResponse( fOutOfBandMessage
);
5494 //*********************************************************************************
5495 // [public] askChangeDown
5497 // Ask registered applications and kernel clients if we can change to a lower
5500 // Subclass can override this to send a different message type. Parameter is
5501 // the destination state number.
5503 // Return true if we don't have to wait for acknowledgements
5504 //*********************************************************************************
5506 bool IOService::askChangeDown( unsigned long stateNum
)
5508 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5511 //*********************************************************************************
5512 // [private] tellChangeDown1
5514 // Notify registered applications and kernel clients that we are definitely
5517 // Return true if we don't have to wait for acknowledgements
5518 //*********************************************************************************
5520 bool IOService::tellChangeDown1( unsigned long stateNum
)
5522 fOutOfBandParameter
= kNotifyApps
;
5523 return tellChangeDown(stateNum
);
5526 //*********************************************************************************
5527 // [private] tellChangeDown2
5529 // Notify priority clients that we are definitely dropping power.
5531 // Return true if we don't have to wait for acknowledgements
5532 //*********************************************************************************
5534 bool IOService::tellChangeDown2( unsigned long stateNum
)
5536 fOutOfBandParameter
= kNotifyPriority
;
5537 return tellChangeDown(stateNum
);
5540 //*********************************************************************************
5541 // [public] tellChangeDown
5543 // Notify registered applications and kernel clients that we are definitely
5546 // Subclass can override this to send a different message type. Parameter is
5547 // the destination state number.
5549 // Return true if we don't have to wait for acknowledgements
5550 //*********************************************************************************
5552 bool IOService::tellChangeDown( unsigned long stateNum
)
5554 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5557 //*********************************************************************************
5558 // cleanClientResponses
5560 //*********************************************************************************
5562 static void logAppTimeouts( OSObject
* object
, void * arg
)
5564 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5566 unsigned int clientIndex
;
5570 if (OSDynamicCast(_IOServiceInterestNotifier
, object
))
5572 // Discover the 'counter' value or index assigned to this client
5573 // when it was notified, by searching for the array index of the
5574 // client in an array holding the cached interested clients.
5576 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5578 if ((clientIndex
!= (unsigned int) -1) &&
5579 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5580 (flag
!= kOSBooleanTrue
))
5582 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5586 pid
= clientID
->unsigned32BitValue();
5587 proc_name(pid
, name
, sizeof(name
));
5588 clientID
->release();
5591 PM_ERROR(context
->errorLog
, pid
, name
);
5593 // TODO: record message type if possible
5594 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5595 gIOPMStatsApplicationResponseTimedOut
,
5596 name
, 0, (30*1000), pid
);
5602 void IOService::cleanClientResponses( bool logErrors
)
5604 if (logErrors
&& fResponseArray
)
5606 switch ( fOutOfBandParameter
) {
5608 case kNotifyCapabilityChangeApps
:
5609 if (fNotifyClientArray
)
5611 IOPMInterestContext context
;
5613 context
.responseArray
= fResponseArray
;
5614 context
.notifyClients
= fNotifyClientArray
;
5615 context
.serialNumber
= fSerialNumber
;
5616 context
.messageType
= kIOMessageCopyClientID
;
5617 context
.notifyType
= kNotifyApps
;
5618 context
.isPreChange
= fIsPreChange
;
5619 context
.enableTracing
= false;
5621 context
.maxTimeRequested
= 0;
5622 context
.stateNumber
= fHeadNotePowerState
;
5623 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5624 context
.changeFlags
= fHeadNoteChangeFlags
;
5625 context
.errorLog
= "PM notification timeout (pid %d, %s)\n";
5627 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5632 // kNotifyPriority, kNotifyCapabilityChangePriority
5633 // TODO: identify the priority client that has not acked
5634 PM_ERROR("PM priority notification timeout\n");
5635 if (gIOKitDebug
& kIOLogDebugPower
)
5637 panic("PM priority notification timeout");
5645 fResponseArray
->release();
5646 fResponseArray
= NULL
;
5648 if (fNotifyClientArray
)
5650 fNotifyClientArray
->release();
5651 fNotifyClientArray
= NULL
;
5655 //*********************************************************************************
5656 // [protected] tellClientsWithResponse
5658 // Notify registered applications and kernel clients that we are definitely
5661 // Return true if we don't have to wait for acknowledgements
5662 //*********************************************************************************
5664 bool IOService::tellClientsWithResponse( int messageType
)
5666 IOPMInterestContext context
;
5667 bool isRootDomain
= IS_ROOT_DOMAIN
;
5669 PM_ASSERT_IN_GATE();
5670 assert( fResponseArray
== NULL
);
5671 assert( fNotifyClientArray
== NULL
);
5673 if(messageType
== (int)kIOPMMessageLastCallBeforeSleep
)
5674 RD_LOG("tellClientsWithResponse( kIOPMMessageLastCallBeforeSleep, %d )\n",
5675 fOutOfBandParameter
);
5677 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5678 getIOMessageString(messageType
), fOutOfBandParameter
);
5680 fResponseArray
= OSArray::withCapacity( 1 );
5681 if (!fResponseArray
)
5684 fResponseArray
->setCapacityIncrement(8);
5685 if (++fSerialNumber
== 0)
5688 context
.responseArray
= fResponseArray
;
5689 context
.notifyClients
= 0;
5690 context
.serialNumber
= fSerialNumber
;
5691 context
.messageType
= messageType
;
5692 context
.notifyType
= fOutOfBandParameter
;
5693 context
.isPreChange
= fIsPreChange
;
5694 context
.enableTracing
= false;
5696 context
.maxTimeRequested
= 0;
5697 context
.stateNumber
= fHeadNotePowerState
;
5698 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5699 context
.changeFlags
= fHeadNoteChangeFlags
;
5700 context
.messageFilter
= (isRootDomain
) ?
5701 OSMemberFunctionCast(
5704 &IOPMrootDomain::systemMessageFilter
) : 0;
5706 switch ( fOutOfBandParameter
) {
5708 applyToInterested( gIOAppPowerStateInterest
,
5709 pmTellAppWithResponse
, (void *) &context
);
5712 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5713 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
) &&
5714 (context
.messageType
!= kIOPMMessageLastCallBeforeSleep
))
5716 // Notify capability app for tellChangeDown1()
5717 // but not for askChangeDown().
5718 context
.notifyType
= kNotifyCapabilityChangeApps
;
5719 context
.messageType
= kIOMessageSystemCapabilityChange
;
5720 applyToInterested( gIOAppPowerStateInterest
,
5721 pmTellCapabilityAppWithResponse
, (void *) &context
);
5722 context
.notifyType
= fOutOfBandParameter
;
5723 context
.messageType
= messageType
;
5725 context
.maxTimeRequested
= k30Seconds
;
5727 applyToInterested( gIOGeneralInterest
,
5728 pmTellClientWithResponse
, (void *) &context
);
5730 fNotifyClientArray
= context
.notifyClients
;
5733 case kNotifyPriority
:
5734 context
.enableTracing
= isRootDomain
;
5735 applyToInterested( gIOPriorityPowerStateInterest
,
5736 pmTellClientWithResponse
, (void *) &context
);
5740 // Notify capability clients for tellChangeDown2().
5741 context
.notifyType
= kNotifyCapabilityChangePriority
;
5742 context
.messageType
= kIOMessageSystemCapabilityChange
;
5743 applyToInterested( gIOPriorityPowerStateInterest
,
5744 pmTellCapabilityClientWithResponse
, (void *) &context
);
5748 case kNotifyCapabilityChangeApps
:
5749 applyToInterested( gIOAppPowerStateInterest
,
5750 pmTellCapabilityAppWithResponse
, (void *) &context
);
5751 fNotifyClientArray
= context
.notifyClients
;
5752 context
.maxTimeRequested
= k30Seconds
;
5755 case kNotifyCapabilityChangePriority
:
5756 applyToInterested( gIOPriorityPowerStateInterest
,
5757 pmTellCapabilityClientWithResponse
, (void *) &context
);
5761 // do we have to wait for somebody?
5762 if ( !checkForDone() )
5764 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5765 if (context
.enableTracing
)
5766 getPMRootDomain()->traceDetail( context
.maxTimeRequested
/ 1000 );
5767 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5772 // everybody responded
5775 fResponseArray
->release();
5776 fResponseArray
= NULL
;
5778 if (fNotifyClientArray
)
5780 fNotifyClientArray
->release();
5781 fNotifyClientArray
= NULL
;
5787 //*********************************************************************************
5788 // [static private] pmTellAppWithResponse
5790 // We send a message to an application, and we expect a response, so we compute a
5791 // cookie we can identify the response with.
5792 //*********************************************************************************
5794 void IOService::pmTellAppWithResponse( OSObject
* object
, void * arg
)
5796 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5797 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5798 uint32_t msgIndex
, msgRef
, msgType
;
5799 OSNumber
*clientID
= NULL
;
5801 boolean_t proc_suspended
= FALSE
;
5802 #if LOG_APP_RESPONSE_TIMES
5806 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5809 if (context
->us
== getPMRootDomain())
5811 if ((clientID
= copyClientIDForNotification(object
, context
)))
5813 uint32_t clientPID
= clientID
->unsigned32BitValue();
5814 clientID
->release();
5815 proc
= proc_find(clientPID
);
5819 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
5824 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
5831 if (context
->messageFilter
&&
5832 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5834 if (kIOLogDebugPower
& gIOKitDebug
)
5836 logClientIDForNotification(object
, context
, "DROP App");
5841 // Create client array (for tracking purposes) only if the service
5842 // has app clients. Usually only root domain does.
5843 if (0 == context
->notifyClients
)
5844 context
->notifyClients
= OSArray::withCapacity( 32 );
5846 msgType
= context
->messageType
;
5847 msgIndex
= context
->responseArray
->getCount();
5848 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5850 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
5851 if (kIOLogDebugPower
& gIOKitDebug
)
5853 logClientIDForNotification(object
, context
, "MESG App");
5856 #if LOG_APP_RESPONSE_TIMES
5858 clock_get_uptime(&now
);
5859 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
5862 context
->responseArray
->setObject(msgIndex
, num
);
5867 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
5869 if (context
->notifyClients
)
5870 context
->notifyClients
->setObject(msgIndex
, object
);
5872 context
->us
->messageClient(msgType
, object
, (void *)(uintptr_t) msgRef
);
5875 //*********************************************************************************
5876 // [static private] pmTellClientWithResponse
5878 // We send a message to an in-kernel client, and we expect a response,
5879 // so we compute a cookie we can identify the response with.
5880 //*********************************************************************************
5882 void IOService::pmTellClientWithResponse( OSObject
* object
, void * arg
)
5884 IOPowerStateChangeNotification notify
;
5885 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5886 OSObject
* replied
= kOSBooleanTrue
;
5887 _IOServiceInterestNotifier
* notifier
;
5888 uint32_t msgIndex
, msgRef
, msgType
;
5891 if (context
->messageFilter
&&
5892 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5894 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5895 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5897 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5898 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5899 context
->us
->getName(),
5900 getIOMessageString(context
->messageType
),
5901 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
5906 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5907 msgType
= context
->messageType
;
5908 msgIndex
= context
->responseArray
->getCount();
5909 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5911 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5912 if (gIOKitDebug
& kIOLogPower
) {
5913 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
5914 if (OSDynamicCast(IOService
, object
)) {
5915 const char *who
= ((IOService
*) object
)->getName();
5916 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
5918 else if (notifier
) {
5919 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
5922 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
5924 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5925 context
->us
->getName(),
5926 getIOMessageString(msgType
),
5927 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
5930 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
5931 notify
.returnValue
= 0;
5932 notify
.stateNumber
= context
->stateNumber
;
5933 notify
.stateFlags
= context
->stateFlags
;
5935 if (context
->enableTracing
&& (notifier
!= 0))
5937 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
5938 ((msgType
& 0xfff) << 12) |
5939 (((uintptr_t) notifier
->handler
) & 0xfff);
5940 getPMRootDomain()->traceDetail( detail
);
5943 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
5945 if (kIOReturnSuccess
== retCode
)
5947 if (0 == notify
.returnValue
) {
5948 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
5950 replied
= kOSBooleanFalse
;
5951 if ( notify
.returnValue
> context
->maxTimeRequested
)
5953 if (notify
.returnValue
> kPriorityClientMaxWait
)
5955 context
->maxTimeRequested
= kPriorityClientMaxWait
;
5956 PM_ERROR("%s: client %p returned %llu for %s\n",
5957 context
->us
->getName(),
5958 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
5959 (uint64_t) notify
.returnValue
,
5960 getIOMessageString(msgType
));
5963 context
->maxTimeRequested
= notify
.returnValue
;
5967 // not a client of ours
5968 // so we won't be waiting for response
5969 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
5972 context
->responseArray
->setObject(msgIndex
, replied
);
5975 //*********************************************************************************
5976 // [static private] pmTellCapabilityAppWithResponse
5977 //*********************************************************************************
5979 void IOService::pmTellCapabilityAppWithResponse( OSObject
* object
, void * arg
)
5981 IOPMSystemCapabilityChangeParameters msgArg
;
5982 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5983 OSObject
* replied
= kOSBooleanTrue
;
5984 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5985 uint32_t msgIndex
, msgRef
, msgType
;
5986 #if LOG_APP_RESPONSE_TIMES
5990 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5993 memset(&msgArg
, 0, sizeof(msgArg
));
5994 if (context
->messageFilter
&&
5995 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
))
6000 // Create client array (for tracking purposes) only if the service
6001 // has app clients. Usually only root domain does.
6002 if (0 == context
->notifyClients
)
6003 context
->notifyClients
= OSArray::withCapacity( 32 );
6005 msgType
= context
->messageType
;
6006 msgIndex
= context
->responseArray
->getCount();
6007 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6009 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6010 if (kIOLogDebugPower
& gIOKitDebug
)
6012 // Log client pid/name and client array index.
6013 OSNumber
* clientID
= NULL
;
6014 OSString
* clientIDString
= NULL
;;
6015 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6017 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6020 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
6021 context
->us
->getName(),
6022 msgIndex
, getIOMessageString(msgType
),
6023 (replied
!= kOSBooleanTrue
),
6024 clientIDString
? clientIDString
->getCStringNoCopy() : "");
6025 if (clientID
) clientID
->release();
6026 if (clientIDString
) clientIDString
->release();
6029 msgArg
.notifyRef
= msgRef
;
6030 msgArg
.maxWaitForReply
= 0;
6032 if (replied
== kOSBooleanTrue
)
6034 msgArg
.notifyRef
= 0;
6035 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6036 if (context
->notifyClients
)
6037 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
6041 #if LOG_APP_RESPONSE_TIMES
6043 clock_get_uptime(&now
);
6044 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6047 context
->responseArray
->setObject(msgIndex
, num
);
6052 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6054 if (context
->notifyClients
)
6055 context
->notifyClients
->setObject(msgIndex
, object
);
6058 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6061 //*********************************************************************************
6062 // [static private] pmTellCapabilityClientWithResponse
6063 //*********************************************************************************
6065 void IOService::pmTellCapabilityClientWithResponse(
6066 OSObject
* object
, void * arg
)
6068 IOPMSystemCapabilityChangeParameters msgArg
;
6069 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6070 OSObject
* replied
= kOSBooleanTrue
;
6071 _IOServiceInterestNotifier
* notifier
;
6072 uint32_t msgIndex
, msgRef
, msgType
;
6075 memset(&msgArg
, 0, sizeof(msgArg
));
6076 if (context
->messageFilter
&&
6077 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, 0))
6079 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6080 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6082 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6083 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6084 context
->us
->getName(),
6085 getIOMessageString(context
->messageType
),
6086 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6091 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6092 msgType
= context
->messageType
;
6093 msgIndex
= context
->responseArray
->getCount();
6094 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6096 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6097 if (gIOKitDebug
& kIOLogPower
) {
6098 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6099 if (OSDynamicCast(IOService
, object
)) {
6100 const char *who
= ((IOService
*) object
)->getName();
6101 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6103 else if (notifier
) {
6104 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6107 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6109 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6110 context
->us
->getName(),
6111 getIOMessageString(msgType
),
6112 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6115 msgArg
.notifyRef
= msgRef
;
6116 msgArg
.maxWaitForReply
= 0;
6118 if (context
->enableTracing
&& (notifier
!= 0))
6120 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
6121 ((msgType
& 0xfff) << 12) |
6122 (((uintptr_t) notifier
->handler
) & 0xfff);
6123 getPMRootDomain()->traceDetail( detail
);
6126 retCode
= context
->us
->messageClient(
6127 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6129 if ( kIOReturnSuccess
== retCode
)
6131 if ( 0 == msgArg
.maxWaitForReply
)
6133 // client doesn't want time to respond
6134 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6138 replied
= kOSBooleanFalse
;
6139 if ( msgArg
.maxWaitForReply
> context
->maxTimeRequested
)
6141 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
)
6143 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
6144 PM_ERROR("%s: client %p returned %u for %s\n",
6145 context
->us
->getName(),
6146 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6147 msgArg
.maxWaitForReply
,
6148 getIOMessageString(msgType
));
6151 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6157 // not a client of ours
6158 // so we won't be waiting for response
6159 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6162 context
->responseArray
->setObject(msgIndex
, replied
);
6165 //*********************************************************************************
6166 // [public] tellNoChangeDown
6168 // Notify registered applications and kernel clients that we are not
6171 // Subclass can override this to send a different message type. Parameter is
6172 // the aborted destination state number.
6173 //*********************************************************************************
6175 void IOService::tellNoChangeDown( unsigned long )
6177 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6180 //*********************************************************************************
6181 // [public] tellChangeUp
6183 // Notify registered applications and kernel clients that we are raising power.
6185 // Subclass can override this to send a different message type. Parameter is
6186 // the aborted destination state number.
6187 //*********************************************************************************
6189 void IOService::tellChangeUp( unsigned long )
6191 return tellClients( kIOMessageDeviceHasPoweredOn
);
6194 //*********************************************************************************
6195 // [protected] tellClients
6197 // Notify registered applications and kernel clients of something.
6198 //*********************************************************************************
6200 void IOService::tellClients( int messageType
)
6202 IOPMInterestContext context
;
6204 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6206 memset(&context
, 0, sizeof(context
));
6207 context
.messageType
= messageType
;
6208 context
.isPreChange
= fIsPreChange
;
6210 context
.stateNumber
= fHeadNotePowerState
;
6211 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6212 context
.changeFlags
= fHeadNoteChangeFlags
;
6213 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6214 OSMemberFunctionCast(
6217 &IOPMrootDomain::systemMessageFilter
) : 0;
6219 context
.notifyType
= kNotifyPriority
;
6220 applyToInterested( gIOPriorityPowerStateInterest
,
6221 tellKernelClientApplier
, (void *) &context
);
6223 context
.notifyType
= kNotifyApps
;
6224 applyToInterested( gIOAppPowerStateInterest
,
6225 tellAppClientApplier
, (void *) &context
);
6227 applyToInterested( gIOGeneralInterest
,
6228 tellKernelClientApplier
, (void *) &context
);
6231 //*********************************************************************************
6232 // [private] tellKernelClientApplier
6234 // Message a kernel client.
6235 //*********************************************************************************
6237 static void tellKernelClientApplier( OSObject
* object
, void * arg
)
6239 IOPowerStateChangeNotification notify
;
6240 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6242 if (context
->messageFilter
&&
6243 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6245 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6246 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6248 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6249 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6250 context
->us
->getName(),
6251 IOService::getIOMessageString(context
->messageType
),
6252 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6257 notify
.powerRef
= (void *) 0;
6258 notify
.returnValue
= 0;
6259 notify
.stateNumber
= context
->stateNumber
;
6260 notify
.stateFlags
= context
->stateFlags
;
6262 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6264 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6265 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6267 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6268 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6269 context
->us
->getName(),
6270 IOService::getIOMessageString(context
->messageType
),
6271 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6275 static OSNumber
* copyClientIDForNotification(
6277 IOPMInterestContext
*context
)
6279 OSNumber
*clientID
= NULL
;
6280 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6284 static void logClientIDForNotification(
6286 IOPMInterestContext
*context
,
6287 const char *logString
)
6289 OSString
*logClientID
= NULL
;
6290 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6295 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6297 PM_LOG("%s %s %s, %s\n",
6298 context
->us
->getName(), logString
,
6299 IOService::getIOMessageString(context
->messageType
),
6300 logClientID
? logClientID
->getCStringNoCopy() : "");
6303 logClientID
->release();
6307 clientID
->release();
6312 static void tellAppClientApplier( OSObject
* object
, void * arg
)
6314 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6315 OSNumber
* clientID
= NULL
;
6317 boolean_t proc_suspended
= FALSE
;
6319 if (context
->us
== IOService::getPMRootDomain())
6321 if ((clientID
= copyClientIDForNotification(object
, context
)))
6323 uint32_t clientPID
= clientID
->unsigned32BitValue();
6324 clientID
->release();
6325 proc
= proc_find(clientPID
);
6329 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6334 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6341 if (context
->messageFilter
&&
6342 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6344 if (kIOLogDebugPower
& gIOKitDebug
)
6346 logClientIDForNotification(object
, context
, "DROP App");
6351 if (kIOLogDebugPower
& gIOKitDebug
)
6353 logClientIDForNotification(object
, context
, "MESG App");
6356 context
->us
->messageClient(context
->messageType
, object
, 0);
6359 //*********************************************************************************
6360 // [private] checkForDone
6361 //*********************************************************************************
6363 bool IOService::checkForDone( void )
6368 if (fResponseArray
== NULL
) {
6372 for (i
= 0; ; i
++) {
6373 theFlag
= fResponseArray
->getObject(i
);
6375 if (NULL
== theFlag
) {
6379 if (kOSBooleanTrue
!= theFlag
) {
6386 //*********************************************************************************
6387 // [public] responseValid
6388 //*********************************************************************************
6390 bool IOService::responseValid( uint32_t refcon
, int pid
)
6392 UInt16 serialComponent
;
6393 UInt16 ordinalComponent
;
6396 serialComponent
= (refcon
>> 16) & 0xFFFF;
6397 ordinalComponent
= (refcon
& 0xFFFF);
6399 if ( serialComponent
!= fSerialNumber
)
6404 if ( fResponseArray
== NULL
)
6409 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6417 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
6419 #if LOG_APP_RESPONSE_TIMES
6426 proc_name(pid
, name
, sizeof(name
));
6427 clock_get_uptime(&now
);
6428 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6429 SUB_ABSOLUTETIME(&now
, &start
);
6430 absolutetime_to_nanoseconds(now
, &nsec
);
6432 PMEventDetails
*details
= PMEventDetails::eventDetails(
6433 kIOPMEventTypeAppResponse
, // type
6435 (uintptr_t)pid
, // owner unique
6436 NULL
, // interest name
6440 NS_TO_US(nsec
)); // usec completion time
6442 getPMRootDomain()->recordAndReleasePMEvent( details
);
6444 if (kIOLogDebugPower
& gIOKitDebug
)
6446 PM_LOG("Ack(%u) %u ms\n",
6447 (uint32_t) ordinalComponent
,
6452 if (nsec
> LOG_APP_RESPONSE_TIMES
)
6454 PM_LOG("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec
),
6457 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
6459 // TODO: populate the messageType argument
6460 getPMRootDomain()->pmStatsRecordApplicationResponse(
6461 gIOPMStatsApplicationResponseSlow
,
6462 name
, 0, NS_TO_MS(nsec
), pid
);
6467 theFlag
= kOSBooleanFalse
;
6470 if ( kOSBooleanFalse
== theFlag
)
6472 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6478 //*********************************************************************************
6479 // [public] allowPowerChange
6481 // Our power state is about to lower, and we have notified applications
6482 // and kernel clients, and one of them has acknowledged. If this is the last to do
6483 // so, and all acknowledgements are positive, we continue with the power change.
6484 //*********************************************************************************
6486 IOReturn
IOService::allowPowerChange( unsigned long refcon
)
6488 IOPMRequest
* request
;
6493 return kIOReturnSuccess
;
6496 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6498 return kIOReturnNoMemory
;
6500 request
->fArg0
= (void *) refcon
;
6501 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6502 request
->fArg2
= (void *) 0;
6503 submitPMRequest( request
);
6505 return kIOReturnSuccess
;
6509 IOReturn
IOService::serializedAllowPowerChange2( unsigned long refcon
)
6511 // [deprecated] public
6512 return kIOReturnUnsupported
;
6514 #endif /* !__LP64__ */
6516 //*********************************************************************************
6517 // [public] cancelPowerChange
6519 // Our power state is about to lower, and we have notified applications
6520 // and kernel clients, and one of them has vetoed the change. If this is the last
6521 // client to respond, we abandon the power change.
6522 //*********************************************************************************
6524 IOReturn
IOService::cancelPowerChange( unsigned long refcon
)
6526 IOPMRequest
* request
;
6528 pid_t pid
= proc_selfpid();
6533 return kIOReturnSuccess
;
6537 proc_name(pid
, name
, sizeof(name
));
6538 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid
, name
);
6540 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6543 return kIOReturnNoMemory
;
6546 request
->fArg0
= (void *) refcon
;
6547 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6548 request
->fArg2
= (void *) OSString::withCString(name
);
6549 submitPMRequest( request
);
6551 return kIOReturnSuccess
;
6555 IOReturn
IOService::serializedCancelPowerChange2( unsigned long refcon
)
6557 // [deprecated] public
6558 return kIOReturnUnsupported
;
6561 //*********************************************************************************
6562 // PM_Clamp_Timer_Expired
6564 // called when clamp timer expires...set power state to 0.
6565 //*********************************************************************************
6567 void IOService::PM_Clamp_Timer_Expired( void )
6571 //*********************************************************************************
6574 // Set to highest available power state for a minimum of duration milliseconds
6575 //*********************************************************************************
6577 void IOService::clampPowerOn( unsigned long duration
)
6580 #endif /* !__LP64__ */
6582 //*********************************************************************************
6583 // configurePowerStateReport
6585 // Configures the IOStateReport for kPMPowerStateChannel
6586 //*********************************************************************************
6587 IOReturn
IOService::configurePowerStatesReport( IOReportConfigureAction action
, void *result
)
6590 IOReturn rc
= kIOReturnSuccess
;
6596 return kIOReturnUnsupported
;
6598 if (!fNumberOfPowerStates
)
6599 return kIOReturnSuccess
; // For drivers which are in power plane, but haven't called registerPowerDriver()
6604 case kIOReportEnable
:
6610 reportSize
= STATEREPORT_BUFSIZE(fNumberOfPowerStates
);
6611 fReportBuf
= IOMalloc(reportSize
);
6613 rc
= kIOReturnNoMemory
;
6616 memset(fReportBuf
, 0, reportSize
);
6618 STATEREPORT_INIT(fNumberOfPowerStates
, fReportBuf
, reportSize
,
6619 getRegistryEntryID(), kPMPowerStatesChID
, kIOReportCategoryPower
);
6621 for (i
= 0; i
< fNumberOfPowerStates
; i
++) {
6624 if (fPowerStates
[i
].capabilityFlags
& kIOPMPowerOn
)
6625 bits
|= kPMReportPowerOn
;
6626 if (fPowerStates
[i
].capabilityFlags
& kIOPMDeviceUsable
)
6627 bits
|= kPMReportDeviceUsable
;
6628 if (fPowerStates
[i
].capabilityFlags
& kIOPMLowPower
)
6629 bits
|= kPMReportLowPower
;
6631 STATEREPORT_SETSTATEID(fReportBuf
, i
, ((bits
& 0xff) << 8) |
6632 ((StateOrder(fMaxPowerState
) & 0xf) << 4) | (StateOrder(i
) & 0xf));
6634 ts
= mach_absolute_time();
6635 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
6638 case kIOReportDisable
:
6639 if (fReportClientCnt
== 0) {
6640 rc
= kIOReturnBadArgument
;
6643 if (fReportClientCnt
== 1)
6645 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
6651 case kIOReportGetDimensions
:
6653 STATEREPORT_UPDATERES(fReportBuf
, kIOReportGetDimensions
, result
);
6662 //*********************************************************************************
6663 // updatePowerStateReport
6665 // Updates the IOStateReport for kPMPowerStateChannel
6666 //*********************************************************************************
6667 IOReturn
IOService::updatePowerStatesReport( IOReportConfigureAction action
, void *result
, void *destination
)
6672 IOReturn rc
= kIOReturnSuccess
;
6673 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6677 return kIOReturnUnsupported
;
6678 if (!fNumberOfPowerStates
)
6679 return kIOReturnSuccess
;
6681 if ( !result
|| !dest
) return kIOReturnBadArgument
;
6685 case kIOReportCopyChannelData
:
6686 if ( !fReportBuf
) {
6687 rc
= kIOReturnNotOpen
;
6691 ts
= mach_absolute_time();
6692 STATEREPORT_UPDATEPREP(fReportBuf
, ts
, data2cpy
, size2cpy
);
6693 if (size2cpy
> (dest
->getCapacity() - dest
->getLength()) ) {
6694 rc
= kIOReturnOverrun
;
6698 STATEREPORT_UPDATERES(fReportBuf
, kIOReportCopyChannelData
, result
);
6699 dest
->appendBytes(data2cpy
, size2cpy
);
6712 //*********************************************************************************
6713 // configureSimplePowerReport
6715 // Configures the IOSimpleReport for given channel id
6716 //*********************************************************************************
6717 IOReturn
IOService::configureSimplePowerReport(IOReportConfigureAction action
, void *result
)
6720 IOReturn rc
= kIOReturnSuccess
;
6723 return kIOReturnUnsupported
;
6725 if ( !fNumberOfPowerStates
)
6730 case kIOReportEnable
:
6731 case kIOReportDisable
:
6734 case kIOReportGetDimensions
:
6735 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
6743 //*********************************************************************************
6744 // updateSimplePowerReport
6746 // Updates the IOSimpleReport for the given chanel id
6747 //*********************************************************************************
6748 IOReturn
IOService::updateSimplePowerReport( IOReportConfigureAction action
, void *result
, void *destination
)
6752 uint64_t buf
[SIMPLEREPORT_BUFSIZE
/sizeof(uint64_t)+1]; // Force a 8-byte alignment
6753 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6754 IOReturn rc
= kIOReturnSuccess
;
6759 return kIOReturnUnsupported
;
6760 if ( !result
|| !dest
) return kIOReturnBadArgument
;
6762 if ( !fNumberOfPowerStates
)
6767 case kIOReportCopyChannelData
:
6769 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), kPMCurrStateChID
, kIOReportCategoryPower
);
6771 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMPowerOn
)
6772 bits
|= kPMReportPowerOn
;
6773 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMDeviceUsable
)
6774 bits
|= kPMReportDeviceUsable
;
6775 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMLowPower
)
6776 bits
|= kPMReportLowPower
;
6779 SIMPLEREPORT_SETVALUE(buf
, ((bits
& 0xff) << 8) | ((StateOrder(fMaxPowerState
) & 0xf) << 4) |
6780 (StateOrder(fCurrentPowerState
) & 0xf));
6782 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
6783 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
6784 rc
= kIOReturnOverrun
;
6788 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
6789 dest
->appendBytes(data2cpy
, size2cpy
);
6798 return kIOReturnSuccess
;
6805 // MARK: Driver Overrides
6807 //*********************************************************************************
6808 // [public] setPowerState
6810 // Does nothing here. This should be implemented in a subclass driver.
6811 //*********************************************************************************
6813 IOReturn
IOService::setPowerState(
6814 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
6819 //*********************************************************************************
6820 // [public] maxCapabilityForDomainState
6822 // Finds the highest power state in the array whose input power requirement
6823 // is equal to the input parameter. Where a more intelligent decision is
6824 // possible, override this in the subclassed driver.
6825 //*********************************************************************************
6827 IOPMPowerStateIndex
IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags
)
6829 IOPMPowerStateIndex stateIndex
;
6831 if (!fNumberOfPowerStates
)
6832 return kPowerStateZero
;
6834 for ( int order
= fNumberOfPowerStates
- 1; order
>= 0; order
-- )
6836 stateIndex
= fPowerStates
[order
].stateOrderToIndex
;
6838 if ( (flags
& fPowerStates
[stateIndex
].inputPowerFlags
) ==
6839 fPowerStates
[stateIndex
].inputPowerFlags
)
6844 return kPowerStateZero
;
6847 unsigned long IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState
)
6849 return getPowerStateForDomainFlags(domainState
);
6852 //*********************************************************************************
6853 // [public] initialPowerStateForDomainState
6855 // Called to query the power state for the initial power transition.
6856 //*********************************************************************************
6858 unsigned long IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState
)
6860 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
))
6862 // Return lowest power state for any root power domain changes
6863 return kPowerStateZero
;
6866 return getPowerStateForDomainFlags(domainState
);
6869 //*********************************************************************************
6870 // [public] powerStateForDomainState
6872 // This method is not called from PM.
6873 //*********************************************************************************
6875 unsigned long IOService::powerStateForDomainState( IOPMPowerFlags domainState
)
6877 return getPowerStateForDomainFlags(domainState
);
6881 //*********************************************************************************
6882 // [deprecated] didYouWakeSystem
6884 // Does nothing here. This should be implemented in a subclass driver.
6885 //*********************************************************************************
6887 bool IOService::didYouWakeSystem( void )
6891 #endif /* !__LP64__ */
6893 //*********************************************************************************
6894 // [public] powerStateWillChangeTo
6896 // Does nothing here. This should be implemented in a subclass driver.
6897 //*********************************************************************************
6899 IOReturn
IOService::powerStateWillChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
6901 return kIOPMAckImplied
;
6904 //*********************************************************************************
6905 // [public] powerStateDidChangeTo
6907 // Does nothing here. This should be implemented in a subclass driver.
6908 //*********************************************************************************
6910 IOReturn
IOService::powerStateDidChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
6912 return kIOPMAckImplied
;
6915 //*********************************************************************************
6916 // [protected] powerChangeDone
6918 // Called from PM work loop thread.
6919 // Does nothing here. This should be implemented in a subclass policy-maker.
6920 //*********************************************************************************
6922 void IOService::powerChangeDone( unsigned long )
6927 //*********************************************************************************
6928 // [deprecated] newTemperature
6930 // Does nothing here. This should be implemented in a subclass driver.
6931 //*********************************************************************************
6933 IOReturn
IOService::newTemperature( long currentTemp
, IOService
* whichZone
)
6937 #endif /* !__LP64__ */
6939 //*********************************************************************************
6940 // [public] systemWillShutdown
6942 // System shutdown and restart notification.
6943 //*********************************************************************************
6945 void IOService::systemWillShutdown( IOOptionBits specifier
)
6947 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
6949 rootDomain
->acknowledgeSystemWillShutdown( this );
6953 // MARK: PM State Machine
6955 //*********************************************************************************
6956 // [private static] acquirePMRequest
6957 //*********************************************************************************
6960 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
6961 IOPMRequest
* active
)
6963 IOPMRequest
* request
;
6967 request
= IOPMRequest::create();
6970 request
->init( target
, requestType
);
6973 IOPMRequest
* root
= active
->getRootRequest();
6974 if (root
) request
->attachRootRequest(root
);
6979 PM_ERROR("%s: No memory for PM request type 0x%x\n",
6980 target
->getName(), (uint32_t) requestType
);
6985 //*********************************************************************************
6986 // [private static] releasePMRequest
6987 //*********************************************************************************
6989 void IOService::releasePMRequest( IOPMRequest
* request
)
6998 //*********************************************************************************
6999 // [private] submitPMRequest
7000 //*********************************************************************************
7002 void IOService::submitPMRequest( IOPMRequest
* request
)
7005 assert( gIOPMReplyQueue
);
7006 assert( gIOPMRequestQueue
);
7008 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7009 (long)request
->getType(), OBFUSCATE(request
),
7010 OBFUSCATE(request
->getTarget()), request
->getTarget()->getName(),
7011 OBFUSCATE(request
->fArg0
),
7012 OBFUSCATE(request
->fArg1
), OBFUSCATE(request
->fArg2
));
7014 if (request
->isReplyType())
7015 gIOPMReplyQueue
->queuePMRequest( request
);
7017 gIOPMRequestQueue
->queuePMRequest( request
);
7020 void IOService::submitPMRequest( IOPMRequest
** requests
, IOItemCount count
)
7023 assert( count
> 0 );
7024 assert( gIOPMRequestQueue
);
7026 for (IOItemCount i
= 0; i
< count
; i
++)
7028 IOPMRequest
* req
= requests
[i
];
7029 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7030 (long)req
->getType(), OBFUSCATE(req
),
7031 OBFUSCATE(req
->getTarget()), req
->getTarget()->getName(),
7032 OBFUSCATE(req
->fArg0
),
7033 OBFUSCATE(req
->fArg1
), OBFUSCATE(req
->fArg2
));
7036 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
7039 //*********************************************************************************
7040 // [private] servicePMRequestQueue
7042 // Called from IOPMRequestQueue::checkForWork().
7043 //*********************************************************************************
7045 bool IOService::servicePMRequestQueue(
7046 IOPMRequest
* request
,
7047 IOPMRequestQueue
* queue
)
7053 // Work queue will immediately execute the queue'd request if possible.
7054 // If execution blocks, the work queue will wait for a producer signal.
7055 // Only need to signal more when completing attached requests.
7057 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
7061 // Calling PM without PMinit() is not allowed, fail the request.
7063 PM_LOG("%s: PM not initialized\n", getName());
7064 fAdjustPowerScheduled
= false;
7065 more
= gIOPMFreeQueue
->queuePMRequest(request
);
7066 if (more
) gIOPMWorkQueue
->incrementProducerCount();
7070 //*********************************************************************************
7071 // [private] servicePMFreeQueue
7073 // Called from IOPMCompletionQueue::checkForWork().
7074 //*********************************************************************************
7076 bool IOService::servicePMFreeQueue(
7077 IOPMRequest
* request
,
7078 IOPMCompletionQueue
* queue
)
7080 bool more
= request
->getNextRequest();
7081 IOPMRequest
* root
= request
->getRootRequest();
7083 if (root
&& (root
!= request
))
7086 gIOPMWorkQueue
->incrementProducerCount();
7088 releasePMRequest( request
);
7092 //*********************************************************************************
7093 // [private] retirePMRequest
7095 // Called by IOPMWorkQueue to retire a completed request.
7096 //*********************************************************************************
7098 bool IOService::retirePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7100 assert(request
&& queue
);
7102 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7103 request
->getType(), OBFUSCATE(request
),
7104 OBFUSCATE(this), getName(),
7105 fMachineState
, gIOPMBusyCount
);
7107 // Catch requests created by idleTimerExpired().
7109 if ((request
->getType() == kIOPMRequestTypeActivityTickle
) &&
7110 (((uintptr_t) request
->fArg1
) & kTickleTypePowerDrop
) &&
7116 // If the request is linked, then Work queue has already incremented its
7119 return (gIOPMFreeQueue
->queuePMRequest( request
));
7122 //*********************************************************************************
7123 // [private] isPMBlocked
7125 // Check if machine state transition is blocked.
7126 //*********************************************************************************
7128 bool IOService::isPMBlocked( IOPMRequest
* request
, int count
)
7133 if (kIOPM_Finished
== fMachineState
)
7136 if (kIOPM_DriverThreadCallDone
== fMachineState
)
7138 // 5 = kDriverCallInformPreChange
7139 // 6 = kDriverCallInformPostChange
7140 // 7 = kDriverCallSetPowerState
7141 // 8 = kRootDomainInformPreChange
7142 if (fDriverCallBusy
)
7143 reason
= 5 + fDriverCallReason
;
7147 // Waiting on driver's setPowerState() timeout.
7153 // Child or interested driver acks pending.
7154 if (fHeadNotePendingAcks
)
7159 // Waiting on apps or priority power interest clients.
7165 // Waiting on settle timer expiration.
7172 fWaitReason
= reason
;
7178 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7179 request
->getType(), OBFUSCATE(request
),
7180 OBFUSCATE(this), getName(),
7181 fMachineState
, reason
);
7190 //*********************************************************************************
7191 // [private] servicePMRequest
7193 // Service a request from our work queue.
7194 //*********************************************************************************
7196 bool IOService::servicePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7201 assert(request
&& queue
);
7203 while (isPMBlocked(request
, loop
++) == false)
7205 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7206 request
->getType(), OBFUSCATE(request
),
7207 OBFUSCATE(this), getName(), fMachineState
);
7209 gIOPMRequest
= request
;
7212 // Every PM machine states must be handled in one of the cases below.
7214 switch ( fMachineState
)
7216 case kIOPM_Finished
:
7217 start_watchdog_timer();
7219 executePMRequest( request
);
7222 case kIOPM_OurChangeTellClientsPowerDown
:
7223 // Root domain might self cancel due to assertions.
7226 bool cancel
= (bool) fDoNotPowerDown
;
7227 getPMRootDomain()->askChangeDownDone(
7228 &fHeadNoteChangeFlags
, &cancel
);
7229 fDoNotPowerDown
= cancel
;
7232 // askChangeDown() done, was it vetoed?
7233 if (!fDoNotPowerDown
)
7235 if (IS_ROOT_DOMAIN
) {
7236 PMEventDetails
*details
= PMEventDetails::eventDetails(
7237 kIOPMEventTypeAppNotificationsFinished
,
7242 getPMRootDomain()->recordAndReleasePMEvent( details
);
7245 // no, we can continue
7246 OurChangeTellClientsPowerDown();
7250 if (IS_ROOT_DOMAIN
) {
7251 PMEventDetails
*details
= PMEventDetails::eventDetails(
7252 kIOPMEventTypeSleepDone
,
7254 1, /* reason: 1 == Ask clients succeeded */
7255 kIOReturnAborted
); /* result */
7257 getPMRootDomain()->recordAndReleasePMEvent( details
);
7260 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7261 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7262 // yes, rescind the warning
7263 tellNoChangeDown(fHeadNotePowerState
);
7264 // mark the change note un-actioned
7265 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7271 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
7272 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7273 if (fDoNotPowerDown
)
7275 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7276 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7277 // yes, rescind the warning
7278 tellNoChangeDown(fHeadNotePowerState
);
7279 // mark the change note un-actioned
7280 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7285 OurChangeTellUserPMPolicyPowerDown();
7288 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
7289 // PMRD: LastCallBeforeSleep notify done
7290 // Non-PMRD: tellChangeDown/kNotifyApps done
7291 if (fDoNotPowerDown
)
7293 if (IS_ROOT_DOMAIN
) {
7294 PMEventDetails
*details
= PMEventDetails::eventDetails(
7295 kIOPMEventTypeSleepDone
,
7297 2, /* reason: 2 == Client cancelled wake */
7298 kIOReturnAborted
); /* result */
7300 getPMRootDomain()->recordAndReleasePMEvent( details
);
7302 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7303 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7304 // no, tell clients we're back in the old state
7305 tellChangeUp(fCurrentPowerState
);
7306 // mark the change note un-actioned
7307 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7313 if (IS_ROOT_DOMAIN
) {
7314 PMEventDetails
*details
= PMEventDetails::eventDetails(
7315 kIOPMEventTypeAppNotificationsFinished
,
7317 2, /* reason: 2 == TellPriorityClientsDone */
7318 kIOReturnSuccess
); /* result */
7320 getPMRootDomain()->recordAndReleasePMEvent( details
);
7322 // yes, we can continue
7323 OurChangeTellPriorityClientsPowerDown();
7327 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
7328 OurChangeNotifyInterestedDriversWillChange();
7331 case kIOPM_OurChangeSetPowerState
:
7332 OurChangeSetPowerState();
7335 case kIOPM_OurChangeWaitForPowerSettle
:
7336 OurChangeWaitForPowerSettle();
7339 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
7340 OurChangeNotifyInterestedDriversDidChange();
7343 case kIOPM_OurChangeTellCapabilityDidChange
:
7344 OurChangeTellCapabilityDidChange();
7347 case kIOPM_OurChangeFinish
:
7351 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
7352 ParentChangeTellPriorityClientsPowerDown();
7355 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
7356 ParentChangeNotifyInterestedDriversWillChange();
7359 case kIOPM_ParentChangeSetPowerState
:
7360 ParentChangeSetPowerState();
7363 case kIOPM_ParentChangeWaitForPowerSettle
:
7364 ParentChangeWaitForPowerSettle();
7367 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7368 ParentChangeNotifyInterestedDriversDidChange();
7371 case kIOPM_ParentChangeTellCapabilityDidChange
:
7372 ParentChangeTellCapabilityDidChange();
7375 case kIOPM_ParentChangeAcknowledgePowerChange
:
7376 ParentChangeAcknowledgePowerChange();
7379 case kIOPM_DriverThreadCallDone
:
7380 switch (fDriverCallReason
)
7382 case kDriverCallInformPreChange
:
7383 case kDriverCallInformPostChange
:
7384 notifyInterestedDriversDone();
7386 case kDriverCallSetPowerState
:
7387 notifyControllingDriverDone();
7389 case kRootDomainInformPreChange
:
7390 notifyRootDomainDone();
7393 panic("%s: bad call reason %x",
7394 getName(), fDriverCallReason
);
7398 case kIOPM_NotifyChildrenOrdered
:
7399 notifyChildrenOrdered();
7402 case kIOPM_NotifyChildrenDelayed
:
7403 notifyChildrenDelayed();
7406 case kIOPM_NotifyChildrenStart
:
7407 // pop notifyAll() state saved by notifyInterestedDriversDone()
7412 case kIOPM_SyncTellClientsPowerDown
:
7413 // Root domain might self cancel due to assertions.
7416 bool cancel
= (bool) fDoNotPowerDown
;
7417 getPMRootDomain()->askChangeDownDone(
7418 &fHeadNoteChangeFlags
, &cancel
);
7419 fDoNotPowerDown
= cancel
;
7421 if (!fDoNotPowerDown
)
7423 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7424 fOutOfBandParameter
= kNotifyApps
;
7425 tellChangeDown(fHeadNotePowerState
);
7429 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7430 // askChangeDown/kNotifyApps
7431 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7432 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7433 tellNoChangeDown(fHeadNotePowerState
);
7434 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7439 case kIOPM_SyncTellPriorityClientsPowerDown
:
7440 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7441 if (!fDoNotPowerDown
)
7443 fMachineState
= kIOPM_SyncNotifyWillChange
;
7444 fOutOfBandParameter
= kNotifyPriority
;
7445 tellChangeDown(fHeadNotePowerState
);
7449 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7450 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7451 tellChangeUp(fCurrentPowerState
);
7452 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7457 case kIOPM_SyncNotifyWillChange
:
7458 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
)
7460 fMachineState
= kIOPM_SyncFinish
;
7463 fMachineState
= kIOPM_SyncNotifyDidChange
;
7464 fDriverCallReason
= kDriverCallInformPreChange
;
7468 case kIOPM_SyncNotifyDidChange
:
7469 fIsPreChange
= false;
7471 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7473 fMachineState
= kIOPM_SyncFinish
;
7477 assert(IS_ROOT_DOMAIN
);
7478 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7481 fDriverCallReason
= kDriverCallInformPostChange
;
7485 case kIOPM_SyncTellCapabilityDidChange
:
7486 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7489 case kIOPM_SyncFinish
:
7490 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7491 ParentChangeAcknowledgePowerChange();
7496 case kIOPM_TellCapabilityChangeDone
:
7499 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
)
7501 MS_POP(); // tellSystemCapabilityChange()
7504 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7508 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
)
7510 MS_POP(); // tellSystemCapabilityChange()
7513 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7515 tellClientsWithResponse( fOutOfBandMessage
);
7519 panic("servicePMWorkQueue: unknown machine state %x",
7525 if (fMachineState
== kIOPM_Finished
)
7527 stop_watchdog_timer();
7536 //*********************************************************************************
7537 // [private] executePMRequest
7538 //*********************************************************************************
7540 void IOService::executePMRequest( IOPMRequest
* request
)
7542 assert( kIOPM_Finished
== fMachineState
);
7544 switch (request
->getType())
7546 case kIOPMRequestTypePMStop
:
7547 handlePMstop( request
);
7550 case kIOPMRequestTypeAddPowerChild1
:
7551 addPowerChild1( request
);
7554 case kIOPMRequestTypeAddPowerChild2
:
7555 addPowerChild2( request
);
7558 case kIOPMRequestTypeAddPowerChild3
:
7559 addPowerChild3( request
);
7562 case kIOPMRequestTypeRegisterPowerDriver
:
7563 handleRegisterPowerDriver( request
);
7566 case kIOPMRequestTypeAdjustPowerState
:
7567 fAdjustPowerScheduled
= false;
7571 case kIOPMRequestTypePowerDomainWillChange
:
7572 handlePowerDomainWillChangeTo( request
);
7575 case kIOPMRequestTypePowerDomainDidChange
:
7576 handlePowerDomainDidChangeTo( request
);
7579 case kIOPMRequestTypeRequestPowerState
:
7580 case kIOPMRequestTypeRequestPowerStateOverride
:
7581 handleRequestPowerState( request
);
7584 case kIOPMRequestTypePowerOverrideOnPriv
:
7585 case kIOPMRequestTypePowerOverrideOffPriv
:
7586 handlePowerOverrideChanged( request
);
7589 case kIOPMRequestTypeActivityTickle
:
7590 handleActivityTickle( request
);
7593 case kIOPMRequestTypeSynchronizePowerTree
:
7594 handleSynchronizePowerTree( request
);
7597 case kIOPMRequestTypeSetIdleTimerPeriod
:
7599 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7600 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
7605 case kIOPMRequestTypeIgnoreIdleTimer
:
7606 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7610 panic("executePMRequest: unknown request type %x", request
->getType());
7614 //*********************************************************************************
7615 // [private] servicePMReplyQueue
7616 //*********************************************************************************
7618 bool IOService::servicePMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7622 assert( request
&& queue
);
7623 assert( request
->isReplyType() );
7625 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7626 request
->getType(), OBFUSCATE(request
),
7627 OBFUSCATE(this), getName(), fMachineState
);
7629 switch ( request
->getType() )
7631 case kIOPMRequestTypeAllowPowerChange
:
7632 case kIOPMRequestTypeCancelPowerChange
:
7633 // Check if we are expecting this response.
7634 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7635 (int)(uintptr_t) request
->fArg1
))
7637 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
7639 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7640 // flag is set. Only root domain will set this flag.
7641 // However, there is one exception to this rule. User-space PM
7642 // policy may choose to cancel sleep even after all clients have
7643 // been notified that we will lower power.
7645 if ((fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7646 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7647 || ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0))
7649 fDoNotPowerDown
= true;
7651 OSString
* name
= (OSString
*) request
->fArg2
;
7652 getPMRootDomain()->pmStatsRecordApplicationResponse(
7653 gIOPMStatsApplicationResponseCancel
,
7654 name
? name
->getCStringNoCopy() : "", 0,
7655 0, (int)(uintptr_t) request
->fArg1
);
7662 cleanClientResponses(false);
7666 // OSString containing app name in Arg2 must be released.
7667 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
7669 OSObject
* obj
= (OSObject
*) request
->fArg2
;
7670 if (obj
) obj
->release();
7674 case kIOPMRequestTypeAckPowerChange
:
7675 more
= handleAcknowledgePowerChange( request
);
7678 case kIOPMRequestTypeAckSetPowerState
:
7679 if (fDriverTimer
== -1)
7681 // driver acked while setPowerState() call is in-flight.
7682 // take this ack, return value from setPowerState() is irrelevant.
7683 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
7684 (uintptr_t) this, fDriverTimer
);
7687 else if (fDriverTimer
> 0)
7689 // expected ack, stop the timer
7692 #if LOG_SETPOWER_TIMES
7693 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
7694 if (nsec
> LOG_SETPOWER_TIMES
)
7695 PM_LOG("%s::setPowerState(%p, %lu -> %lu) async took %d ms\n",
7696 fName
, OBFUSCATE(this), fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
7698 PMEventDetails
*details
= PMEventDetails::eventDetails(
7699 kIOPMEventTypeSetPowerStateDelayed
, // type
7701 (uintptr_t)this, // owner unique
7702 NULL
, // interest name
7703 (uint8_t)getPowerState(), // old
7704 (uint8_t)fHeadNotePowerState
, // new
7706 NS_TO_US(nsec
)); // usec completion time
7708 getPMRootDomain()->recordAndReleasePMEvent( details
);
7710 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
7717 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
7721 case kIOPMRequestTypeInterestChanged
:
7722 handleInterestChanged( request
);
7726 case kIOPMRequestTypeIdleCancel
:
7727 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
7728 || (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7729 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7730 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
7731 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
7733 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7734 PM_LOG2("%s: cancel from machine state %d\n",
7735 getName(), fMachineState
);
7736 fDoNotPowerDown
= true;
7737 // Stop waiting for app replys.
7738 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
7739 (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
) ||
7740 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
7741 cleanClientResponses(false);
7746 case kIOPMRequestTypeChildNotifyDelayCancel
:
7747 if (fMachineState
== kIOPM_NotifyChildrenDelayed
)
7749 PM_LOG2("%s: delay notify cancelled\n", getName());
7750 notifyChildrenDelayed();
7755 panic("servicePMReplyQueue: unknown reply type %x",
7756 request
->getType());
7759 more
|= gIOPMFreeQueue
->queuePMRequest(request
);
7761 gIOPMWorkQueue
->incrementProducerCount();
7766 //*********************************************************************************
7767 // [private] assertPMDriverCall / deassertPMDriverCall
7768 //*********************************************************************************
7770 bool IOService::assertPMDriverCall(
7771 IOPMDriverCallEntry
* entry
,
7772 IOOptionBits options
,
7773 IOPMinformee
* inform
)
7775 IOService
* target
= 0;
7783 if (fLockedFlags
.PMStop
)
7788 if (((options
& kIOPMADC_NoInactiveCheck
) == 0) && isInactive())
7795 if (!inform
->active
)
7799 target
= inform
->whatObject
;
7800 if (target
->isInactive())
7806 entry
->thread
= current_thread();
7807 entry
->target
= target
;
7808 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7817 void IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
7819 bool wakeup
= false;
7823 assert( !queue_empty(&fPMDriverCallQueue
) );
7824 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7825 if (fLockedFlags
.PMDriverCallWait
)
7833 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
7836 void IOService::waitForPMDriverCall( IOService
* target
)
7838 const IOPMDriverCallEntry
* entry
;
7839 thread_t thread
= current_thread();
7840 AbsoluteTime deadline
;
7847 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
7849 // Target of interested driver call
7850 if (target
&& (target
!= entry
->target
))
7853 if (entry
->thread
== thread
)
7857 PM_LOG("%s: %s(%s) on PM thread\n",
7858 fName
, __FUNCTION__
, target
? target
->getName() : "");
7859 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
7860 fName
, __FUNCTION__
, target
? target
->getName() : "");
7872 fLockedFlags
.PMDriverCallWait
= true;
7873 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
7874 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
7875 fLockedFlags
.PMDriverCallWait
= false;
7876 if (THREAD_TIMED_OUT
== waitResult
)
7878 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
7885 //*********************************************************************************
7886 // [private] Debug helpers
7887 //*********************************************************************************
7889 const char * IOService::getIOMessageString( uint32_t msg
)
7891 #define MSG_ENTRY(x) {(int) x, #x}
7893 static const IONamedValue msgNames
[] = {
7894 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
7895 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
7896 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
7897 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
7898 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
7899 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
7900 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
7901 MSG_ENTRY( kIOMessageCanSystemSleep
),
7902 MSG_ENTRY( kIOMessageSystemWillSleep
),
7903 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
7904 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
7905 MSG_ENTRY( kIOMessageSystemWillRestart
),
7906 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
7907 MSG_ENTRY( kIOMessageSystemCapabilityChange
),
7908 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep
)
7911 return IOFindNameForValue(msg
, msgNames
);
7916 // MARK: IOPMRequest
7918 //*********************************************************************************
7919 // IOPMRequest Class
7921 // Requests from PM clients, and also used for inter-object messaging within PM.
7922 //*********************************************************************************
7924 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
7926 IOPMRequest
* IOPMRequest::create( void )
7928 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
7929 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
7937 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
7939 if (!IOCommand::init())
7945 fCompletionStatus
= kIOReturnSuccess
;
7954 void IOPMRequest::reset( void )
7956 assert( fWorkWaitCount
== 0 );
7957 assert( fFreeWaitCount
== 0 );
7959 detachNextRequest();
7960 detachRootRequest();
7962 fType
= kIOPMRequestTypeInvalid
;
7965 if (fCompletionAction
)
7967 fCompletionAction(fCompletionTarget
, fCompletionParam
, fCompletionStatus
);
7978 bool IOPMRequest::attachNextRequest( IOPMRequest
* next
)
7984 // Postpone the execution of the next request after
7986 fRequestNext
= next
;
7987 fRequestNext
->fWorkWaitCount
++;
7988 #if LOG_REQUEST_ATTACH
7989 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7990 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestNext
),
7991 (uint32_t) fRequestNext
->fType
,
7992 (uint32_t) fRequestNext
->fWorkWaitCount
,
7993 fTarget
->getName());
8000 bool IOPMRequest::detachNextRequest( void )
8006 assert(fRequestNext
->fWorkWaitCount
);
8007 if (fRequestNext
->fWorkWaitCount
)
8008 fRequestNext
->fWorkWaitCount
--;
8009 #if LOG_REQUEST_ATTACH
8010 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8011 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestNext
),
8012 (uint32_t) fRequestNext
->fType
,
8013 (uint32_t) fRequestNext
->fWorkWaitCount
,
8014 fTarget
->getName());
8022 bool IOPMRequest::attachRootRequest( IOPMRequest
* root
)
8028 // Delay the completion of the root request after
8030 fRequestRoot
= root
;
8031 fRequestRoot
->fFreeWaitCount
++;
8032 #if LOG_REQUEST_ATTACH
8033 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8034 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8035 (uint32_t) fRequestRoot
->fType
,
8036 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8037 fTarget
->getName());
8044 bool IOPMRequest::detachRootRequest( void )
8050 assert(fRequestRoot
->fFreeWaitCount
);
8051 if (fRequestRoot
->fFreeWaitCount
)
8052 fRequestRoot
->fFreeWaitCount
--;
8053 #if LOG_REQUEST_ATTACH
8054 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8055 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8056 (uint32_t) fRequestRoot
->fType
,
8057 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8058 fTarget
->getName());
8067 // MARK: IOPMRequestQueue
8069 //*********************************************************************************
8070 // IOPMRequestQueue Class
8072 // Global queues. Queues are created once and never released.
8073 //*********************************************************************************
8075 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
8077 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
8079 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
8080 if (me
&& !me
->init(inOwner
, inAction
))
8088 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
8090 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8093 queue_init(&fQueue
);
8094 fLock
= IOLockAlloc();
8095 return (fLock
!= 0);
8098 void IOPMRequestQueue::free( void )
8105 return IOEventSource::free();
8108 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
8112 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
8113 IOLockUnlock(fLock
);
8114 if (workLoop
) signalWorkAvailable();
8118 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
8122 assert(requests
&& count
);
8128 queue_enter(&fQueue
, next
, IOPMRequest
*, fCommandChain
);
8130 IOLockUnlock(fLock
);
8131 if (workLoop
) signalWorkAvailable();
8134 bool IOPMRequestQueue::checkForWork( void )
8136 Action dqAction
= (Action
) action
;
8137 IOPMRequest
* request
;
8141 IOLockLock( fLock
);
8143 while (!queue_empty(&fQueue
))
8145 queue_remove_first( &fQueue
, request
, IOPMRequest
*, fCommandChain
);
8146 IOLockUnlock( fLock
);
8147 target
= request
->getTarget();
8149 more
|= (*dqAction
)( target
, request
, this );
8150 IOLockLock( fLock
);
8153 IOLockUnlock( fLock
);
8158 // MARK: IOPMWorkQueue
8160 //*********************************************************************************
8161 // IOPMWorkQueue Class
8163 // Queue of IOServicePM objects with busy IOPMRequest(s).
8164 //*********************************************************************************
8166 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
8169 IOPMWorkQueue::create( IOService
* inOwner
, Action work
, Action retire
)
8171 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
8172 if (me
&& !me
->init(inOwner
, work
, retire
))
8180 bool IOPMWorkQueue::init( IOService
* inOwner
, Action work
, Action retire
)
8182 if (!work
|| !retire
||
8183 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
8186 queue_init(&fWorkQueue
);
8189 fRetireAction
= retire
;
8190 fConsumerCount
= fProducerCount
= 0;
8195 bool IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
8202 assert( onThread() );
8203 assert( queue_next(&request
->fCommandChain
) ==
8204 queue_prev(&request
->fCommandChain
) );
8208 // Add new request to the tail of the per-service request queue.
8209 // Then immediately check the request queue to minimize latency
8210 // if the queue was empty.
8212 empty
= queue_empty(&pwrMgt
->RequestHead
);
8213 queue_enter(&pwrMgt
->RequestHead
, request
, IOPMRequest
*, fCommandChain
);
8216 more
= checkRequestQueue(&pwrMgt
->RequestHead
, &empty
);
8219 // New Request is blocked, add IOServicePM to work queue.
8220 assert( queue_next(&pwrMgt
->WorkChain
) ==
8221 queue_prev(&pwrMgt
->WorkChain
) );
8223 queue_enter(&fWorkQueue
, pwrMgt
, IOServicePM
*, WorkChain
);
8225 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8226 fQueueLength
, pwrMgt
->Name
, OBFUSCATE(pwrMgt
));
8233 bool IOPMWorkQueue::checkRequestQueue( queue_head_t
* queue
, bool * empty
)
8235 IOPMRequest
* request
;
8240 assert(!queue_empty(queue
));
8242 request
= (IOPMRequest
*) queue_first(queue
);
8243 if (request
->isWorkBlocked())
8244 break; // cannot start, blocked on attached request
8246 target
= request
->getTarget();
8247 done
= (*fWorkAction
)( target
, request
, this );
8249 break; // work started, blocked on PM state machine
8251 assert(gIOPMBusyCount
> 0);
8255 queue_remove_first(queue
, request
, IOPMRequest
*, fCommandChain
);
8256 more
|= (*fRetireAction
)( target
, request
, this );
8257 done
= queue_empty(queue
);
8264 // Retired request blocks another request, since the
8265 // blocked request may reside in the work queue, we
8266 // must bump the producer count to avoid work stall.
8273 bool IOPMWorkQueue::checkForWork( void )
8275 IOServicePM
* entry
;
8280 #if WORK_QUEUE_STATS
8281 fStatCheckForWork
++;
8284 // Each producer signal triggers a full iteration over
8285 // all IOServicePM entries in the work queue.
8287 while (fConsumerCount
!= fProducerCount
)
8289 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8290 fProducerCount
, fConsumerCount
);
8292 fConsumerCount
= fProducerCount
;
8294 #if WORK_QUEUE_STATS
8295 if (queue_empty(&fWorkQueue
))
8301 uint32_t cachedWorkCount
= gIOPMWorkCount
;
8304 entry
= (IOServicePM
*) queue_first(&fWorkQueue
);
8305 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
))
8307 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
8309 // Get next entry, points to head if current entry is last.
8310 next
= (IOServicePM
*) queue_next(&entry
->WorkChain
);
8312 // if request queue is empty, remove IOServicePM from queue.
8315 assert(fQueueLength
);
8316 if (fQueueLength
) fQueueLength
--;
8317 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8318 fQueueLength
, entry
->Name
, OBFUSCATE(entry
));
8319 queue_remove(&fWorkQueue
, entry
, IOServicePM
*, WorkChain
);
8324 #if WORK_QUEUE_STATS
8325 if (cachedWorkCount
== gIOPMWorkCount
)
8333 void IOPMWorkQueue::signalWorkAvailable( void )
8336 IOEventSource::signalWorkAvailable();
8339 void IOPMWorkQueue::incrementProducerCount( void )
8345 // MARK: IOPMCompletionQueue
8347 //*********************************************************************************
8348 // IOPMCompletionQueue Class
8349 //*********************************************************************************
8351 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
8353 IOPMCompletionQueue
*
8354 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
8356 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
8357 if (me
&& !me
->init(inOwner
, inAction
))
8365 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
8367 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8370 queue_init(&fQueue
);
8374 bool IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
8379 // unblock dependent request
8380 more
= request
->detachNextRequest();
8381 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
8385 bool IOPMCompletionQueue::checkForWork( void )
8387 Action dqAction
= (Action
) action
;
8388 IOPMRequest
* request
;
8393 request
= (IOPMRequest
*) queue_first(&fQueue
);
8394 while (!queue_end(&fQueue
, (queue_entry_t
) request
))
8396 next
= (IOPMRequest
*) queue_next(&request
->fCommandChain
);
8397 if (!request
->isFreeBlocked())
8399 queue_remove(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
8400 target
= request
->getTarget();
8402 more
|= (*dqAction
)( target
, request
, this );
8411 // MARK: IOServicePM
8413 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8415 //*********************************************************************************
8418 // Serialize IOServicePM for debugging.
8419 //*********************************************************************************
8422 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8424 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8427 dict
->setObject(key
, num
);
8432 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
) const
8434 OSDictionary
* dict
;
8436 int powerClamp
= -1;
8439 if (IdleTimerPeriod
)
8442 if (PMActions
.parameter
& kPMActionsFlagLimitPower
)
8446 if (PMActions
.parameter
&
8447 (kPMActionsFlagIsDisplayWrangler
| kPMActionsFlagIsGraphicsDevice
))
8451 #if WORK_QUEUE_STATS
8452 if (gIOPMRootNode
== ControllingDriver
)
8457 dict
= OSDictionary::withDictionary(
8458 PowerClients
, PowerClients
->getCount() + dictSize
);
8460 dict
= OSDictionary::withCapacity(dictSize
);
8464 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8465 if (NumberOfPowerStates
)
8466 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
-1);
8467 if (DesiredPowerState
!= CurrentPowerState
)
8468 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8469 if (kIOPM_Finished
!= MachineState
)
8470 setPMProperty(dict
, "MachineState", MachineState
);
8471 if (DeviceOverrideEnabled
)
8472 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8473 if (powerClamp
>= 0)
8474 setPMProperty(dict
, "PowerClamp", powerClamp
);
8476 if (IdleTimerPeriod
)
8482 clock_get_uptime(&now
);
8484 // The idle timer period in milliseconds.
8485 setPMProperty(dict
, "IdleTimerPeriod", IdleTimerPeriod
* 1000ULL);
8487 // The number of activity tickles recorded since device idle
8488 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8490 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
8492 // The number of milliseconds since the last activity tickle.
8494 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8495 absolutetime_to_nanoseconds(delta
, &nsecs
);
8496 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
8499 if (AbsoluteTime_to_scalar(&IdleTimerStartTime
))
8501 // The number of milliseconds since the last device idle.
8503 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
8504 absolutetime_to_nanoseconds(delta
, &nsecs
);
8505 setPMProperty(dict
, "TimeSinceDeviceIdle", NS_TO_MS(nsecs
));
8509 #if WORK_QUEUE_STATS
8510 if (gIOPMRootNode
== Owner
)
8512 setPMProperty(dict
, "WQ-CheckForWork",
8513 gIOPMWorkQueue
->fStatCheckForWork
);
8514 setPMProperty(dict
, "WQ-ScanEntries",
8515 gIOPMWorkQueue
->fStatScanEntries
);
8516 setPMProperty(dict
, "WQ-QueueEmpty",
8517 gIOPMWorkQueue
->fStatQueueEmpty
);
8518 setPMProperty(dict
, "WQ-NoWorkDone",
8519 gIOPMWorkQueue
->fStatNoWorkDone
);
8523 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
)
8525 // Don't report advisory tickle when it has no influence
8526 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
8529 ok
= dict
->serialize(s
);
8533 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
8536 bool IOServicePM::serialize( OSSerialize
* s
) const
8538 IOReturn ret
= kIOReturnNotReady
;
8540 if (gIOPMWatchDogThread
== current_thread())
8542 // Calling without lock as this data is collected for debug purpose, before reboot.
8543 // The workloop is probably already hung in state machine.
8544 ret
= gatedSerialize(s
);
8546 else if (gIOPMWorkLoop
)
8548 ret
= gIOPMWorkLoop
->runAction(
8549 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
8550 (OSObject
*) this, (void *) s
);
8553 return (kIOReturnSuccess
== ret
);
8556 void IOServicePM::pmPrint(
8559 uintptr_t param2
) const
8561 gPlatform
->PMLog(Name
, event
, param1
, param2
);
8564 void IOServicePM::pmTrace(
8567 uintptr_t param2
) const
8569 const char * who
= Name
;
8570 uint64_t regId
= Owner
->getRegistryEntryID();
8573 static const uint32_t sStartStopBitField
[] =
8574 { 0x00000000, 0x00000040 }; // Only Program Hardware so far
8576 // Arcane formula from Hacker's Delight by Warren
8577 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
8578 uint32_t sgnevent
= ((int) event
>> 31);
8579 uint32_t absevent
= sgnevent
^ (event
+ sgnevent
);
8580 uint32_t code
= IODBG_POWER(absevent
);
8582 uint32_t bit
= 1 << (absevent
& 0x1f);
8583 if ((absevent
< (sizeof(sStartStopBitField
) * 8)) &&
8584 (sStartStopBitField
[absevent
>> 5] & bit
))
8586 // Or in the START or END bits, Start = 1 & END = 2
8587 // If sgnevent == 0 then START - 0 => START
8588 // else if sgnevent == -1 then START - -1 => END
8589 code
|= DBG_FUNC_START
- sgnevent
;
8592 // Copy the first characters of the name into an uintptr_t
8593 for (uint32_t i
= 0; (i
< sizeof(uintptr_t) && who
[i
] != 0); i
++)
8595 ((char *) &name
)[sizeof(uintptr_t) - i
- 1] = who
[i
];
8598 IOTimeStampConstant(code
, name
, (uintptr_t) regId
, param1
, param2
);
8601 PMEventDetails
* PMEventDetails::eventDetails(uint32_t type
,
8602 const char *ownerName
,
8603 uintptr_t ownerUnique
,
8604 const char *interestName
,
8608 uint32_t elapsedTimeUS
) {
8610 PMEventDetails
*myself
;
8611 myself
= new PMEventDetails
;
8614 myself
->eventType
= type
;
8615 myself
->ownerName
= ownerName
;
8616 myself
->ownerUnique
= ownerUnique
;
8617 myself
->interestName
= interestName
;
8618 myself
->oldState
= oldState
;
8619 myself
->newState
= newState
;
8620 myself
->result
= result
;
8621 myself
->elapsedTimeUS
= elapsedTimeUS
;
8623 myself
->eventClassifier
= kIOPMEventClassDriverEvent
;
8630 PMEventDetails
* PMEventDetails::eventDetails(uint32_t type
,
8635 PMEventDetails
*myself
;
8636 myself
= new PMEventDetails
;
8639 myself
->eventType
= type
;
8640 myself
->uuid
= uuid
;
8641 myself
->reason
= reason
;
8642 myself
->result
= result
;
8644 myself
->eventClassifier
= kIOPMEventClassSystemEvent
;