2 * Copyright (c) 1998-2016 Apple 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@
29 #include <IOKit/assert.h>
30 #include <IOKit/IOKitDebug.h>
31 #include <IOKit/IOLib.h>
32 #include <IOKit/IOMessage.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IOEventSource.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/IOCommand.h>
38 #include <IOKit/IOTimeStamp.h>
39 #include <IOKit/IOReportMacros.h>
40 #include <IOKit/IODeviceTreeSupport.h>
42 #include <IOKit/pwr_mgt/IOPMlog.h>
43 #include <IOKit/pwr_mgt/IOPMinformee.h>
44 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
45 #include <IOKit/pwr_mgt/IOPowerConnection.h>
46 #include <IOKit/pwr_mgt/RootDomain.h>
47 #include <IOKit/pwr_mgt/IOPMPrivate.h>
50 #include <sys/proc_internal.h>
51 #include <sys/sysctl.h>
52 #include <libkern/OSDebug.h>
53 #include <kern/thread.h>
55 // Required for notification instrumentation
56 #include "IOServicePrivate.h"
57 #include "IOServicePMPrivate.h"
58 #include "IOKitKernelInternal.h"
61 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
62 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
63 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
64 static void tellAppClientApplier(OSObject
* object
, void * arg
);
67 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 //******************************************************************************
84 //******************************************************************************
86 static bool gIOPMInitialized
= false;
87 static uint32_t gIOPMBusyRequestCount
= 0;
88 static uint32_t gIOPMWorkInvokeCount
= 0;
89 static uint32_t gIOPMTickleGeneration
= 0;
90 static IOWorkLoop
* gIOPMWorkLoop
= NULL
;
91 static IOPMRequestQueue
* gIOPMRequestQueue
= NULL
;
92 static IOPMRequestQueue
* gIOPMReplyQueue
= NULL
;
93 static IOPMWorkQueue
* gIOPMWorkQueue
= NULL
;
94 static IOPMCompletionQueue
* gIOPMCompletionQueue
= NULL
;
95 static IOPMRequest
* gIOPMRequest
= NULL
;
96 static IOService
* gIOPMRootNode
= NULL
;
97 static IOPlatformExpert
* gPlatform
= NULL
;
100 const OSSymbol
* gIOPMPowerClientDevice
= NULL
;
101 const OSSymbol
* gIOPMPowerClientDriver
= NULL
;
102 const OSSymbol
* gIOPMPowerClientChildProxy
= NULL
;
103 const OSSymbol
* gIOPMPowerClientChildren
= NULL
;
104 const OSSymbol
* gIOPMPowerClientRootDomain
= NULL
;
106 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= NULL
;
107 static bool gIOPMAdvisoryTickleEnabled
= true;
108 static thread_t gIOPMWatchDogThread
= NULL
;
109 uint32_t gCanSleepTimeout
= 0;
112 getPMRequestType( void )
114 uint32_t type
= kIOPMRequestTypeInvalid
;
116 type
= gIOPMRequest
->getType();
121 static IOPMRequestTag
122 getPMRequestTag( void )
124 IOPMRequestTag tag
= 0;
126 (gIOPMRequest
->getType() == kIOPMRequestTypeRequestPowerStateOverride
)) {
127 tag
= gIOPMRequest
->fRequestTag
;
132 SYSCTL_UINT(_kern
, OID_AUTO
, pmtimeout
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &gCanSleepTimeout
, 0, "Power Management Timeout");
134 //******************************************************************************
136 //******************************************************************************
138 #define PM_ERROR(x...) do { kprintf(x);IOLog(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); \
161 #define PM_ASSERT_IN_GATE(x) \
163 assert(gIOPMWorkLoop->inGate()); \
166 #define PM_LOCK() IOLockLock(fPMLock)
167 #define PM_UNLOCK() IOLockUnlock(fPMLock)
168 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
169 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
171 #define us_per_s 1000000
172 #define ns_per_us 1000
173 #define k30Seconds (30*us_per_s)
174 #define k5Seconds ( 5*us_per_s)
176 #define kCanSleepMaxTimeReq k5Seconds
178 #define kCanSleepMaxTimeReq k30Seconds
180 #define kMaxTimeRequested k30Seconds
181 #define kMinAckTimeoutTicks (10*1000000)
182 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
183 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
184 #define kPwrMgtKey "IOPowerManagement"
186 #define OUR_PMLog(t, a, b) do { \
188 if (gIOKitDebug & kIOLogPower) \
189 pwrMgt->pmPrint(t, a, b); \
190 if (gIOKitTrace & kIOTracePowerMgmt) \
191 pwrMgt->pmTrace(t, DBG_FUNC_NONE, a, b); \
195 #define OUR_PMLogFuncStart(t, a, b) do { \
197 if (gIOKitDebug & kIOLogPower) \
198 pwrMgt->pmPrint(t, a, b); \
199 if (gIOKitTrace & kIOTracePowerMgmt) \
200 pwrMgt->pmTrace(t, DBG_FUNC_START, a, b); \
204 #define OUR_PMLogFuncEnd(t, a, b) do { \
206 if (gIOKitDebug & kIOLogPower) \
207 pwrMgt->pmPrint(-t, a, b); \
208 if (gIOKitTrace & kIOTracePowerMgmt) \
209 pwrMgt->pmTrace(t, DBG_FUNC_END, a, b); \
213 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
214 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
216 #define SUPPORT_IDLE_CANCEL 1
218 #define kIOPMPowerStateMax 0xFFFFFFFF
219 #define kInvalidTicklePowerState kIOPMPowerStateMax
221 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
223 #define IS_PM_ROOT (this == gIOPMRootNode)
224 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
225 #define IS_POWER_DROP (StateOrder(fHeadNotePowerState) < StateOrder(fCurrentPowerState))
226 #define IS_POWER_RISE (StateOrder(fHeadNotePowerState) > StateOrder(fCurrentPowerState))
228 // log setPowerStates longer than (ns):
229 #if defined(__i386__) || defined(__x86_64__)
230 #define LOG_SETPOWER_TIMES (300ULL * 1000ULL * 1000ULL)
232 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
234 // log app responses longer than (ns):
235 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
236 // use message tracer to log messages longer than (ns):
237 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
239 // log kext responses longer than (ns):
240 #define LOG_KEXT_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
243 kReserveDomainPower
= 1
247 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
248 assert(kIOPM_BadMachineState != n); \
249 fSavedMachineState = n; } while (false)
252 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
253 fMachineState = fSavedMachineState; \
254 fSavedMachineState = kIOPM_BadMachineState; } while (false)
256 #define PM_ACTION_0(a) \
257 do { if (fPMActions.a) { \
258 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
261 #define PM_ACTION_2(a, x, y) \
262 do { if (fPMActions.a) { \
263 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, \
264 getPMRequestTag()); } \
267 #define PM_ACTION_3(a, x, y, z) \
268 do { if (fPMActions.a) { \
269 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, z); } \
272 static OSNumber
* copyClientIDForNotification(
274 IOPMInterestContext
*context
);
276 static void logClientIDForNotification(
278 IOPMInterestContext
*context
,
279 const char *logString
);
281 //*********************************************************************************
284 // Check kgmacros after modifying machine states.
285 //*********************************************************************************
290 kIOPM_OurChangeTellClientsPowerDown
= 1,
291 kIOPM_OurChangeTellUserPMPolicyPowerDown
= 2,
292 kIOPM_OurChangeTellPriorityClientsPowerDown
= 3,
293 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 4,
294 kIOPM_OurChangeSetPowerState
= 5,
295 kIOPM_OurChangeWaitForPowerSettle
= 6,
296 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 7,
297 kIOPM_OurChangeTellCapabilityDidChange
= 8,
298 kIOPM_OurChangeFinish
= 9,
300 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
301 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
302 kIOPM_ParentChangeSetPowerState
= 12,
303 kIOPM_ParentChangeWaitForPowerSettle
= 13,
304 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
305 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
306 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
308 kIOPM_NotifyChildrenStart
= 17,
309 kIOPM_NotifyChildrenOrdered
= 18,
310 kIOPM_NotifyChildrenDelayed
= 19,
311 kIOPM_SyncTellClientsPowerDown
= 20,
312 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
313 kIOPM_SyncNotifyWillChange
= 22,
314 kIOPM_SyncNotifyDidChange
= 23,
315 kIOPM_SyncTellCapabilityDidChange
= 24,
316 kIOPM_SyncFinish
= 25,
317 kIOPM_TellCapabilityChangeDone
= 26,
318 kIOPM_DriverThreadCallDone
= 27,
320 kIOPM_BadMachineState
= 0xFFFFFFFF
323 //*********************************************************************************
326 // Initialize power management.
327 //*********************************************************************************
330 IOService::PMinit( void )
333 if (!gIOPMInitialized
) {
334 gPlatform
= getPlatform();
335 gIOPMWorkLoop
= IOWorkLoop::workLoop();
337 gIOPMRequestQueue
= IOPMRequestQueue::create(
338 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
339 this, &IOService::actionPMRequestQueue
));
341 gIOPMReplyQueue
= IOPMRequestQueue::create(
342 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
343 this, &IOService::actionPMReplyQueue
));
345 gIOPMWorkQueue
= IOPMWorkQueue::create(this,
346 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
347 &IOService::actionPMWorkQueueInvoke
),
348 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
349 &IOService::actionPMWorkQueueRetire
));
351 gIOPMCompletionQueue
= IOPMCompletionQueue::create(
352 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
353 this, &IOService::actionPMCompletionQueue
));
355 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
357 gIOPMRequestQueue
->release();
358 gIOPMRequestQueue
= NULL
;
361 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
363 gIOPMReplyQueue
->release();
364 gIOPMReplyQueue
= NULL
;
367 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
369 gIOPMWorkQueue
->release();
370 gIOPMWorkQueue
= NULL
;
373 // Must be added after the work queue, which pushes request
374 // to the completion queue without signaling the work loop.
375 if (gIOPMWorkLoop
->addEventSource(gIOPMCompletionQueue
) !=
377 gIOPMCompletionQueue
->release();
378 gIOPMCompletionQueue
= NULL
;
381 gIOPMPowerClientDevice
=
382 OSSymbol::withCStringNoCopy( "DevicePowerState" );
384 gIOPMPowerClientDriver
=
385 OSSymbol::withCStringNoCopy( "DriverPowerState" );
387 gIOPMPowerClientChildProxy
=
388 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
390 gIOPMPowerClientChildren
=
391 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
393 gIOPMPowerClientAdvisoryTickle
=
394 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
396 gIOPMPowerClientRootDomain
=
397 OSSymbol::withCStringNoCopy( "RootDomainPower" );
400 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMCompletionQueue
) {
401 gIOPMInitialized
= true;
404 if (!gIOPMInitialized
) {
408 pwrMgt
= new IOServicePM
;
410 setProperty(kPwrMgtKey
, pwrMgt
);
412 queue_init(&pwrMgt
->WorkChain
);
413 queue_init(&pwrMgt
->RequestHead
);
414 queue_init(&pwrMgt
->PMDriverCallQueue
);
417 fPMLock
= IOLockAlloc();
418 fInterestedDrivers
= new IOPMinformeeList
;
419 fInterestedDrivers
->initialize();
420 fDesiredPowerState
= kPowerStateZero
;
421 fDeviceDesire
= kPowerStateZero
;
422 fInitialPowerChange
= true;
423 fInitialSetPowerState
= true;
424 fPreviousRequestPowerFlags
= 0;
425 fDeviceOverrideEnabled
= false;
426 fMachineState
= kIOPM_Finished
;
427 fSavedMachineState
= kIOPM_BadMachineState
;
428 fIdleTimerMinPowerState
= kPowerStateZero
;
429 fActivityLock
= IOLockAlloc();
430 fStrictTreeOrder
= false;
431 fActivityTicklePowerState
= kInvalidTicklePowerState
;
432 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
433 fControllingDriver
= NULL
;
435 fNumberOfPowerStates
= 0;
436 fCurrentPowerState
= kPowerStateZero
;
437 fParentsCurrentPowerFlags
= 0;
438 fMaxPowerState
= kPowerStateZero
;
440 fParentsKnowState
= false;
442 fResponseArray
= NULL
;
443 fNotifyClientArray
= NULL
;
444 fCurrentPowerConsumption
= kIOPMUnknown
;
445 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
447 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot())) {
448 gIOPMRootNode
= this;
449 fParentsKnowState
= true;
450 } else if (getProperty(kIOPMResetPowerStateOnWakeKey
) == kOSBooleanTrue
) {
451 fResetPowerStateOnWake
= true;
454 if (IS_ROOT_DOMAIN
) {
455 fWatchdogTimer
= thread_call_allocate(
456 &IOService::watchdog_timer_expired
, (thread_call_param_t
)this);
457 fWatchdogLock
= IOLockAlloc();
459 fBlockedArray
= OSArray::withCapacity(4);
462 fAckTimer
= thread_call_allocate(
463 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
464 fSettleTimer
= thread_call_allocate(
465 &settle_timer_expired
, (thread_call_param_t
)this);
466 fIdleTimer
= thread_call_allocate(
467 &idle_timer_expired
, (thread_call_param_t
)this);
468 fDriverCallEntry
= thread_call_allocate(
469 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
470 assert(fDriverCallEntry
);
472 // Check for powerChangeDone override.
473 if (OSMemberFunctionCast(void (*)(void),
474 getResourceService(), &IOService::powerChangeDone
) !=
475 OSMemberFunctionCast(void (*)(void),
476 this, &IOService::powerChangeDone
)) {
477 fPCDFunctionOverride
= true;
481 IOPMprot
* prot
= new IOPMprot
;
484 prot
->ourName
= fName
;
485 prot
->thePlatform
= gPlatform
;
490 pm_vars
= (void *) (uintptr_t) true;
497 //*********************************************************************************
500 // Free the data created by PMinit. Only called from IOService::free().
501 //*********************************************************************************
504 IOService::PMfree( void )
510 assert(fMachineState
== kIOPM_Finished
);
511 assert(fInsertInterestSet
== NULL
);
512 assert(fRemoveInterestSet
== NULL
);
513 assert(fNotifyChildArray
== NULL
);
514 assert(queue_empty(&pwrMgt
->RequestHead
));
515 assert(queue_empty(&fPMDriverCallQueue
));
517 if (fWatchdogTimer
) {
518 thread_call_cancel(fWatchdogTimer
);
519 thread_call_free(fWatchdogTimer
);
520 fWatchdogTimer
= NULL
;
524 IOLockFree(fWatchdogLock
);
525 fWatchdogLock
= NULL
;
529 fBlockedArray
->release();
530 fBlockedArray
= NULL
;
534 thread_call_cancel(fSettleTimer
);
535 thread_call_free(fSettleTimer
);
539 thread_call_cancel(fAckTimer
);
540 thread_call_free(fAckTimer
);
544 thread_call_cancel(fIdleTimer
);
545 thread_call_free(fIdleTimer
);
548 if (fDriverCallEntry
) {
549 thread_call_free(fDriverCallEntry
);
550 fDriverCallEntry
= NULL
;
557 IOLockFree(fActivityLock
);
558 fActivityLock
= NULL
;
560 if (fInterestedDrivers
) {
561 fInterestedDrivers
->release();
562 fInterestedDrivers
= NULL
;
564 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
565 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
566 fDriverCallParamPtr
= NULL
;
567 fDriverCallParamSlots
= 0;
569 if (fResponseArray
) {
570 fResponseArray
->release();
571 fResponseArray
= NULL
;
573 if (fNotifyClientArray
) {
574 fNotifyClientArray
->release();
575 fNotifyClientArray
= NULL
;
577 if (fPowerStates
&& fNumberOfPowerStates
) {
578 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
579 fNumberOfPowerStates
= 0;
583 fPowerClients
->release();
584 fPowerClients
= NULL
;
600 IOService::PMDebug( uint32_t event
, uintptr_t param1
, uintptr_t param2
)
602 OUR_PMLog(event
, param1
, param2
);
605 //*********************************************************************************
606 // [public] joinPMtree
608 // A policy-maker calls its nub here when initializing, to be attached into
609 // the power management hierarchy. The default function is to call the
610 // platform expert, which knows how to do it. This method is overridden
611 // by a nub subclass which may either know how to do it, or may need to
612 // take other action.
614 // This may be the only "power management" method used in a nub,
615 // meaning it may not be initialized for power management.
616 //*********************************************************************************
619 IOService::joinPMtree( IOService
* driver
)
621 IOPlatformExpert
* platform
;
623 platform
= getPlatform();
624 assert(platform
!= NULL
);
625 platform
->PMRegisterDevice(this, driver
);
629 //*********************************************************************************
630 // [deprecated] youAreRoot
632 // Power Managment is informing us that we are the root power domain.
633 //*********************************************************************************
636 IOService::youAreRoot( void )
640 #endif /* !__LP64__ */
642 //*********************************************************************************
645 // Immediately stop driver callouts. Schedule an async stop request to detach
647 //*********************************************************************************
650 IOService::PMstop( void )
652 IOPMRequest
* request
;
660 if (fLockedFlags
.PMStop
) {
661 PM_LOG2("%s: PMstop() already stopped\n", fName
);
666 // Inhibit future driver calls.
667 fLockedFlags
.PMStop
= true;
669 // Wait for all prior driver calls to finish.
670 waitForPMDriverCall();
674 // The rest of the work is performed async.
675 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
677 PM_LOG2("%s: %p PMstop\n", getName(), OBFUSCATE(this));
678 submitPMRequest( request
);
682 //*********************************************************************************
683 // [private] handlePMstop
685 // Disconnect the node from all parents and children in the power plane.
686 //*********************************************************************************
689 IOService::handlePMstop( IOPMRequest
* request
)
693 IOPowerConnection
* connection
;
694 IOService
* theChild
;
695 IOService
* theParent
;
698 PM_LOG2("%s: %p %s start\n", getName(), OBFUSCATE(this), __FUNCTION__
);
700 // remove driver from prevent system sleep lists
701 getPMRootDomain()->updatePreventIdleSleepList(this, false);
702 getPMRootDomain()->updatePreventSystemSleepList(this, false);
704 // remove the property
705 removeProperty(kPwrMgtKey
);
708 iter
= getParentIterator(gIOPowerPlane
);
710 while ((next
= iter
->getNextObject())) {
711 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
712 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
714 theParent
->removePowerChild(connection
);
715 theParent
->release();
722 // detach IOConnections
723 detachAbove( gIOPowerPlane
);
725 // no more power state changes
726 fParentsKnowState
= false;
729 iter
= getChildIterator(gIOPowerPlane
);
731 while ((next
= iter
->getNextObject())) {
732 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
733 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
735 // detach nub from child
736 connection
->detachFromChild(theChild
, gIOPowerPlane
);
739 // detach us from nub
740 detachFromChild(connection
, gIOPowerPlane
);
746 // Remove all interested drivers from the list, including the power
747 // controlling driver.
749 // Usually, the controlling driver and the policy-maker functionality
750 // are implemented by the same object, and without the deregistration,
751 // the object will be holding an extra retain on itself, and cannot
754 if (fInterestedDrivers
) {
755 IOPMinformeeList
* list
= fInterestedDrivers
;
759 while ((item
= list
->firstInList())) {
760 list
->removeFromList(item
->whatObject
);
765 // Clear idle period to prevent idleTimerExpired() from servicing
766 // idle timer expirations.
768 fIdleTimerPeriod
= 0;
769 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
)) {
773 PM_LOG2("%s: %p %s done\n", getName(), OBFUSCATE(this), __FUNCTION__
);
776 //*********************************************************************************
777 // [public] addPowerChild
779 // Power Management is informing us who our children are.
780 //*********************************************************************************
783 IOService::addPowerChild( IOService
* child
)
785 IOPowerConnection
* connection
= NULL
;
786 IOPMRequest
* requests
[3] = {NULL
, NULL
, NULL
};
791 return kIOReturnBadArgument
;
794 if (!initialized
|| !child
->initialized
) {
795 return IOPMNotYetInitialized
;
798 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
801 // Is this child already one of our children?
803 iter
= child
->getParentIterator( gIOPowerPlane
);
805 IORegistryEntry
* entry
;
808 while ((next
= iter
->getNextObject())) {
809 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
810 isChild(entry
, gIOPowerPlane
)) {
818 PM_LOG2("%s: %s (%p) is already a child\n",
819 getName(), child
->getName(), OBFUSCATE(child
));
823 // Add the child to the power plane immediately, but the
824 // joining connection is marked as not ready.
825 // We want the child to appear in the power plane before
826 // returning to the caller, but don't want the caller to
827 // block on the PM work loop.
829 connection
= new IOPowerConnection
;
834 // Create a chain of PM requests to perform the bottom-half
835 // work from the PM work loop.
837 requests
[0] = acquirePMRequest(
839 /* type */ kIOPMRequestTypeAddPowerChild1
);
841 requests
[1] = acquirePMRequest(
843 /* type */ kIOPMRequestTypeAddPowerChild2
);
845 requests
[2] = acquirePMRequest(
847 /* type */ kIOPMRequestTypeAddPowerChild3
);
849 if (!requests
[0] || !requests
[1] || !requests
[2]) {
853 requests
[0]->attachNextRequest( requests
[1] );
854 requests
[1]->attachNextRequest( requests
[2] );
857 connection
->start(this);
858 connection
->setAwaitingAck(false);
859 connection
->setReadyFlag(false);
861 attachToChild( connection
, gIOPowerPlane
);
862 connection
->attachToChild( child
, gIOPowerPlane
);
864 // connection needs to be released
865 requests
[0]->fArg0
= connection
;
866 requests
[1]->fArg0
= connection
;
867 requests
[2]->fArg0
= connection
;
869 submitPMRequests( requests
, 3 );
870 return kIOReturnSuccess
;
874 connection
->release();
877 releasePMRequest(requests
[0]);
880 releasePMRequest(requests
[1]);
883 releasePMRequest(requests
[2]);
886 // Silent failure, to prevent platform drivers from adding the child
887 // to the root domain.
889 return kIOReturnSuccess
;
892 //*********************************************************************************
893 // [private] addPowerChild1
895 // Step 1/3 of adding a power child. Called on the power parent.
896 //*********************************************************************************
899 IOService::addPowerChild1( IOPMRequest
* request
)
901 IOPMPowerStateIndex tempDesire
= kPowerStateZero
;
903 // Make us temporary usable before adding the child.
906 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
908 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
) {
909 tempDesire
= fHighestPowerState
;
912 if ((tempDesire
!= kPowerStateZero
) &&
913 (IS_PM_ROOT
|| (StateOrder(fMaxPowerState
) >= StateOrder(tempDesire
)))) {
914 adjustPowerState(tempDesire
);
918 //*********************************************************************************
919 // [private] addPowerChild2
921 // Step 2/3 of adding a power child. Called on the joining child.
922 // Execution blocked behind addPowerChild1.
923 //*********************************************************************************
926 IOService::addPowerChild2( IOPMRequest
* request
)
928 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
930 IOPMPowerFlags powerFlags
;
932 unsigned long powerState
;
933 unsigned long tempDesire
;
936 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
938 if (!parent
|| !inPlane(gIOPowerPlane
)) {
939 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
943 // Parent will be waiting for us to complete this stage.
944 // It is safe to directly access parent's vars.
946 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
947 powerState
= parent
->fCurrentPowerState
;
950 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
955 // Set our power parent.
957 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
959 setParentInfo( powerFlags
, connection
, knowsState
);
961 connection
->setReadyFlag(true);
963 if (fControllingDriver
&& fParentsKnowState
) {
964 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
965 // initially change into the state we are already in
966 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
967 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
968 adjustPowerState(tempDesire
);
971 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
974 //*********************************************************************************
975 // [private] addPowerChild3
977 // Step 3/3 of adding a power child. Called on the parent.
978 // Execution blocked behind addPowerChild2.
979 //*********************************************************************************
982 IOService::addPowerChild3( IOPMRequest
* request
)
984 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
986 IOPMrootDomain
* rootDomain
= getPMRootDomain();
989 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
991 if (child
&& inPlane(gIOPowerPlane
)) {
992 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder")) {
993 PM_LOG1("%s: strict PM order enforced\n", getName());
994 fStrictTreeOrder
= true;
998 rootDomain
->joinAggressiveness( child
);
1001 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1004 connection
->release();
1008 //*********************************************************************************
1009 // [deprecated] setPowerParent
1011 // Power Management is informing us who our parent is.
1012 // If we have a controlling driver, find out, given our newly-informed
1013 // power domain state, what state it would be in, and then tell it
1014 // to assume that state.
1015 //*********************************************************************************
1018 IOService::setPowerParent(
1019 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
1021 return kIOReturnUnsupported
;
1023 #endif /* !__LP64__ */
1025 //*********************************************************************************
1026 // [public] removePowerChild
1028 // Called on a parent whose child is being removed by PMstop().
1029 //*********************************************************************************
1032 IOService::removePowerChild( IOPowerConnection
* theNub
)
1034 IORegistryEntry
* theChild
;
1036 PM_ASSERT_IN_GATE();
1037 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1041 // detach nub from child
1042 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1044 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1045 theChild
->release();
1047 // detach from the nub
1048 detachFromChild(theNub
, gIOPowerPlane
);
1050 // Are we awaiting an ack from this child?
1051 if (theNub
->getAwaitingAck()) {
1052 // yes, pretend we got one
1053 theNub
->setAwaitingAck(false);
1054 if (fHeadNotePendingAcks
!= 0) {
1055 // that's one fewer ack to worry about
1056 fHeadNotePendingAcks
--;
1058 // is that the last?
1059 if (fHeadNotePendingAcks
== 0) {
1061 getPMRootDomain()->reset_watchdog_timer(this, 0);
1063 // This parent may have a request in the work queue that is
1064 // blocked on fHeadNotePendingAcks=0. And removePowerChild()
1065 // is called while executing the child's PMstop request so they
1066 // can occur simultaneously. IOPMWorkQueue::checkForWork() must
1067 // restart and check all request queues again.
1069 gIOPMWorkQueue
->incrementProducerCount();
1076 // A child has gone away, re-scan children desires and clamp bits.
1077 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1079 if (!fAdjustPowerScheduled
) {
1080 IOPMRequest
* request
;
1081 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1083 submitPMRequest( request
);
1084 fAdjustPowerScheduled
= true;
1091 //*********************************************************************************
1092 // [public] registerPowerDriver
1094 // A driver has called us volunteering to control power to our device.
1095 //*********************************************************************************
1098 IOService::registerPowerDriver(
1099 IOService
* powerDriver
,
1100 IOPMPowerState
* powerStates
,
1101 unsigned long numberOfStates
)
1103 IOPMRequest
* request
;
1104 IOPMPSEntry
* powerStatesCopy
= NULL
;
1105 IOPMPowerStateIndex stateOrder
;
1106 IOReturn error
= kIOReturnSuccess
;
1109 return IOPMNotYetInitialized
;
1112 if (!powerStates
|| (numberOfStates
< 2)) {
1113 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1114 return kIOReturnBadArgument
;
1117 if (!powerDriver
|| !powerDriver
->initialized
) {
1118 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1119 return kIOReturnBadArgument
;
1122 if (powerStates
[0].version
> kIOPMPowerStateVersion2
) {
1123 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1124 return kIOReturnBadArgument
;
1128 // Make a copy of the supplied power state array.
1129 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1130 if (!powerStatesCopy
) {
1131 error
= kIOReturnNoMemory
;
1135 // Initialize to bogus values
1136 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++) {
1137 powerStatesCopy
[i
].stateOrderToIndex
= kIOPMPowerStateMax
;
1140 for (uint32_t i
= 0; i
< numberOfStates
; i
++) {
1141 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1142 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1143 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1144 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1145 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1146 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1147 if (powerStates
[i
].version
>= kIOPMPowerStateVersion2
) {
1148 stateOrder
= powerStates
[i
].stateOrder
;
1153 if (stateOrder
< numberOfStates
) {
1154 powerStatesCopy
[i
].stateOrder
= stateOrder
;
1155 powerStatesCopy
[stateOrder
].stateOrderToIndex
= i
;
1159 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++) {
1160 if (powerStatesCopy
[i
].stateOrderToIndex
== kIOPMPowerStateMax
) {
1161 // power state order missing
1162 error
= kIOReturnBadArgument
;
1166 if (kIOReturnSuccess
!= error
) {
1170 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1172 error
= kIOReturnNoMemory
;
1176 powerDriver
->retain();
1177 request
->fArg0
= (void *) powerDriver
;
1178 request
->fArg1
= (void *) powerStatesCopy
;
1179 request
->fArg2
= (void *) numberOfStates
;
1181 submitPMRequest( request
);
1182 return kIOReturnSuccess
;
1185 if (powerStatesCopy
) {
1186 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1192 //*********************************************************************************
1193 // [private] handleRegisterPowerDriver
1194 //*********************************************************************************
1197 IOService::handleRegisterPowerDriver( IOPMRequest
* request
)
1199 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1200 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1201 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1202 unsigned long i
, stateIndex
;
1203 unsigned long lowestPowerState
;
1207 PM_ASSERT_IN_GATE();
1208 assert(powerStates
);
1209 assert(powerDriver
);
1210 assert(numberOfStates
> 1);
1212 if (!fNumberOfPowerStates
) {
1213 OUR_PMLog(kPMLogControllingDriver
,
1214 (unsigned long) numberOfStates
,
1215 (unsigned long) kIOPMPowerStateVersion1
);
1217 fPowerStates
= powerStates
;
1218 fNumberOfPowerStates
= numberOfStates
;
1219 fControllingDriver
= powerDriver
;
1220 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1222 lowestPowerState
= fPowerStates
[0].stateOrderToIndex
;
1223 fHighestPowerState
= fPowerStates
[numberOfStates
- 1].stateOrderToIndex
;
1227 IOService
* service
;
1231 // Disallow kIOPMAOTPower states unless device tree enabled
1235 while (service
&& !service
->inPlane(gIODTPlane
)) {
1236 service
= service
->getProvider();
1239 object
= service
->copyProperty(kIOPMAOTPowerKey
, gIODTPlane
);
1240 data
= OSDynamicCast(OSData
, object
);
1241 if (data
&& (data
->getLength() >= sizeof(uint32_t))) {
1242 aotFlags
= ((uint32_t *)data
->getBytesNoCopy())[0];
1244 OSSafeReleaseNULL(object
);
1247 for (i
= 0; i
< numberOfStates
; i
++) {
1248 if (kIOPMAOTPower
& fPowerStates
[i
].inputPowerFlags
) {
1249 fPowerStates
[i
].inputPowerFlags
= 0xFFFFFFFF;
1250 fPowerStates
[i
].capabilityFlags
= 0;
1251 fPowerStates
[i
].outputPowerFlags
= 0;
1257 // OR'in all the output power flags
1258 fMergedOutputPowerFlags
= 0;
1259 fDeviceUsablePowerState
= lowestPowerState
;
1260 for (i
= 0; i
< numberOfStates
; i
++) {
1261 fMergedOutputPowerFlags
|= fPowerStates
[i
].outputPowerFlags
;
1263 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
1264 assert(stateIndex
< numberOfStates
);
1265 if ((fDeviceUsablePowerState
== lowestPowerState
) &&
1266 (fPowerStates
[stateIndex
].capabilityFlags
& IOPMDeviceUsable
)) {
1267 // The minimum power state that the device is usable
1268 fDeviceUsablePowerState
= stateIndex
;
1272 // Register powerDriver as interested, unless already done.
1273 // We don't want to register the default implementation since
1274 // it does nothing. One ramification of not always registering
1275 // is the one fewer retain count held.
1277 root
= getPlatform()->getProvider();
1280 ((OSMemberFunctionCast(void (*)(void),
1281 root
, &IOService::powerStateDidChangeTo
)) !=
1282 ((OSMemberFunctionCast(void (*)(void),
1283 this, &IOService::powerStateDidChangeTo
)))) ||
1284 ((OSMemberFunctionCast(void (*)(void),
1285 root
, &IOService::powerStateWillChangeTo
)) !=
1286 ((OSMemberFunctionCast(void (*)(void),
1287 this, &IOService::powerStateWillChangeTo
))))) {
1288 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
) {
1290 fInterestedDrivers
->appendNewInformee(powerDriver
);
1295 // Examine all existing power clients and perform limit check.
1297 if (fPowerClients
&&
1298 (iter
= OSCollectionIterator::withCollection(fPowerClients
))) {
1299 const OSSymbol
* client
;
1300 while ((client
= (const OSSymbol
*) iter
->getNextObject())) {
1301 IOPMPowerStateIndex powerState
= getPowerStateForClient(client
);
1302 if (powerState
>= numberOfStates
) {
1303 updatePowerClient(client
, fHighestPowerState
);
1309 if (inPlane(gIOPowerPlane
) && fParentsKnowState
) {
1310 IOPMPowerStateIndex tempDesire
;
1311 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1312 // initially change into the state we are already in
1313 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1314 adjustPowerState(tempDesire
);
1317 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1318 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1321 powerDriver
->release();
1324 //*********************************************************************************
1325 // [public] registerInterestedDriver
1327 // Add the caller to our list of interested drivers and return our current
1328 // power state. If we don't have a power-controlling driver yet, we will
1329 // call this interested driver again later when we do get a driver and find
1330 // out what the current power state of the device is.
1331 //*********************************************************************************
1334 IOService::registerInterestedDriver( IOService
* driver
)
1336 IOPMRequest
* request
;
1339 if (!driver
|| !initialized
|| !fInterestedDrivers
) {
1344 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1345 if (fInsertInterestSet
== NULL
) {
1346 fInsertInterestSet
= OSSet::withCapacity(4);
1348 if (fInsertInterestSet
) {
1349 fInsertInterestSet
->setObject(driver
);
1350 if (fRemoveInterestSet
) {
1351 fRemoveInterestSet
->removeObject(driver
);
1357 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1359 submitPMRequest( request
);
1363 // This return value cannot be trusted, but return a value
1364 // for those clients that care.
1366 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1367 return kIOPMDeviceUsable
;
1370 //*********************************************************************************
1371 // [public] deRegisterInterestedDriver
1372 //*********************************************************************************
1375 IOService::deRegisterInterestedDriver( IOService
* driver
)
1377 IOPMinformee
* item
;
1378 IOPMRequest
* request
;
1382 return kIOReturnBadArgument
;
1384 if (!initialized
|| !fInterestedDrivers
) {
1385 return IOPMNotPowerManaged
;
1389 if (fInsertInterestSet
) {
1390 fInsertInterestSet
->removeObject(driver
);
1393 item
= fInterestedDrivers
->findItem(driver
);
1396 return kIOReturnNotFound
;
1399 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1400 if (fRemoveInterestSet
== NULL
) {
1401 fRemoveInterestSet
= OSSet::withCapacity(4);
1403 if (fRemoveInterestSet
) {
1404 fRemoveInterestSet
->setObject(driver
);
1406 item
->active
= false;
1407 waitForPMDriverCall( driver
);
1413 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1415 submitPMRequest( request
);
1422 //*********************************************************************************
1423 // [private] handleInterestChanged
1425 // Handle interest added or removed.
1426 //*********************************************************************************
1429 IOService::handleInterestChanged( IOPMRequest
* request
)
1432 IOPMinformee
* informee
;
1433 IOPMinformeeList
* list
= fInterestedDrivers
;
1437 if (fInsertInterestSet
) {
1438 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject())) {
1439 if (list
->findItem(driver
) == NULL
) {
1440 informee
= list
->appendNewInformee(driver
);
1442 fInsertInterestSet
->removeObject(driver
);
1444 fInsertInterestSet
->release();
1445 fInsertInterestSet
= NULL
;
1448 if (fRemoveInterestSet
) {
1449 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject())) {
1450 informee
= list
->findItem(driver
);
1452 // Clean-up async interest acknowledgement
1453 if (fHeadNotePendingAcks
&& informee
->timer
) {
1454 informee
->timer
= 0;
1455 fHeadNotePendingAcks
--;
1457 list
->removeFromList(driver
);
1459 fRemoveInterestSet
->removeObject(driver
);
1461 fRemoveInterestSet
->release();
1462 fRemoveInterestSet
= NULL
;
1468 //*********************************************************************************
1469 // [public] acknowledgePowerChange
1471 // After we notified one of the interested drivers or a power-domain child
1472 // of an impending change in power, it has called to say it is now
1473 // prepared for the change. If this object is the last to
1474 // acknowledge this change, we take whatever action we have been waiting
1476 // That may include acknowledging to our parent. In this case, we do it
1477 // last of all to insure that this doesn't cause the parent to call us some-
1478 // where else and alter data we are relying on here (like the very existance
1479 // of a "current change note".)
1480 //*********************************************************************************
1483 IOService::acknowledgePowerChange( IOService
* whichObject
)
1485 IOPMRequest
* request
;
1488 return IOPMNotYetInitialized
;
1491 return kIOReturnBadArgument
;
1494 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1496 return kIOReturnNoMemory
;
1499 whichObject
->retain();
1500 request
->fArg0
= whichObject
;
1502 submitPMRequest( request
);
1506 //*********************************************************************************
1507 // [private] handleAcknowledgePowerChange
1508 //*********************************************************************************
1511 IOService::handleAcknowledgePowerChange( IOPMRequest
* request
)
1513 IOPMinformee
* informee
;
1514 unsigned long childPower
= kIOPMUnknown
;
1515 IOService
* theChild
;
1516 IOService
* whichObject
;
1517 bool all_acked
= false;
1519 PM_ASSERT_IN_GATE();
1520 whichObject
= (IOService
*) request
->fArg0
;
1521 assert(whichObject
);
1523 // one of our interested drivers?
1524 informee
= fInterestedDrivers
->findItem( whichObject
);
1525 if (informee
== NULL
) {
1526 if (!isChild(whichObject
, gIOPowerPlane
)) {
1527 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1530 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1533 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1536 if (fHeadNotePendingAcks
!= 0) {
1537 assert(fPowerStates
!= NULL
);
1539 // yes, make sure we're expecting acks
1540 if (informee
!= NULL
) {
1541 // it's an interested driver
1542 // make sure we're expecting this ack
1543 if (informee
->timer
!= 0) {
1544 if (informee
->timer
> 0) {
1545 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1546 if (nsec
> LOG_SETPOWER_TIMES
) {
1547 getPMRootDomain()->pmStatsRecordApplicationResponse(
1548 gIOPMStatsDriverPSChangeSlow
, informee
->whatObject
->getName(),
1549 fDriverCallReason
, NS_TO_MS(nsec
), informee
->whatObject
->getRegistryEntryID(),
1550 NULL
, fHeadNotePowerState
);
1555 informee
->timer
= 0;
1556 // that's one fewer to worry about
1557 fHeadNotePendingAcks
--;
1559 // this driver has already acked
1560 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1564 // make sure we're expecting this ack
1565 if (((IOPowerConnection
*)whichObject
)->getAwaitingAck()) {
1566 // that's one fewer to worry about
1567 fHeadNotePendingAcks
--;
1568 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1569 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1571 childPower
= theChild
->currentPowerConsumption();
1572 theChild
->release();
1574 if (childPower
== kIOPMUnknown
) {
1575 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1577 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
) {
1578 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1584 if (fHeadNotePendingAcks
== 0) {
1585 // yes, stop the timer
1587 // and now we can continue
1589 getPMRootDomain()->reset_watchdog_timer(this, 0);
1592 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1597 whichObject
->release();
1603 //*********************************************************************************
1604 // [public] acknowledgeSetPowerState
1606 // After we instructed our controlling driver to change power states,
1607 // it has called to say it has finished doing so.
1608 // We continue to process the power state change.
1609 //*********************************************************************************
1612 IOService::acknowledgeSetPowerState( void )
1614 IOPMRequest
* request
;
1617 return IOPMNotYetInitialized
;
1620 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1622 return kIOReturnNoMemory
;
1625 submitPMRequest( request
);
1626 return kIOReturnSuccess
;
1629 //*********************************************************************************
1630 // [private] adjustPowerState
1631 //*********************************************************************************
1634 IOService::adjustPowerState( uint32_t clamp
)
1636 PM_ASSERT_IN_GATE();
1637 computeDesiredState(clamp
, false);
1638 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
)) {
1639 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1641 // Indicate that children desires must be ignored, and do not ask
1642 // apps for permission to drop power. This is used by root domain
1643 // for demand sleep.
1645 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
) {
1646 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1650 /* flags */ changeFlags
,
1651 /* power state */ fDesiredPowerState
,
1652 /* domain flags */ 0,
1653 /* connection */ NULL
,
1654 /* parent flags */ 0);
1658 //*********************************************************************************
1659 // [public] synchronizePowerTree
1660 //*********************************************************************************
1663 IOService::synchronizePowerTree(
1664 IOOptionBits options
,
1665 IOService
* notifyRoot
)
1667 IOPMRequest
* request_c
= NULL
;
1668 IOPMRequest
* request_s
;
1670 if (this != getPMRootDomain()) {
1671 return kIOReturnBadArgument
;
1674 return kIOPMNotYetInitialized
;
1677 OUR_PMLog(kPMLogCSynchronizePowerTree
, options
, (notifyRoot
!= NULL
));
1682 // Cancels don't need to be synchronized.
1683 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1685 submitPMRequest(nr
);
1687 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1689 submitPMRequest(nr
);
1693 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1695 goto error_no_memory
;
1698 if (options
& kIOPMSyncCancelPowerDown
) {
1699 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1702 request_c
->attachNextRequest( request_s
);
1703 submitPMRequest(request_c
);
1706 request_s
->fArg0
= (void *)(uintptr_t) options
;
1707 submitPMRequest(request_s
);
1709 return kIOReturnSuccess
;
1713 releasePMRequest(request_c
);
1716 releasePMRequest(request_s
);
1718 return kIOReturnNoMemory
;
1721 //*********************************************************************************
1722 // [private] handleSynchronizePowerTree
1723 //*********************************************************************************
1726 IOService::handleSynchronizePowerTree( IOPMRequest
* request
)
1728 PM_ASSERT_IN_GATE();
1729 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1730 (fCurrentPowerState
== fHighestPowerState
)) {
1731 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1734 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1735 (options
& kIOPMSyncNoChildNotify
),
1736 /* power state */ fCurrentPowerState
,
1737 /* domain flags */ 0,
1738 /* connection */ NULL
,
1739 /* parent flags */ 0);
1744 //*********************************************************************************
1745 // [deprecated] powerDomainWillChangeTo
1747 // Called by the power-hierarchy parent notifying of a new power state
1748 // in the power domain.
1749 // We enqueue a parent power-change to our queue of power changes.
1750 // This may or may not cause us to change power, depending on what
1751 // kind of change is occuring in the domain.
1752 //*********************************************************************************
1755 IOService::powerDomainWillChangeTo(
1756 IOPMPowerFlags newPowerFlags
,
1757 IOPowerConnection
* whichParent
)
1760 return kIOReturnUnsupported
;
1762 #endif /* !__LP64__ */
1764 //*********************************************************************************
1765 // [private] handlePowerDomainWillChangeTo
1766 //*********************************************************************************
1769 IOService::handlePowerDomainWillChangeTo( IOPMRequest
* request
)
1771 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1772 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1773 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1774 IOPMPowerChangeFlags myChangeFlags
;
1777 IOPowerConnection
* connection
;
1778 IOPMPowerStateIndex maxPowerState
;
1779 IOPMPowerFlags combinedPowerFlags
;
1780 bool savedParentsKnowState
;
1781 IOReturn result
= IOPMAckImplied
;
1783 PM_ASSERT_IN_GATE();
1784 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1786 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck()) {
1787 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1791 savedParentsKnowState
= fParentsKnowState
;
1793 // Combine parents' output power flags.
1795 combinedPowerFlags
= 0;
1797 iter
= getParentIterator(gIOPowerPlane
);
1799 while ((next
= iter
->getNextObject())) {
1800 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
1801 if (connection
== whichParent
) {
1802 combinedPowerFlags
|= parentPowerFlags
;
1804 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1811 // If our initial change has yet to occur, then defer the power change
1812 // until after the power domain has completed its power transition.
1814 if (fControllingDriver
&& !fInitialPowerChange
) {
1815 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1816 combinedPowerFlags
);
1818 if (parentChangeFlags
& kIOPMDomainPowerDrop
) {
1819 // fMaxPowerState set a limit on self-initiated power changes.
1820 // Update it before a parent power drop.
1821 fMaxPowerState
= maxPowerState
;
1824 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1825 // to avoid propagating the root change flags if any service must
1826 // change power state due to root's will-change notification.
1827 // Root does not change power state for kIOPMSynchronize.
1829 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1830 (parentChangeFlags
& kIOPMSynchronize
);
1832 result
= startPowerChange(
1833 /* flags */ myChangeFlags
,
1834 /* power state */ maxPowerState
,
1835 /* domain flags */ combinedPowerFlags
,
1836 /* connection */ whichParent
,
1837 /* parent flags */ parentPowerFlags
);
1840 // If parent is dropping power, immediately update the parent's
1841 // capability flags. Any future merging of parent(s) combined
1842 // power flags should account for this power drop.
1844 if (parentChangeFlags
& kIOPMDomainPowerDrop
) {
1845 setParentInfo(parentPowerFlags
, whichParent
, true);
1848 // Parent is expecting an ACK from us. If we did not embark on a state
1849 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1850 // still required to issue an ACK to our parent.
1852 if (IOPMAckImplied
== result
) {
1854 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1857 parent
->acknowledgePowerChange( whichParent
);
1863 // Drop the retain from notifyChild().
1865 whichParent
->release();
1870 //*********************************************************************************
1871 // [deprecated] powerDomainDidChangeTo
1873 // Called by the power-hierarchy parent after the power state of the power domain
1874 // has settled at a new level.
1875 // We enqueue a parent power-change to our queue of power changes.
1876 // This may or may not cause us to change power, depending on what
1877 // kind of change is occuring in the domain.
1878 //*********************************************************************************
1881 IOService::powerDomainDidChangeTo(
1882 IOPMPowerFlags newPowerFlags
,
1883 IOPowerConnection
* whichParent
)
1886 return kIOReturnUnsupported
;
1888 #endif /* !__LP64__ */
1890 //*********************************************************************************
1891 // [private] handlePowerDomainDidChangeTo
1892 //*********************************************************************************
1895 IOService::handlePowerDomainDidChangeTo( IOPMRequest
* request
)
1897 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1898 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1899 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1900 IOPMPowerChangeFlags myChangeFlags
;
1901 IOPMPowerStateIndex maxPowerState
;
1902 IOPMPowerStateIndex initialDesire
= kPowerStateZero
;
1903 bool computeDesire
= false;
1904 bool desireChanged
= false;
1905 bool savedParentsKnowState
;
1906 IOReturn result
= IOPMAckImplied
;
1908 PM_ASSERT_IN_GATE();
1909 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1911 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck()) {
1912 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1916 savedParentsKnowState
= fParentsKnowState
;
1918 setParentInfo(parentPowerFlags
, whichParent
, true);
1920 if (fControllingDriver
) {
1921 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1922 fParentsCurrentPowerFlags
);
1924 if ((parentChangeFlags
& kIOPMDomainPowerDrop
) == 0) {
1925 // fMaxPowerState set a limit on self-initiated power changes.
1926 // Update it after a parent power rise.
1927 fMaxPowerState
= maxPowerState
;
1930 if (fInitialPowerChange
) {
1931 computeDesire
= true;
1932 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1933 fParentsCurrentPowerFlags
);
1934 } else if (parentChangeFlags
& kIOPMRootChangeUp
) {
1935 if (fAdvisoryTickleUsed
) {
1936 // On system wake, re-compute the desired power state since
1937 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1938 // which is an input to computeDesiredState(). This is not
1939 // necessary for a dark wake because powerChangeDone() will
1940 // handle the dark to full wake case, but it does no harm.
1942 desireChanged
= true;
1945 if (fResetPowerStateOnWake
) {
1946 // Query the driver for the desired power state on system wake.
1947 // Default implementation returns the lowest power state.
1949 IOPMPowerStateIndex wakePowerState
=
1950 fControllingDriver
->initialPowerStateForDomainState(
1951 kIOPMRootDomainState
| kIOPMPowerOn
);
1953 // fDesiredPowerState was adjusted before going to sleep
1954 // with fDeviceDesire at min.
1956 if (StateOrder(wakePowerState
) > StateOrder(fDesiredPowerState
)) {
1957 // Must schedule a power adjustment if we changed the
1958 // device desire. That will update the desired domain
1959 // power on the parent power connection and ping the
1960 // power parent if necessary.
1962 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1963 desireChanged
= true;
1968 if (computeDesire
|| desireChanged
) {
1969 computeDesiredState(initialDesire
, false);
1972 // Absorb and propagate parent's broadcast flags
1973 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1974 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1976 if (kIOPMAOTPower
& fPowerStates
[maxPowerState
].inputPowerFlags
) {
1977 IOLog("aotPS %s0x%qx[%ld]\n", getName(), getRegistryEntryID(), maxPowerState
);
1980 result
= startPowerChange(
1981 /* flags */ myChangeFlags
,
1982 /* power state */ maxPowerState
,
1983 /* domain flags */ fParentsCurrentPowerFlags
,
1984 /* connection */ whichParent
,
1985 /* parent flags */ 0);
1988 // Parent is expecting an ACK from us. If we did not embark on a state
1989 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1990 // still required to issue an ACK to our parent.
1992 if (IOPMAckImplied
== result
) {
1994 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1997 parent
->acknowledgePowerChange( whichParent
);
2002 // If the parent registers its power driver late, then this is the
2003 // first opportunity to tell our parent about our desire. Or if the
2004 // child's desire changed during a parent change notify.
2006 if (fControllingDriver
&&
2007 ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
)) {
2008 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
2009 getName(), fParentsKnowState
);
2010 requestDomainPower( fDesiredPowerState
);
2014 // Drop the retain from notifyChild().
2016 whichParent
->release();
2020 //*********************************************************************************
2021 // [private] setParentInfo
2023 // Set our connection data for one specific parent, and then combine all the parent
2025 //*********************************************************************************
2028 IOService::setParentInfo(
2029 IOPMPowerFlags newPowerFlags
,
2030 IOPowerConnection
* whichParent
,
2035 IOPowerConnection
* conn
;
2037 PM_ASSERT_IN_GATE();
2039 // set our connection data
2040 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
2041 whichParent
->setParentKnowsState(knowsState
);
2043 // recompute our parent info
2044 fParentsCurrentPowerFlags
= 0;
2045 fParentsKnowState
= true;
2047 iter
= getParentIterator(gIOPowerPlane
);
2049 while ((next
= iter
->getNextObject())) {
2050 if ((conn
= OSDynamicCast(IOPowerConnection
, next
))) {
2051 fParentsKnowState
&= conn
->parentKnowsState();
2052 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
2059 //******************************************************************************
2060 // [private] trackSystemSleepPreventers
2061 //******************************************************************************
2064 IOService::trackSystemSleepPreventers(
2065 IOPMPowerStateIndex oldPowerState
,
2066 IOPMPowerStateIndex newPowerState
,
2067 IOPMPowerChangeFlags changeFlags __unused
)
2069 IOPMPowerFlags oldCapability
, newCapability
;
2071 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2072 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2073 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2074 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2076 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
) {
2079 if (oldCapability
== newCapability
) {
2083 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
) {
2084 bool enablePrevention
= ((oldCapability
& kIOPMPreventIdleSleep
) == 0);
2085 bool idleCancelAllowed
= getPMRootDomain()->updatePreventIdleSleepList(
2086 this, enablePrevention
);
2087 #if SUPPORT_IDLE_CANCEL
2088 if (idleCancelAllowed
&& enablePrevention
) {
2089 IOPMRequest
* cancelRequest
;
2091 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2092 if (cancelRequest
) {
2093 submitPMRequest( cancelRequest
);
2099 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
) {
2100 getPMRootDomain()->updatePreventSystemSleepList(this,
2101 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2105 //*********************************************************************************
2106 // [public] requestPowerDomainState
2108 // Called on a power parent when a child's power requirement changes.
2109 //*********************************************************************************
2112 IOService::requestPowerDomainState(
2113 IOPMPowerFlags childRequestPowerFlags
,
2114 IOPowerConnection
* childConnection
,
2115 unsigned long specification
)
2117 IOPMPowerStateIndex order
, powerState
;
2118 IOPMPowerFlags outputPowerFlags
;
2120 IOPMRequest
* subRequest
;
2121 bool adjustPower
= false;
2124 return IOPMNotYetInitialized
;
2127 if (gIOPMWorkLoop
->onThread() == false) {
2128 PM_LOG("%s::requestPowerDomainState\n", getName());
2129 return kIOReturnSuccess
;
2132 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2134 if (!isChild(childConnection
, gIOPowerPlane
)) {
2135 return kIOReturnNotAttached
;
2138 if (!fControllingDriver
|| !fNumberOfPowerStates
) {
2139 return kIOReturnNotReady
;
2142 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2145 // Remove flags from child request which we can't possibly supply
2146 childRequestPowerFlags
&= fMergedOutputPowerFlags
;
2148 // Merge in the power flags contributed by this power parent
2149 // at its current or impending power state.
2151 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2152 if (fMachineState
!= kIOPM_Finished
) {
2153 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
) {
2154 // Use the lower power state when dropping power.
2155 // Must be careful since a power drop can be cancelled
2156 // from the following states:
2157 // - kIOPM_OurChangeTellClientsPowerDown
2158 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2160 // The child must not wait for this parent to raise power
2161 // if the power drop was cancelled. The solution is to cancel
2162 // the power drop if possible, then schedule an adjustment to
2163 // re-evaluate the parent's power state.
2165 // Root domain is excluded to avoid idle sleep issues. And allow
2166 // root domain children to pop up when system is going to sleep.
2168 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2169 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)) {
2170 fDoNotPowerDown
= true; // cancel power drop
2171 adjustPower
= true;// schedule an adjustment
2172 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2173 getName(), fMachineState
, child
->getName());
2175 // Beyond cancellation point, report the impending state.
2177 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2179 } else if (IS_POWER_RISE
) {
2180 // When raising power, must report the output power flags from
2181 // child's perspective. A child power request may arrive while
2182 // parent is transitioning upwards. If a request arrives after
2183 // setParentInfo() has already recorded the output power flags
2184 // for the next power state, then using the power supplied by
2185 // fCurrentPowerState is incorrect, and might cause the child
2186 // to wait when it should not.
2188 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2191 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2193 // Map child's requested power flags to one of our power state.
2195 for (order
= 0; order
< fNumberOfPowerStates
; order
++) {
2196 powerState
= fPowerStates
[order
].stateOrderToIndex
;
2197 if ((fPowerStates
[powerState
].outputPowerFlags
& childRequestPowerFlags
)
2198 == childRequestPowerFlags
) {
2202 if (order
>= fNumberOfPowerStates
) {
2203 powerState
= kPowerStateZero
;
2206 // Conditions that warrants a power adjustment on this parent.
2207 // Adjust power will also propagate any changes to the child's
2208 // prevent idle/sleep flags towards the root domain.
2210 if (!childConnection
->childHasRequestedPower() ||
2211 (powerState
!= childConnection
->getDesiredDomainState())) {
2215 #if ENABLE_DEBUG_LOGS
2217 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2218 getName(), child
->getName(),
2219 !childConnection
->childHasRequestedPower(),
2220 (uint32_t) childConnection
->getDesiredDomainState(),
2221 (uint32_t) powerState
);
2225 // Record the child's desires on the connection.
2226 childConnection
->setChildHasRequestedPower();
2227 childConnection
->setDesiredDomainState( powerState
);
2229 // Schedule a request to re-evaluate all children desires and
2230 // adjust power state. Submit a request if one wasn't pending,
2231 // or if the current request is part of a call tree.
2233 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2234 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest())) {
2235 subRequest
= acquirePMRequest(
2236 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2238 submitPMRequest( subRequest
);
2239 fAdjustPowerScheduled
= true;
2243 return kIOReturnSuccess
;
2246 //*********************************************************************************
2247 // [public] temporaryPowerClampOn
2249 // A power domain wants to clamp its power on till it has children which
2250 // will thendetermine the power domain state.
2252 // We enter the highest state until addPowerChild is called.
2253 //*********************************************************************************
2256 IOService::temporaryPowerClampOn( void )
2258 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2261 //*********************************************************************************
2262 // [public] makeUsable
2264 // Some client of our device is asking that we become usable. Although
2265 // this has not come from a subclassed device object, treat it exactly
2266 // as if it had. In this way, subsequent requests for lower power from
2267 // a subclassed device object will pre-empt this request.
2269 // We treat this as a subclass object request to switch to the
2270 // highest power state.
2271 //*********************************************************************************
2274 IOService::makeUsable( void )
2276 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2277 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2280 //*********************************************************************************
2281 // [public] currentCapability
2282 //*********************************************************************************
2285 IOService::currentCapability( void )
2288 return IOPMNotPowerManaged
;
2291 return fCurrentCapabilityFlags
;
2294 //*********************************************************************************
2295 // [public] changePowerStateTo
2297 // Called by our power-controlling driver to change power state. The new desired
2298 // power state is computed and compared against the current power state. If those
2299 // power states differ, then a power state change is initiated.
2300 //*********************************************************************************
2303 IOService::changePowerStateTo( unsigned long ordinal
)
2305 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2306 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2309 //*********************************************************************************
2310 // [protected] changePowerStateToPriv
2312 // Called by our driver subclass to change power state. The new desired power
2313 // state is computed and compared against the current power state. If those
2314 // power states differ, then a power state change is initiated.
2315 //*********************************************************************************
2318 IOService::changePowerStateToPriv( unsigned long ordinal
)
2320 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2321 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2324 //*********************************************************************************
2325 // [public] changePowerStateWithOverrideTo
2327 // Called by our driver subclass to change power state. The new desired power
2328 // state is computed and compared against the current power state. If those
2329 // power states differ, then a power state change is initiated.
2330 // Override enforced - Children and Driver desires are ignored.
2331 //*********************************************************************************
2334 IOService::changePowerStateWithOverrideTo( IOPMPowerStateIndex ordinal
,
2335 IOPMRequestTag tag
)
2337 IOPMRequest
* request
;
2340 return kIOPMNotYetInitialized
;
2343 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2345 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2347 return kIOReturnNoMemory
;
2350 gIOPMPowerClientDevice
->retain();
2351 request
->fRequestTag
= tag
;
2352 request
->fArg0
= (void *) ordinal
;
2353 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2354 request
->fArg2
= NULL
;
2357 request
->installCompletionAction( action
, target
, param
);
2361 // Prevent needless downwards power transitions by clamping power
2362 // until the scheduled request is executed.
2364 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
)) {
2365 fTempClampPowerState
= StateMax(fTempClampPowerState
, ordinal
);
2367 fOverrideMaxPowerState
= ordinal
;
2368 request
->fArg2
= (void *) (uintptr_t) true;
2371 submitPMRequest( request
);
2375 //*********************************************************************************
2376 // [public] changePowerStateForRootDomain
2378 // Adjust the root domain's power desire on the target
2379 //*********************************************************************************
2382 IOService::changePowerStateForRootDomain( IOPMPowerStateIndex ordinal
)
2384 OUR_PMLog(kPMLogChangeStateForRootDomain
, ordinal
, 0);
2385 return requestPowerState( gIOPMPowerClientRootDomain
, ordinal
);
2388 //*********************************************************************************
2389 // [public for PMRD] quiescePowerTree
2391 // For root domain to issue a request to quiesce the power tree.
2392 // Supplied callback invoked upon completion.
2393 //*********************************************************************************
2396 IOService::quiescePowerTree(
2397 void * target
, IOPMCompletionAction action
, void * param
)
2399 IOPMRequest
* request
;
2402 return kIOPMNotYetInitialized
;
2404 if (!target
|| !action
) {
2405 return kIOReturnBadArgument
;
2408 OUR_PMLog(kPMLogQuiescePowerTree
, 0, 0);
2410 // Target the root node instead of root domain. This is to avoid blocking
2411 // the quiesce request behind an existing root domain request in the work
2412 // queue. Root parent and root domain requests in the work queue must not
2413 // block the completion of the quiesce request.
2415 request
= acquirePMRequest(gIOPMRootNode
, kIOPMRequestTypeQuiescePowerTree
);
2417 return kIOReturnNoMemory
;
2420 request
->installCompletionAction(target
, action
, param
);
2422 // Submit through the normal request flow. This will make sure any request
2423 // already in the request queue will get pushed over to the work queue for
2424 // execution. Any request submitted after this request may not be serviced.
2426 submitPMRequest( request
);
2427 return kIOReturnSuccess
;
2430 //*********************************************************************************
2431 // [private] requestPowerState
2432 //*********************************************************************************
2435 IOService::requestPowerState(
2436 const OSSymbol
* client
,
2439 IOPMRequest
* request
;
2442 return kIOReturnBadArgument
;
2445 return kIOPMNotYetInitialized
;
2448 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2450 return kIOReturnNoMemory
;
2454 request
->fArg0
= (void *)(uintptr_t) state
;
2455 request
->fArg1
= (void *) client
;
2456 request
->fArg2
= NULL
;
2459 request
->installCompletionAction( action
, target
, param
);
2463 // Prevent needless downwards power transitions by clamping power
2464 // until the scheduled request is executed.
2466 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
)) {
2467 fTempClampPowerState
= StateMax(fTempClampPowerState
, state
);
2469 request
->fArg2
= (void *) (uintptr_t) true;
2472 submitPMRequest( request
);
2476 //*********************************************************************************
2477 // [private] handleRequestPowerState
2478 //*********************************************************************************
2481 IOService::handleRequestPowerState( IOPMRequest
* request
)
2483 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2484 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2486 PM_ASSERT_IN_GATE();
2487 if (request
->fArg2
) {
2488 assert(fTempClampCount
!= 0);
2489 if (fTempClampCount
) {
2492 if (!fTempClampCount
) {
2493 fTempClampPowerState
= kPowerStateZero
;
2497 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
)) {
2498 state
= fHighestPowerState
;
2501 // The power suppression due to changePowerStateWithOverrideTo() expires
2502 // upon the next "device" power request - changePowerStateToPriv().
2504 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2505 (client
== gIOPMPowerClientDevice
)) {
2506 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2509 if ((state
== kPowerStateZero
) &&
2510 (client
!= gIOPMPowerClientDevice
) &&
2511 (client
!= gIOPMPowerClientDriver
) &&
2512 (client
!= gIOPMPowerClientChildProxy
)) {
2513 removePowerClient(client
);
2515 updatePowerClient(client
, state
);
2522 //*********************************************************************************
2523 // [private] Helper functions to update/remove power clients.
2524 //*********************************************************************************
2527 IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2529 IOPMPowerStateIndex oldPowerState
= kPowerStateZero
;
2531 if (!fPowerClients
) {
2532 fPowerClients
= OSDictionary::withCapacity(4);
2534 if (fPowerClients
&& client
) {
2535 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2537 oldPowerState
= num
->unsigned32BitValue();
2538 num
->setValue(powerState
);
2540 num
= OSNumber::withNumber(powerState
, 32);
2542 fPowerClients
->setObject(client
, num
);
2547 PM_ACTION_3(actionUpdatePowerClient
, client
, oldPowerState
, powerState
);
2552 IOService::removePowerClient( const OSSymbol
* client
)
2554 if (fPowerClients
&& client
) {
2555 fPowerClients
->removeObject(client
);
2560 IOService::getPowerStateForClient( const OSSymbol
* client
)
2562 uint32_t powerState
= kPowerStateZero
;
2564 if (fPowerClients
&& client
) {
2565 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2567 powerState
= num
->unsigned32BitValue();
2573 //*********************************************************************************
2574 // [protected] powerOverrideOnPriv
2575 //*********************************************************************************
2578 IOService::powerOverrideOnPriv( void )
2580 IOPMRequest
* request
;
2583 return IOPMNotYetInitialized
;
2586 if (gIOPMWorkLoop
->inGate()) {
2587 fDeviceOverrideEnabled
= true;
2591 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2593 return kIOReturnNoMemory
;
2596 submitPMRequest( request
);
2600 //*********************************************************************************
2601 // [protected] powerOverrideOffPriv
2602 //*********************************************************************************
2605 IOService::powerOverrideOffPriv( void )
2607 IOPMRequest
* request
;
2610 return IOPMNotYetInitialized
;
2613 if (gIOPMWorkLoop
->inGate()) {
2614 fDeviceOverrideEnabled
= false;
2618 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2620 return kIOReturnNoMemory
;
2623 submitPMRequest( request
);
2627 //*********************************************************************************
2628 // [private] handlePowerOverrideChanged
2629 //*********************************************************************************
2632 IOService::handlePowerOverrideChanged( IOPMRequest
* request
)
2634 PM_ASSERT_IN_GATE();
2635 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
) {
2636 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2637 fDeviceOverrideEnabled
= true;
2639 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2640 fDeviceOverrideEnabled
= false;
2646 //*********************************************************************************
2647 // [private] computeDesiredState
2648 //*********************************************************************************
2651 IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2655 IOPowerConnection
* connection
;
2656 uint32_t desiredState
= kPowerStateZero
;
2657 uint32_t newPowerState
= kPowerStateZero
;
2658 bool hasChildren
= false;
2660 // Desired power state is always 0 without a controlling driver.
2662 if (!fNumberOfPowerStates
) {
2663 fDesiredPowerState
= kPowerStateZero
;
2667 // Examine the children's desired power state.
2669 iter
= getChildIterator(gIOPowerPlane
);
2671 while ((next
= iter
->getNextObject())) {
2672 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
2673 if (connection
->getReadyFlag() == false) {
2674 PM_LOG3("[%s] %s: connection not ready\n",
2675 getName(), __FUNCTION__
);
2678 if (connection
->childHasRequestedPower()) {
2681 desiredState
= StateMax(connection
->getDesiredDomainState(), desiredState
);
2687 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2689 removePowerClient(gIOPMPowerClientChildren
);
2692 // Iterate through all power clients to determine the min power state.
2694 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2696 const OSSymbol
* client
;
2697 while ((client
= (const OSSymbol
*) iter
->getNextObject())) {
2698 // Ignore child and driver when override is in effect.
2699 if ((fDeviceOverrideEnabled
||
2700 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2701 ((client
== gIOPMPowerClientChildren
) ||
2702 (client
== gIOPMPowerClientDriver
))) {
2706 // Ignore child proxy when children are present.
2707 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
)) {
2711 // Advisory tickles are irrelevant unless system is in full wake
2712 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2713 !gIOPMAdvisoryTickleEnabled
) {
2717 desiredState
= getPowerStateForClient(client
);
2718 assert(desiredState
< fNumberOfPowerStates
);
2720 desiredState
, client
->getCStringNoCopy());
2722 newPowerState
= StateMax(newPowerState
, desiredState
);
2724 if (client
== gIOPMPowerClientDevice
) {
2725 fDeviceDesire
= desiredState
;
2731 // Factor in the temporary power desires.
2733 newPowerState
= StateMax(newPowerState
, localClamp
);
2734 newPowerState
= StateMax(newPowerState
, fTempClampPowerState
);
2736 // Limit check against max power override.
2738 newPowerState
= StateMin(newPowerState
, fOverrideMaxPowerState
);
2740 // Limit check against number of power states.
2742 if (newPowerState
>= fNumberOfPowerStates
) {
2743 newPowerState
= fHighestPowerState
;
2746 if (getPMRootDomain()->isAOTMode()) {
2747 if ((kIOPMPreventIdleSleep
& fPowerStates
[newPowerState
].capabilityFlags
)
2748 && !(kIOPMPreventIdleSleep
& fPowerStates
[fDesiredPowerState
].capabilityFlags
)) {
2749 getPMRootDomain()->claimSystemWakeEvent(this, kIOPMWakeEventAOTExit
, getName(), NULL
);
2753 fDesiredPowerState
= newPowerState
;
2755 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2756 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2757 (uint32_t) fCurrentPowerState
, newPowerState
);
2760 // Restart idle timer if possible when device desire has increased.
2761 // Or if an advisory desire exists.
2763 if (fIdleTimerPeriod
&& fIdleTimerStopped
) {
2767 // Invalidate cached tickle power state when desires change, and not
2768 // due to a tickle request. In case the driver has requested a lower
2769 // power state, but the tickle is caching a higher power state which
2770 // will drop future tickles until the cached value is lowered or in-
2771 // validated. The invalidation must occur before the power transition
2772 // to avoid dropping a necessary tickle.
2774 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2775 (fActivityTicklePowerState
!= kInvalidTicklePowerState
)) {
2776 IOLockLock(fActivityLock
);
2777 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2778 IOLockUnlock(fActivityLock
);
2783 //*********************************************************************************
2784 // [public] currentPowerConsumption
2786 //*********************************************************************************
2789 IOService::currentPowerConsumption( void )
2792 return kIOPMUnknown
;
2795 return fCurrentPowerConsumption
;
2798 //*********************************************************************************
2799 // [deprecated] getPMworkloop
2800 //*********************************************************************************
2804 IOService::getPMworkloop( void )
2806 return gIOPMWorkLoop
;
2812 //*********************************************************************************
2813 // Power Parent/Children Applier
2814 //*********************************************************************************
2817 applyToPowerChildren(
2818 IOService
* service
,
2819 IOServiceApplierFunction applier
,
2821 IOOptionBits options
)
2823 PM_ASSERT_IN_GATE();
2825 IORegistryEntry
* entry
;
2826 IORegistryIterator
* iter
;
2827 IOPowerConnection
* connection
;
2830 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2832 while ((entry
= iter
->getNextObject())) {
2833 // Get child of IOPowerConnection objects
2834 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
))) {
2835 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2837 (*applier
)(child
, context
);
2848 IOService
* service
,
2849 IOServiceApplierFunction applier
,
2851 IOOptionBits options
)
2853 PM_ASSERT_IN_GATE();
2855 IORegistryEntry
* entry
;
2856 IORegistryIterator
* iter
;
2857 IOPowerConnection
* connection
;
2860 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2861 options
| kIORegistryIterateParents
);
2863 while ((entry
= iter
->getNextObject())) {
2864 // Get child of IOPowerConnection objects
2865 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
))) {
2866 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2868 (*applier
)(parent
, context
);
2877 #endif /* NOT_YET */
2880 // MARK: Activity Tickle & Idle Timer
2883 IOService::setAdvisoryTickleEnable( bool enable
)
2885 gIOPMAdvisoryTickleEnabled
= enable
;
2888 //*********************************************************************************
2889 // [public] activityTickle
2891 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2892 // flag to be set, and the device state checked. If the device has been
2893 // powered down, it is powered up again.
2894 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2895 // should be intercepted by a subclass.
2896 //*********************************************************************************
2899 IOService::activityTickle( unsigned long type
, unsigned long stateNumber
)
2901 IOPMRequest
* request
;
2902 bool noPowerChange
= true;
2903 uint32_t tickleFlags
;
2906 return true; // no power change
2908 if ((type
== kIOPMSuperclassPolicy1
) && StateOrder(stateNumber
)) {
2909 IOLockLock(fActivityLock
);
2911 // Record device activity for the idle timer handler.
2913 fDeviceWasActive
= true;
2914 fActivityTickleCount
++;
2915 clock_get_uptime(&fDeviceActiveTimestamp
);
2917 PM_ACTION_0(actionActivityTickle
);
2919 // Record the last tickle power state.
2920 // This helps to filter out redundant tickles as
2921 // this function may be called from the data path.
2923 if ((fActivityTicklePowerState
== kInvalidTicklePowerState
)
2924 || StateOrder(fActivityTicklePowerState
) < StateOrder(stateNumber
)) {
2925 fActivityTicklePowerState
= stateNumber
;
2926 noPowerChange
= false;
2928 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2929 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2931 request
->fArg0
= (void *) stateNumber
;
2932 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2933 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2934 submitPMRequest(request
);
2938 IOLockUnlock(fActivityLock
);
2939 } else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2940 ((stateNumber
= fDeviceUsablePowerState
) != kPowerStateZero
)) {
2941 IOLockLock(fActivityLock
);
2943 fAdvisoryTickled
= true;
2945 if (fAdvisoryTicklePowerState
!= stateNumber
) {
2946 fAdvisoryTicklePowerState
= stateNumber
;
2947 noPowerChange
= false;
2949 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2950 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2952 request
->fArg0
= (void *) stateNumber
;
2953 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2954 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2955 submitPMRequest(request
);
2959 IOLockUnlock(fActivityLock
);
2962 // Returns false if the activityTickle might cause a transition to a
2963 // higher powered state, true otherwise.
2965 return noPowerChange
;
2968 //*********************************************************************************
2969 // [private] handleActivityTickle
2970 //*********************************************************************************
2973 IOService::handleActivityTickle( IOPMRequest
* request
)
2975 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2976 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
2977 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
2978 bool adjustPower
= false;
2980 PM_ASSERT_IN_GATE();
2981 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
)) {
2982 // Drivers that don't want power restored on wake will drop any
2983 // tickles that pre-dates the current system wake. The model is
2984 // that each wake is a fresh start, with power state depressed
2985 // until a new tickle or an explicit power up request from the
2986 // driver. It is possible for the PM work loop to enter the
2987 // system sleep path with tickle requests queued.
2992 if (tickleFlags
& kTickleTypeActivity
) {
2993 IOPMPowerStateIndex deviceDesireOrder
= StateOrder(fDeviceDesire
);
2994 uint32_t idleTimerGeneration
= ticklePowerState
; // kTickleTypePowerDrop
2996 if (tickleFlags
& kTickleTypePowerRise
) {
2997 if ((StateOrder(ticklePowerState
) > deviceDesireOrder
) &&
2998 (ticklePowerState
< fNumberOfPowerStates
)) {
2999 fIdleTimerMinPowerState
= ticklePowerState
;
3000 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
3003 } else if ((deviceDesireOrder
> StateOrder(fIdleTimerMinPowerState
)) &&
3004 (idleTimerGeneration
== fIdleTimerGeneration
)) {
3005 // Power drop due to idle timer expiration.
3006 // Do not allow idle timer to reduce power below tickle power.
3007 // This prevents the idle timer from decreasing the device desire
3008 // to zero and cancelling the effect of a pre-sleep tickle when
3009 // system wakes up to doze state, while the device is unable to
3010 // raise its power state to satisfy the tickle.
3012 deviceDesireOrder
--;
3013 if (deviceDesireOrder
< fNumberOfPowerStates
) {
3014 ticklePowerState
= fPowerStates
[deviceDesireOrder
].stateOrderToIndex
;
3015 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
3019 } else { // advisory tickle
3020 if (tickleFlags
& kTickleTypePowerRise
) {
3021 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
3022 (ticklePowerState
< fNumberOfPowerStates
)) {
3023 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
3024 fHasAdvisoryDesire
= true;
3025 fAdvisoryTickleUsed
= true;
3028 IOLockLock(fActivityLock
);
3029 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3030 IOLockUnlock(fActivityLock
);
3032 } else if (fHasAdvisoryDesire
) {
3033 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
3034 fHasAdvisoryDesire
= false;
3044 //******************************************************************************
3045 // [public] setIdleTimerPeriod
3047 // A subclass policy-maker is using our standard idleness detection service.
3048 // Start the idle timer. Period is in seconds.
3049 //******************************************************************************
3052 IOService::setIdleTimerPeriod( unsigned long period
)
3055 return IOPMNotYetInitialized
;
3058 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
3060 IOPMRequest
* request
=
3061 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
3063 return kIOReturnNoMemory
;
3066 request
->fArg0
= (void *) period
;
3067 submitPMRequest( request
);
3069 return kIOReturnSuccess
;
3073 IOService::setIgnoreIdleTimer( bool ignore
)
3076 return IOPMNotYetInitialized
;
3079 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
3081 IOPMRequest
* request
=
3082 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
3084 return kIOReturnNoMemory
;
3087 request
->fArg0
= (void *) ignore
;
3088 submitPMRequest( request
);
3090 return kIOReturnSuccess
;
3093 //******************************************************************************
3094 // [public] nextIdleTimeout
3096 // Returns how many "seconds from now" the device should idle into its
3097 // next lowest power state.
3098 //******************************************************************************
3101 IOService::nextIdleTimeout(
3102 AbsoluteTime currentTime
,
3103 AbsoluteTime lastActivity
,
3104 unsigned int powerState
)
3111 // Calculate time difference using funky macro from clock.h.
3112 delta
= currentTime
;
3113 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
3115 // Figure it in seconds.
3116 absolutetime_to_nanoseconds(delta
, &delta_ns
);
3117 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
3119 // Be paranoid about delta somehow exceeding timer period.
3120 if (delta_secs
< (int) fIdleTimerPeriod
) {
3121 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3123 delay_secs
= (int) fIdleTimerPeriod
;
3126 return (SInt32
)delay_secs
;
3129 //*********************************************************************************
3130 // [public] start_PM_idle_timer
3131 //*********************************************************************************
3134 IOService::start_PM_idle_timer( void )
3136 static const int maxTimeout
= 100000;
3137 static const int minTimeout
= 1;
3138 AbsoluteTime uptime
, deadline
;
3142 if (!initialized
|| !fIdleTimerPeriod
) {
3146 IOLockLock(fActivityLock
);
3148 clock_get_uptime(&uptime
);
3150 // Subclasses may modify idle sleep algorithm
3151 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3153 // Check for out-of range responses
3154 if (idle_in
> maxTimeout
) {
3155 // use standard implementation
3156 idle_in
= IOService::nextIdleTimeout(uptime
,
3157 fDeviceActiveTimestamp
,
3158 fCurrentPowerState
);
3159 } else if (idle_in
< minTimeout
) {
3160 idle_in
= fIdleTimerPeriod
;
3163 IOLockUnlock(fActivityLock
);
3165 fNextIdleTimerPeriod
= idle_in
;
3166 fIdleTimerStartTime
= uptime
;
3169 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3170 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3171 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3177 //*********************************************************************************
3178 // [private] restartIdleTimer
3179 //*********************************************************************************
3182 IOService::restartIdleTimer( void )
3184 if (fDeviceDesire
!= kPowerStateZero
) {
3185 fIdleTimerStopped
= false;
3186 fActivityTickleCount
= 0;
3187 start_PM_idle_timer();
3188 } else if (fHasAdvisoryDesire
) {
3189 fIdleTimerStopped
= false;
3190 start_PM_idle_timer();
3192 fIdleTimerStopped
= true;
3196 //*********************************************************************************
3197 // idle_timer_expired
3198 //*********************************************************************************
3202 thread_call_param_t arg0
, thread_call_param_t arg1
)
3204 IOService
* me
= (IOService
*) arg0
;
3206 if (gIOPMWorkLoop
) {
3207 gIOPMWorkLoop
->runAction(
3208 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3209 &IOService::idleTimerExpired
),
3216 //*********************************************************************************
3217 // [private] idleTimerExpired
3219 // The idle timer has expired. If there has been activity since the last
3220 // expiration, just restart the timer and return. If there has not been
3221 // activity, switch to the next lower power state and restart the timer.
3222 //*********************************************************************************
3225 IOService::idleTimerExpired( void )
3227 IOPMRequest
* request
;
3228 bool restartTimer
= true;
3229 uint32_t tickleFlags
;
3231 if (!initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3232 fLockedFlags
.PMStop
) {
3236 fIdleTimerStartTime
= 0;
3238 IOLockLock(fActivityLock
);
3240 // Check for device activity (tickles) over last timer period.
3242 if (fDeviceWasActive
) {
3243 // Device was active - do not drop power, restart timer.
3244 fDeviceWasActive
= false;
3245 } else if (!fIdleTimerIgnored
) {
3246 // No device activity - drop power state by one level.
3247 // Decrement the cached tickle power state when possible.
3248 // This value may be kInvalidTicklePowerState before activityTickle()
3249 // is called, but the power drop request must be issued regardless.
3251 if ((fActivityTicklePowerState
!= kInvalidTicklePowerState
) &&
3252 (fActivityTicklePowerState
!= kPowerStateZero
)) {
3253 fActivityTicklePowerState
--;
3256 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3257 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3259 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3260 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3261 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3262 submitPMRequest( request
);
3264 // Do not restart timer until after the tickle request has been
3267 restartTimer
= false;
3271 if (fAdvisoryTickled
) {
3272 fAdvisoryTickled
= false;
3273 } else if (fHasAdvisoryDesire
) {
3274 // Want new tickles to turn into pm request after we drop the lock
3275 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3277 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3278 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3280 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3281 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3282 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3283 submitPMRequest( request
);
3285 // Do not restart timer until after the tickle request has been
3288 restartTimer
= false;
3292 IOLockUnlock(fActivityLock
);
3295 start_PM_idle_timer();
3300 //*********************************************************************************
3301 // [deprecated] PM_idle_timer_expiration
3302 //*********************************************************************************
3305 IOService::PM_idle_timer_expiration( void )
3309 //*********************************************************************************
3310 // [deprecated] command_received
3311 //*********************************************************************************
3314 IOService::command_received( void *statePtr
, void *, void *, void * )
3317 #endif /* !__LP64__ */
3319 //*********************************************************************************
3320 // [public] setAggressiveness
3322 // Pass on the input parameters to all power domain children. All those which are
3323 // power domains will pass it on to their children, etc.
3324 //*********************************************************************************
3327 IOService::setAggressiveness( unsigned long type
, unsigned long newLevel
)
3329 return kIOReturnSuccess
;
3332 //*********************************************************************************
3333 // [public] getAggressiveness
3335 // Called by the user client.
3336 //*********************************************************************************
3339 IOService::getAggressiveness( unsigned long type
, unsigned long * currentLevel
)
3341 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3344 return kIOReturnNotReady
;
3347 return rootDomain
->getAggressiveness( type
, currentLevel
);
3350 //*********************************************************************************
3351 // [public] getPowerState
3353 //*********************************************************************************
3356 IOService::getPowerState( void )
3359 return kPowerStateZero
;
3362 return fCurrentPowerState
;
3366 //*********************************************************************************
3367 // [deprecated] systemWake
3369 // Pass this to all power domain children. All those which are
3370 // power domains will pass it on to their children, etc.
3371 //*********************************************************************************
3374 IOService::systemWake( void )
3378 IOPowerConnection
* connection
;
3379 IOService
* theChild
;
3381 iter
= getChildIterator(gIOPowerPlane
);
3383 while ((next
= iter
->getNextObject())) {
3384 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
3385 if (connection
->getReadyFlag() == false) {
3386 PM_LOG3("[%s] %s: connection not ready\n",
3387 getName(), __FUNCTION__
);
3391 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3393 theChild
->systemWake();
3394 theChild
->release();
3401 if (fControllingDriver
!= NULL
) {
3402 if (fControllingDriver
->didYouWakeSystem()) {
3410 //*********************************************************************************
3411 // [deprecated] temperatureCriticalForZone
3412 //*********************************************************************************
3415 IOService::temperatureCriticalForZone( IOService
* whichZone
)
3417 IOService
* theParent
;
3420 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3422 if (inPlane(gIOPowerPlane
) && !IS_PM_ROOT
) {
3423 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3425 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3428 theParent
->temperatureCriticalForZone(whichZone
);
3429 theParent
->release();
3435 #endif /* !__LP64__ */
3438 // MARK: Power Change (Common)
3440 //*********************************************************************************
3441 // [private] startPowerChange
3443 // All power state changes starts here.
3444 //*********************************************************************************
3447 IOService::startPowerChange(
3448 IOPMPowerChangeFlags changeFlags
,
3449 IOPMPowerStateIndex powerState
,
3450 IOPMPowerFlags domainFlags
,
3451 IOPowerConnection
* parentConnection
,
3452 IOPMPowerFlags parentFlags
)
3454 uint32_t savedPMActionsParam
;
3456 PM_ASSERT_IN_GATE();
3457 assert( fMachineState
== kIOPM_Finished
);
3458 assert( powerState
< fNumberOfPowerStates
);
3460 if (powerState
>= fNumberOfPowerStates
) {
3461 return IOPMAckImplied
;
3464 fIsPreChange
= true;
3465 savedPMActionsParam
= fPMActions
.parameter
;
3466 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3468 // rdar://problem/55040032
3469 // Schedule a power adjustment after removing the power clamp
3470 // to inform our power parent(s) about our latest desired domain
3471 // power state. For a self-initiated change, let OurChangeStart()
3472 // automatically request parent power when necessary.
3473 if (!fAdjustPowerScheduled
&&
3474 ((changeFlags
& kIOPMSelfInitiated
) == 0) &&
3475 ((fPMActions
.parameter
& kPMActionsFlagLimitPower
) == 0) &&
3476 ((savedPMActionsParam
& kPMActionsFlagLimitPower
) != 0)) {
3477 IOPMRequest
* request
= acquirePMRequest(this, kIOPMRequestTypeAdjustPowerState
);
3479 submitPMRequest(request
);
3480 fAdjustPowerScheduled
= true;
3484 if (changeFlags
& kIOPMExpireIdleTimer
) {
3485 // Root domain requested removal of tickle influence
3486 if (StateOrder(fDeviceDesire
) > StateOrder(powerState
)) {
3487 // Reset device desire down to the clamped power state
3488 updatePowerClient(gIOPMPowerClientDevice
, powerState
);
3489 computeDesiredState(kPowerStateZero
, true);
3491 // Invalidate tickle cache so the next tickle will issue a request
3492 IOLockLock(fActivityLock
);
3493 fDeviceWasActive
= false;
3494 fActivityTicklePowerState
= kInvalidTicklePowerState
;
3495 IOLockUnlock(fActivityLock
);
3497 fIdleTimerMinPowerState
= kPowerStateZero
;
3501 // Root domain's override handler may cancel the power change by
3502 // setting the kIOPMNotDone flag.
3504 if (changeFlags
& kIOPMNotDone
) {
3505 return IOPMAckImplied
;
3508 // Forks to either Driver or Parent initiated power change paths.
3510 fHeadNoteChangeFlags
= changeFlags
;
3511 fHeadNotePowerState
= powerState
;
3512 fHeadNotePowerArrayEntry
= &fPowerStates
[powerState
];
3513 fHeadNoteParentConnection
= NULL
;
3515 if (changeFlags
& kIOPMSelfInitiated
) {
3516 if (changeFlags
& kIOPMSynchronize
) {
3523 assert(changeFlags
& kIOPMParentInitiated
);
3524 fHeadNoteDomainFlags
= domainFlags
;
3525 fHeadNoteParentFlags
= parentFlags
;
3526 fHeadNoteParentConnection
= parentConnection
;
3527 return ParentChangeStart();
3531 //*********************************************************************************
3532 // [private] notifyInterestedDrivers
3533 //*********************************************************************************
3536 IOService::notifyInterestedDrivers( void )
3538 IOPMinformee
* informee
;
3539 IOPMinformeeList
* list
= fInterestedDrivers
;
3540 DriverCallParam
* param
;
3542 IOItemCount skipCnt
= 0;
3544 PM_ASSERT_IN_GATE();
3545 assert( fDriverCallParamCount
== 0 );
3546 assert( fHeadNotePendingAcks
== 0 );
3548 fHeadNotePendingAcks
= 0;
3550 count
= list
->numberOfItems();
3552 goto done
; // no interested drivers
3554 // Allocate an array of interested drivers and their return values
3555 // for the callout thread. Everything else is still "owned" by the
3556 // PM work loop, which can run to process acknowledgePowerChange()
3559 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3560 if (count
> fDriverCallParamSlots
) {
3561 if (fDriverCallParamSlots
) {
3562 assert(fDriverCallParamPtr
);
3563 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3564 fDriverCallParamPtr
= NULL
;
3565 fDriverCallParamSlots
= 0;
3568 param
= IONew(DriverCallParam
, count
);
3570 goto done
; // no memory
3572 fDriverCallParamPtr
= (void *) param
;
3573 fDriverCallParamSlots
= count
;
3576 informee
= list
->firstInList();
3578 for (IOItemCount i
= 0; i
< count
; i
++) {
3579 if (fInitialSetPowerState
|| (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)) {
3580 // Skip notifying self, if 'kIOPMInitialDeviceState' is set and
3581 // this is the initial power state change
3582 if ((this == informee
->whatObject
) &&
3583 (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)) {
3588 informee
->timer
= -1;
3589 param
[i
].Target
= informee
;
3591 informee
= list
->nextInList( informee
);
3598 fDriverCallParamCount
= count
;
3599 fHeadNotePendingAcks
= count
;
3601 // Block state machine and wait for callout completion.
3602 assert(!fDriverCallBusy
);
3603 fDriverCallBusy
= true;
3604 thread_call_enter( fDriverCallEntry
);
3608 // Return false if there are no interested drivers or could not schedule
3609 // callout thread due to error.
3613 //*********************************************************************************
3614 // [private] notifyInterestedDriversDone
3615 //*********************************************************************************
3618 IOService::notifyInterestedDriversDone( void )
3620 IOPMinformee
* informee
;
3622 DriverCallParam
* param
;
3626 PM_ASSERT_IN_GATE();
3627 assert( fDriverCallBusy
== false );
3628 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3630 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3631 count
= fDriverCallParamCount
;
3633 if (param
&& count
) {
3634 for (IOItemCount i
= 0; i
< count
; i
++, param
++) {
3635 informee
= (IOPMinformee
*) param
->Target
;
3636 result
= param
->Result
;
3638 if ((result
== IOPMAckImplied
) || (result
< 0)) {
3639 // Interested driver return IOPMAckImplied.
3640 // If informee timer is zero, it must have de-registered
3641 // interest during the thread callout. That also drops
3642 // the pending ack count.
3644 if (fHeadNotePendingAcks
&& informee
->timer
) {
3645 fHeadNotePendingAcks
--;
3648 informee
->timer
= 0;
3649 } else if (informee
->timer
) {
3650 assert(informee
->timer
== -1);
3652 // Driver has not acked, and has returned a positive result.
3653 // Enforce a minimum permissible timeout value.
3654 // Make the min value large enough so timeout is less likely
3655 // to occur if a driver misinterpreted that the return value
3656 // should be in microsecond units. And make it large enough
3657 // to be noticeable if a driver neglects to ack.
3659 if (result
< kMinAckTimeoutTicks
) {
3660 result
= kMinAckTimeoutTicks
;
3663 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3664 if (result
> maxTimeout
) {
3665 maxTimeout
= result
;
3668 // else, child has already acked or driver has removed interest,
3669 // and head_note_pendingAcks decremented.
3670 // informee may have been removed from the interested drivers list,
3671 // thus the informee must be retained across the callout.
3673 informee
->release();
3676 fDriverCallParamCount
= 0;
3678 if (fHeadNotePendingAcks
) {
3679 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3681 getPMRootDomain()->reset_watchdog_timer(this, maxTimeout
/ USEC_PER_SEC
+ 1);
3685 MS_POP(); // pop the machine state passed to notifyAll()
3687 // If interest acks are outstanding, block the state machine until
3688 // fHeadNotePendingAcks drops to zero before notifying root domain.
3689 // Otherwise notify root domain directly.
3691 if (!fHeadNotePendingAcks
) {
3694 MS_PUSH(fMachineState
);
3695 fMachineState
= kIOPM_NotifyChildrenStart
;
3699 //*********************************************************************************
3700 // [private] notifyRootDomain
3701 //*********************************************************************************
3704 IOService::notifyRootDomain( void )
3706 assert( fDriverCallBusy
== false );
3708 // Only for root domain in the will-change phase
3709 if (!IS_ROOT_DOMAIN
|| (fMachineState
!= kIOPM_OurChangeSetPowerState
)) {
3714 MS_PUSH(fMachineState
); // push notifyAll() machine state
3715 fMachineState
= kIOPM_DriverThreadCallDone
;
3717 // Call IOPMrootDomain::willNotifyPowerChildren() on a thread call
3718 // to avoid a deadlock.
3719 fDriverCallReason
= kRootDomainInformPreChange
;
3720 fDriverCallBusy
= true;
3721 thread_call_enter( fDriverCallEntry
);
3725 IOService::notifyRootDomainDone( void )
3727 assert( fDriverCallBusy
== false );
3728 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3730 MS_POP(); // pop notifyAll() machine state
3734 //*********************************************************************************
3735 // [private] notifyChildren
3736 //*********************************************************************************
3739 IOService::notifyChildren( void )
3743 IOPowerConnection
* connection
;
3744 OSArray
* children
= NULL
;
3745 IOPMrootDomain
* rootDomain
;
3746 bool delayNotify
= false;
3748 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3749 (IS_POWER_DROP
== fIsPreChange
) &&
3750 ((rootDomain
= getPMRootDomain()) == this)) {
3751 rootDomain
->tracePoint( IS_POWER_DROP
?
3752 kIOPMTracePointSleepPowerPlaneDrivers
:
3753 kIOPMTracePointWakePowerPlaneDrivers
);
3756 if (fStrictTreeOrder
) {
3757 children
= OSArray::withCapacity(8);
3760 // Sum child power consumption in notifyChild()
3761 fHeadNotePowerArrayEntry
->staticPower
= 0;
3763 iter
= getChildIterator(gIOPowerPlane
);
3765 while ((next
= iter
->getNextObject())) {
3766 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
3767 if (connection
->getReadyFlag() == false) {
3768 PM_LOG3("[%s] %s: connection not ready\n",
3769 getName(), __FUNCTION__
);
3773 // Mechanism to postpone the did-change notification to
3774 // certain power children to order those children last.
3775 // Cannot be used together with strict tree ordering.
3777 if (!fIsPreChange
&&
3778 connection
->delayChildNotification
&&
3779 getPMRootDomain()->shouldDelayChildNotification(this)) {
3781 children
= OSArray::withCapacity(8);
3787 children
->setObject( connection
);
3792 if (!delayNotify
&& children
) {
3793 children
->setObject( connection
);
3795 notifyChild( connection
);
3802 if (children
&& (children
->getCount() == 0)) {
3803 children
->release();
3807 assert(fNotifyChildArray
== NULL
);
3808 fNotifyChildArray
= children
;
3809 MS_PUSH(fMachineState
);
3812 // Block until all non-delayed children have acked their
3813 // notification. Then notify the remaining delayed child
3814 // in the array. This is used to hold off graphics child
3815 // notification while the rest of the system powers up.
3816 // If a hid tickle arrives during this time, the delayed
3817 // children are immediately notified and root domain will
3818 // not clamp power for dark wake.
3820 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3821 PM_LOG2("%s: %d children in delayed array\n",
3822 getName(), children
->getCount());
3824 // Child array created to support strict notification order.
3825 // Notify children in the array one at a time.
3827 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3832 //*********************************************************************************
3833 // [private] notifyChildrenOrdered
3834 //*********************************************************************************
3837 IOService::notifyChildrenOrdered( void )
3839 PM_ASSERT_IN_GATE();
3840 assert(fNotifyChildArray
);
3841 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3843 // Notify one child, wait for it to ack, then repeat for next child.
3844 // This is a workaround for some drivers with multiple instances at
3845 // the same branch in the power tree, but the driver is slow to power
3846 // up unless the tree ordering is observed. Problem observed only on
3847 // system wake, not on system sleep.
3849 // We have the ability to power off in reverse child index order.
3850 // That works nicely on some machines, but not on all HW configs.
3852 if (fNotifyChildArray
->getCount()) {
3853 IOPowerConnection
* connection
;
3854 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3855 notifyChild( connection
);
3856 fNotifyChildArray
->removeObject(0);
3858 fNotifyChildArray
->release();
3859 fNotifyChildArray
= NULL
;
3861 MS_POP(); // pushed by notifyChildren()
3865 //*********************************************************************************
3866 // [private] notifyChildrenDelayed
3867 //*********************************************************************************
3870 IOService::notifyChildrenDelayed( void )
3872 IOPowerConnection
* connection
;
3874 PM_ASSERT_IN_GATE();
3875 assert(fNotifyChildArray
);
3876 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3878 // Wait after all non-delayed children and interested drivers have ack'ed,
3879 // then notify all delayed children. If notify delay is canceled, child
3880 // acks may be outstanding with PM blocked on fHeadNotePendingAcks != 0.
3881 // But the handling for either case is identical.
3883 for (int i
= 0;; i
++) {
3884 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3889 notifyChild( connection
);
3892 PM_LOG2("%s: notified delayed children\n", getName());
3893 fNotifyChildArray
->release();
3894 fNotifyChildArray
= NULL
;
3896 MS_POP(); // pushed by notifyChildren()
3899 //*********************************************************************************
3900 // [private] notifyAll
3901 //*********************************************************************************
3904 IOService::notifyAll( uint32_t nextMS
)
3906 // Save the machine state to be restored by notifyInterestedDriversDone()
3908 PM_ASSERT_IN_GATE();
3910 fMachineState
= kIOPM_DriverThreadCallDone
;
3911 fDriverCallReason
= fIsPreChange
?
3912 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3914 if (!notifyInterestedDrivers()) {
3915 notifyInterestedDriversDone();
3918 return IOPMWillAckLater
;
3921 //*********************************************************************************
3922 // [private, static] pmDriverCallout
3924 // Thread call context
3925 //*********************************************************************************
3928 IOService::actionDriverCalloutDone(
3930 void * arg0
, void * arg1
,
3931 void * arg2
, void * arg3
)
3933 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3935 assert( fDriverCallBusy
);
3936 fDriverCallBusy
= false;
3938 assert(gIOPMWorkQueue
);
3939 gIOPMWorkQueue
->signalWorkAvailable();
3941 return kIOReturnSuccess
;
3945 IOService::pmDriverCallout( IOService
* from
)
3948 switch (from
->fDriverCallReason
) {
3949 case kDriverCallSetPowerState
:
3950 from
->driverSetPowerState();
3953 case kDriverCallInformPreChange
:
3954 case kDriverCallInformPostChange
:
3955 from
->driverInformPowerChange();
3958 case kRootDomainInformPreChange
:
3959 getPMRootDomain()->willNotifyPowerChildren(from
->fHeadNotePowerState
);
3963 panic("IOService::pmDriverCallout bad machine state %x",
3964 from
->fDriverCallReason
);
3967 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3969 /* arg0 */ (void *) from
->pwrMgt
);
3972 //*********************************************************************************
3973 // [private] driverSetPowerState
3975 // Thread call context
3976 //*********************************************************************************
3979 IOService::driverSetPowerState( void )
3981 IOPMPowerStateIndex powerState
;
3982 DriverCallParam
* param
;
3983 IOPMDriverCallEntry callEntry
;
3986 uint32_t oldPowerState
= getPowerState();
3988 assert( fDriverCallBusy
);
3989 assert( fDriverCallParamPtr
);
3990 assert( fDriverCallParamCount
== 1 );
3992 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3993 powerState
= fHeadNotePowerState
;
3995 if (assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetPowerState
)) {
3996 OUR_PMLogFuncStart(kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3997 clock_get_uptime(&fDriverCallStartTime
);
3998 result
= fControllingDriver
->setPowerState( powerState
, this );
3999 clock_get_uptime(&end
);
4000 OUR_PMLogFuncEnd(kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
4002 deassertPMDriverCall(&callEntry
);
4004 // Record the most recent max power state residency timings.
4005 // Use with DeviceActiveTimestamp to diagnose tickle issues.
4006 if (powerState
== fHighestPowerState
) {
4007 fMaxPowerStateEntryTime
= end
;
4008 } else if (oldPowerState
== fHighestPowerState
) {
4009 fMaxPowerStateExitTime
= end
;
4013 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
4014 fName
, OBFUSCATE(this), fCurrentPowerState
, powerState
, result
);
4018 if ((result
== IOPMAckImplied
) || (result
< 0)) {
4021 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
4022 absolutetime_to_nanoseconds(end
, &nsec
);
4023 if (nsec
> LOG_SETPOWER_TIMES
) {
4024 getPMRootDomain()->pmStatsRecordApplicationResponse(
4025 gIOPMStatsDriverPSChangeSlow
,
4026 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
4031 result
= kIOPMAckImplied
;
4034 param
->Result
= result
;
4037 //*********************************************************************************
4038 // [private] driverInformPowerChange
4040 // Thread call context
4041 //*********************************************************************************
4044 IOService::driverInformPowerChange( void )
4046 IOPMinformee
* informee
;
4048 DriverCallParam
* param
;
4049 IOPMDriverCallEntry callEntry
;
4050 IOPMPowerFlags powerFlags
;
4051 IOPMPowerStateIndex powerState
;
4055 IOOptionBits callMethod
= (fDriverCallReason
== kDriverCallInformPreChange
) ?
4056 kIOPMDriverCallMethodWillChange
: kIOPMDriverCallMethodDidChange
;
4058 assert( fDriverCallBusy
);
4059 assert( fDriverCallParamPtr
);
4060 assert( fDriverCallParamCount
);
4062 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4063 count
= fDriverCallParamCount
;
4065 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4066 powerState
= fHeadNotePowerState
;
4068 for (IOItemCount i
= 0; i
< count
; i
++) {
4069 informee
= (IOPMinformee
*) param
->Target
;
4070 driver
= informee
->whatObject
;
4072 if (assertPMDriverCall(&callEntry
, callMethod
, informee
)) {
4073 if (fDriverCallReason
== kDriverCallInformPreChange
) {
4074 OUR_PMLogFuncStart(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
4075 clock_get_uptime(&informee
->startTime
);
4076 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
4077 clock_get_uptime(&end
);
4078 OUR_PMLogFuncEnd(kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
4080 OUR_PMLogFuncStart(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
4081 clock_get_uptime(&informee
->startTime
);
4082 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
4083 clock_get_uptime(&end
);
4084 OUR_PMLogFuncEnd(kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
4087 deassertPMDriverCall(&callEntry
);
4090 if ((result
== IOPMAckImplied
) || (result
< 0)) {
4093 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
4094 absolutetime_to_nanoseconds(end
, &nsec
);
4095 if (nsec
> LOG_SETPOWER_TIMES
) {
4096 getPMRootDomain()->pmStatsRecordApplicationResponse(
4097 gIOPMStatsDriverPSChangeSlow
, driver
->getName(),
4098 fDriverCallReason
, NS_TO_MS(nsec
), driver
->getRegistryEntryID(),
4103 result
= kIOPMAckImplied
;
4106 param
->Result
= result
;
4111 //*********************************************************************************
4112 // [private] notifyChild
4114 // Notify a power domain child of an upcoming power change.
4115 // If the object acknowledges the current change, we return TRUE.
4116 //*********************************************************************************
4119 IOService::notifyChild( IOPowerConnection
* theNub
)
4121 IOReturn ret
= IOPMAckImplied
;
4122 unsigned long childPower
;
4123 IOService
* theChild
;
4124 IOPMRequest
* childRequest
;
4125 IOPMPowerChangeFlags requestArg2
;
4128 PM_ASSERT_IN_GATE();
4129 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
4134 // Unless the child handles the notification immediately and returns
4135 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4136 fHeadNotePendingAcks
++;
4137 theNub
->setAwaitingAck(true);
4139 requestArg2
= fHeadNoteChangeFlags
;
4140 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
)) {
4141 requestArg2
|= kIOPMDomainPowerDrop
;
4144 requestType
= fIsPreChange
?
4145 kIOPMRequestTypePowerDomainWillChange
:
4146 kIOPMRequestTypePowerDomainDidChange
;
4148 childRequest
= acquirePMRequest( theChild
, requestType
);
4151 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4152 childRequest
->fArg1
= (void *) theNub
;
4153 childRequest
->fArg2
= (void *)(uintptr_t) requestArg2
;
4154 theChild
->submitPMRequest( childRequest
);
4155 ret
= IOPMWillAckLater
;
4157 ret
= IOPMAckImplied
;
4158 fHeadNotePendingAcks
--;
4159 theNub
->setAwaitingAck(false);
4160 childPower
= theChild
->currentPowerConsumption();
4161 if (childPower
== kIOPMUnknown
) {
4162 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4164 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
) {
4165 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4170 theChild
->release();
4171 return IOPMAckImplied
== ret
;
4174 //*********************************************************************************
4175 // [private] notifyControllingDriver
4176 //*********************************************************************************
4179 IOService::notifyControllingDriver( void )
4181 DriverCallParam
* param
;
4183 PM_ASSERT_IN_GATE();
4184 assert( fDriverCallParamCount
== 0 );
4185 assert( fControllingDriver
);
4187 if (fInitialSetPowerState
) {
4188 fInitialSetPowerState
= false;
4189 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4191 // Driver specified flag to skip the inital setPowerState()
4192 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
) {
4197 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4199 param
= IONew(DriverCallParam
, 1);
4201 return false; // no memory
4203 fDriverCallParamPtr
= (void *) param
;
4204 fDriverCallParamSlots
= 1;
4207 param
->Target
= fControllingDriver
;
4208 fDriverCallParamCount
= 1;
4211 // Block state machine and wait for callout completion.
4212 assert(!fDriverCallBusy
);
4213 fDriverCallBusy
= true;
4214 thread_call_enter( fDriverCallEntry
);
4219 //*********************************************************************************
4220 // [private] notifyControllingDriverDone
4221 //*********************************************************************************
4224 IOService::notifyControllingDriverDone( void )
4226 DriverCallParam
* param
;
4229 PM_ASSERT_IN_GATE();
4230 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4232 assert( fDriverCallBusy
== false );
4233 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4235 if (param
&& fDriverCallParamCount
) {
4236 assert(fDriverCallParamCount
== 1);
4238 // the return value from setPowerState()
4239 result
= param
->Result
;
4241 if ((result
== IOPMAckImplied
) || (result
< 0)) {
4243 } else if (fDriverTimer
) {
4244 assert(fDriverTimer
== -1);
4246 // Driver has not acked, and has returned a positive result.
4247 // Enforce a minimum permissible timeout value.
4248 // Make the min value large enough so timeout is less likely
4249 // to occur if a driver misinterpreted that the return value
4250 // should be in microsecond units. And make it large enough
4251 // to be noticeable if a driver neglects to ack.
4253 if (result
< kMinAckTimeoutTicks
) {
4254 result
= kMinAckTimeoutTicks
;
4257 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4259 // else, child has already acked and driver_timer reset to 0.
4261 fDriverCallParamCount
= 0;
4264 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4266 getPMRootDomain()->reset_watchdog_timer(this, result
/ USEC_PER_SEC
+ 1);
4270 MS_POP(); // pushed by OurChangeSetPowerState()
4271 fIsPreChange
= false;
4274 //*********************************************************************************
4275 // [private] all_done
4277 // A power change is done.
4278 //*********************************************************************************
4281 IOService::all_done( void )
4283 IOPMPowerStateIndex prevPowerState
;
4284 const IOPMPSEntry
* powerStatePtr
;
4285 IOPMDriverCallEntry callEntry
;
4286 uint32_t prevMachineState
= fMachineState
;
4287 bool actionCalled
= false;
4290 fMachineState
= kIOPM_Finished
;
4292 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4293 ((prevMachineState
== kIOPM_Finished
) ||
4294 (prevMachineState
== kIOPM_SyncFinish
))) {
4295 // Sync operation and no power change occurred.
4296 // Do not inform driver and clients about this request completion,
4297 // except for the originator (root domain).
4299 PM_ACTION_2(actionPowerChangeDone
,
4300 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4302 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
) {
4303 powerChangeDone(fCurrentPowerState
);
4304 } else if (fAdvisoryTickleUsed
) {
4305 // Not root domain and advisory tickle target.
4306 // Re-adjust power after power tree sync at the 'did' pass
4307 // to recompute desire and adjust power state between dark
4308 // and full wake transitions. Root domain is responsible
4309 // for calling setAdvisoryTickleEnable() before starting
4310 // the kIOPMSynchronize power change.
4312 if (!fAdjustPowerScheduled
&&
4313 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
)) {
4314 IOPMRequest
* request
;
4315 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4317 submitPMRequest( request
);
4318 fAdjustPowerScheduled
= true;
4327 if (fHeadNoteChangeFlags
& kIOPMSelfInitiated
) {
4328 // power state changed
4329 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0) {
4330 trackSystemSleepPreventers(
4331 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4333 // we changed, tell our parent
4334 requestDomainPower(fHeadNotePowerState
);
4336 // yes, did power raise?
4337 if (StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
)) {
4338 // yes, inform clients and apps
4339 tellChangeUp(fHeadNotePowerState
);
4341 prevPowerState
= fCurrentPowerState
;
4343 fCurrentPowerState
= fHeadNotePowerState
;
4346 ts
= mach_absolute_time();
4347 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4351 fPMVars
->myCurrentState
= fCurrentPowerState
;
4353 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4354 PM_ACTION_2(actionPowerChangeDone
,
4355 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4356 actionCalled
= true;
4358 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4359 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4360 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
) {
4361 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4364 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
) {
4365 // Bump tickle generation count once the entire tree is down
4366 gIOPMTickleGeneration
++;
4369 // inform subclass policy-maker
4370 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4371 assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodChangeDone
, NULL
, kIOPMDriverCallNoInactiveCheck
)) {
4372 powerChangeDone(prevPowerState
);
4373 deassertPMDriverCall(&callEntry
);
4375 } else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
) {
4376 // changePowerStateWithOverrideTo() was cancelled
4377 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4381 // parent-initiated power change
4382 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
4383 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
) {
4384 ParentChangeRootChangeDown();
4387 // power state changed
4388 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0) {
4389 trackSystemSleepPreventers(
4390 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4393 if (StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
)) {
4394 // yes, inform clients and apps
4395 tellChangeUp(fHeadNotePowerState
);
4398 prevPowerState
= fCurrentPowerState
;
4399 fCurrentPowerState
= fHeadNotePowerState
;
4402 ts
= mach_absolute_time();
4403 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4407 fPMVars
->myCurrentState
= fCurrentPowerState
;
4410 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4411 PM_ACTION_2(actionPowerChangeDone
,
4412 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4413 actionCalled
= true;
4415 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4416 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4417 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
) {
4418 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4421 // inform subclass policy-maker
4422 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4423 assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodChangeDone
, NULL
, kIOPMDriverCallNoInactiveCheck
)) {
4424 powerChangeDone(prevPowerState
);
4425 deassertPMDriverCall(&callEntry
);
4430 // When power rises enough to satisfy the tickle's desire for more power,
4431 // the condition preventing idle-timer from dropping power is removed.
4433 if (StateOrder(fCurrentPowerState
) >= StateOrder(fIdleTimerMinPowerState
)) {
4434 fIdleTimerMinPowerState
= kPowerStateZero
;
4437 if (!actionCalled
) {
4438 PM_ACTION_2(actionPowerChangeDone
,
4439 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4444 // MARK: Power Change Initiated by Driver
4446 //*********************************************************************************
4447 // [private] OurChangeStart
4449 // Begin the processing of a power change initiated by us.
4450 //*********************************************************************************
4453 IOService::OurChangeStart( void )
4455 PM_ASSERT_IN_GATE();
4456 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4458 // fMaxPowerState is our maximum possible power state based on the current
4459 // power state of our parents. If we are trying to raise power beyond the
4460 // maximum, send an async request for more power to all parents.
4462 if (!IS_PM_ROOT
&& (StateOrder(fMaxPowerState
) < StateOrder(fHeadNotePowerState
))) {
4463 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4464 requestDomainPower(fHeadNotePowerState
);
4469 // Redundant power changes skips to the end of the state machine.
4471 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
)) {
4475 fInitialPowerChange
= false;
4477 // Change started, but may not complete...
4478 // Can be canceled (power drop) or deferred (power rise).
4480 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4482 // Two separate paths, depending if power is being raised or lowered.
4483 // Lowering power is subject to approval by clients of this service.
4485 if (IS_POWER_DROP
) {
4486 fDoNotPowerDown
= false;
4488 // Ask for persmission to drop power state
4489 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4490 fOutOfBandParameter
= kNotifyApps
;
4491 askChangeDown(fHeadNotePowerState
);
4493 // This service is raising power and parents are able to support the
4494 // new power state. However a parent may have already committed to
4495 // drop power, which might force this object to temporarily drop power.
4496 // This results in "oscillations" before the state machines converge
4497 // to a steady state.
4499 // To prevent this, a child must make a power reservation against all
4500 // parents before raising power. If the reservation fails, indicating
4501 // that the child will be unable to sustain the higher power state,
4502 // then the child will signal the parent to adjust power, and the child
4503 // will defer its power change.
4507 // Reserve parent power necessary to achieve fHeadNotePowerState.
4508 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4509 if (ret
!= kIOReturnSuccess
) {
4510 // Reservation failed, defer power rise.
4511 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4516 OurChangeTellCapabilityWillChange();
4520 //*********************************************************************************
4521 // [private] requestDomainPowerApplier
4523 // Call requestPowerDomainState() on all power parents.
4524 //*********************************************************************************
4526 struct IOPMRequestDomainPowerContext
{
4527 IOService
* child
; // the requesting child
4528 IOPMPowerFlags requestPowerFlags
;// power flags requested by child
4532 requestDomainPowerApplier(
4533 IORegistryEntry
* entry
,
4536 IOPowerConnection
* connection
;
4538 IOPMRequestDomainPowerContext
* context
;
4540 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == NULL
) {
4543 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4549 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4551 if (connection
->parentKnowsState() && connection
->getReadyFlag()) {
4552 parent
->requestPowerDomainState(
4553 context
->requestPowerFlags
,
4561 //*********************************************************************************
4562 // [private] requestDomainPower
4564 // Called by a power child to broadcast its desired power state to all parents.
4565 // If the child self-initiates a power change, it must call this function to
4566 // allow its parents to adjust power state.
4567 //*********************************************************************************
4570 IOService::requestDomainPower(
4571 IOPMPowerStateIndex ourPowerState
,
4572 IOOptionBits options
)
4574 IOPMPowerFlags requestPowerFlags
;
4575 IOPMPowerStateIndex maxPowerState
;
4576 IOPMRequestDomainPowerContext context
;
4578 PM_ASSERT_IN_GATE();
4579 assert(ourPowerState
< fNumberOfPowerStates
);
4580 if (ourPowerState
>= fNumberOfPowerStates
) {
4581 return kIOReturnBadArgument
;
4584 return kIOReturnSuccess
;
4587 // Fetch our input power flags for the requested power state.
4588 // Parent request is stated in terms of required power flags.
4590 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4592 // Disregard the "previous request" for power reservation.
4594 if (((options
& kReserveDomainPower
) == 0) &&
4595 (fPreviousRequestPowerFlags
== requestPowerFlags
)) {
4596 // skip if domain already knows our requirements
4599 fPreviousRequestPowerFlags
= requestPowerFlags
;
4601 // The results will be collected by fHeadNoteDomainTargetFlags
4602 context
.child
= this;
4603 context
.requestPowerFlags
= requestPowerFlags
;
4604 fHeadNoteDomainTargetFlags
= 0;
4605 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4607 if (options
& kReserveDomainPower
) {
4608 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4609 fHeadNoteDomainTargetFlags
);
4611 if (StateOrder(maxPowerState
) < StateOrder(ourPowerState
)) {
4612 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4614 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4615 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4616 return kIOReturnNoPower
;
4621 return kIOReturnSuccess
;
4624 //*********************************************************************************
4625 // [private] OurSyncStart
4626 //*********************************************************************************
4629 IOService::OurSyncStart( void )
4631 PM_ASSERT_IN_GATE();
4633 if (fInitialPowerChange
) {
4637 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4639 if (fHeadNoteChangeFlags
& kIOPMNotDone
) {
4644 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
) {
4645 fDoNotPowerDown
= false;
4647 // Ask for permission to drop power state
4648 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4649 fOutOfBandParameter
= kNotifyApps
;
4650 askChangeDown(fHeadNotePowerState
);
4652 // Only inform capability app and clients.
4653 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4657 //*********************************************************************************
4658 // [private] OurChangeTellClientsPowerDown
4660 // All applications and kernel clients have acknowledged our permission to drop
4661 // power. Here we notify them that we will lower the power and wait for acks.
4662 //*********************************************************************************
4665 IOService::OurChangeTellClientsPowerDown( void )
4667 if (!IS_ROOT_DOMAIN
) {
4668 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4670 fMachineState
= kIOPM_OurChangeTellUserPMPolicyPowerDown
;
4672 tellChangeDown1(fHeadNotePowerState
);
4675 //*********************************************************************************
4676 // [private] OurChangeTellUserPMPolicyPowerDown
4678 // All applications and kernel clients have acknowledged our permission to drop
4679 // power. Here we notify power management policy in user-space and wait for acks
4680 // one last time before we lower power
4681 //*********************************************************************************
4683 IOService::OurChangeTellUserPMPolicyPowerDown( void )
4685 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4686 fOutOfBandParameter
= kNotifyApps
;
4688 tellClientsWithResponse(kIOPMMessageLastCallBeforeSleep
);
4691 //*********************************************************************************
4692 // [private] OurChangeTellPriorityClientsPowerDown
4694 // All applications and kernel clients have acknowledged our intention to drop
4695 // power. Here we notify "priority" clients that we are lowering power.
4696 //*********************************************************************************
4699 IOService::OurChangeTellPriorityClientsPowerDown( void )
4701 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4702 tellChangeDown2(fHeadNotePowerState
);
4705 //*********************************************************************************
4706 // [private] OurChangeTellCapabilityWillChange
4708 // Extra stage for root domain to notify apps and drivers about the
4709 // system capability change when raising power state.
4710 //*********************************************************************************
4713 IOService::OurChangeTellCapabilityWillChange( void )
4715 if (!IS_ROOT_DOMAIN
) {
4716 return OurChangeNotifyInterestedDriversWillChange();
4719 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4722 //*********************************************************************************
4723 // [private] OurChangeNotifyInterestedDriversWillChange
4725 // All applications and kernel clients have acknowledged our power state change.
4726 // Here we notify interested drivers pre-change.
4727 //*********************************************************************************
4730 IOService::OurChangeNotifyInterestedDriversWillChange( void )
4732 IOPMrootDomain
* rootDomain
;
4733 if ((rootDomain
= getPMRootDomain()) == this) {
4734 if (IS_POWER_DROP
) {
4735 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4737 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4741 notifyAll( kIOPM_OurChangeSetPowerState
);
4744 //*********************************************************************************
4745 // [private] OurChangeSetPowerState
4747 // Instruct our controlling driver to program the hardware for the power state
4748 // change. Wait for async completions.
4749 //*********************************************************************************
4752 IOService::OurChangeSetPowerState( void )
4754 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4755 fMachineState
= kIOPM_DriverThreadCallDone
;
4756 fDriverCallReason
= kDriverCallSetPowerState
;
4758 if (notifyControllingDriver() == false) {
4759 notifyControllingDriverDone();
4763 //*********************************************************************************
4764 // [private] OurChangeWaitForPowerSettle
4766 // Our controlling driver has completed the power state change we initiated.
4767 // Wait for the driver specified settle time to expire.
4768 //*********************************************************************************
4771 IOService::OurChangeWaitForPowerSettle( void )
4773 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4777 //*********************************************************************************
4778 // [private] OurChangeNotifyInterestedDriversDidChange
4780 // Power has settled on a power change we initiated. Here we notify
4781 // all our interested drivers post-change.
4782 //*********************************************************************************
4785 IOService::OurChangeNotifyInterestedDriversDidChange( void )
4787 IOPMrootDomain
* rootDomain
;
4788 if ((rootDomain
= getPMRootDomain()) == this) {
4789 rootDomain
->tracePoint( IS_POWER_DROP
?
4790 kIOPMTracePointSleepDidChangeInterests
:
4791 kIOPMTracePointWakeDidChangeInterests
);
4794 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4797 //*********************************************************************************
4798 // [private] OurChangeTellCapabilityDidChange
4800 // For root domain to notify capability power-change.
4801 //*********************************************************************************
4804 IOService::OurChangeTellCapabilityDidChange( void )
4806 if (!IS_ROOT_DOMAIN
) {
4807 return OurChangeFinish();
4810 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4811 kIOPMTracePointSleepCapabilityClients
:
4812 kIOPMTracePointWakeCapabilityClients
);
4814 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4817 //*********************************************************************************
4818 // [private] OurChangeFinish
4820 // Done with this self-induced power state change.
4821 //*********************************************************************************
4824 IOService::OurChangeFinish( void )
4830 // MARK: Power Change Initiated by Parent
4832 //*********************************************************************************
4833 // [private] ParentChangeStart
4835 // Here we begin the processing of a power change initiated by our parent.
4836 //*********************************************************************************
4839 IOService::ParentChangeStart( void )
4841 PM_ASSERT_IN_GATE();
4842 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4844 // Root power domain has transitioned to its max power state
4845 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4846 (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) {
4847 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4848 if (fIdleTimerPeriod
&& fIdleTimerStopped
) {
4853 // Power domain is forcing us to lower power
4854 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
)) {
4855 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4857 // Tell apps and kernel clients
4858 fInitialPowerChange
= false;
4859 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4860 tellChangeDown1(fHeadNotePowerState
);
4861 return IOPMWillAckLater
;
4864 // Power domain is allowing us to raise power up to fHeadNotePowerState
4865 if (StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
)) {
4866 if (StateOrder(fDesiredPowerState
) > StateOrder(fCurrentPowerState
)) {
4867 if (StateOrder(fDesiredPowerState
) < StateOrder(fHeadNotePowerState
)) {
4868 // We power up, but not all the way
4869 fHeadNotePowerState
= fDesiredPowerState
;
4870 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4871 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4874 // We don't need to change
4875 fHeadNotePowerState
= fCurrentPowerState
;
4876 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4877 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4881 if (fHeadNoteChangeFlags
& kIOPMDomainDidChange
) {
4882 if (StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
)) {
4883 PM_ACTION_2(actionPowerChangeStart
,
4884 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4886 // Parent did change up - start our change up
4887 fInitialPowerChange
= false;
4888 ParentChangeTellCapabilityWillChange();
4889 return IOPMWillAckLater
;
4890 } else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
) {
4891 // No need to change power state, but broadcast change
4893 fMachineState
= kIOPM_SyncNotifyDidChange
;
4894 fDriverCallReason
= kDriverCallInformPreChange
;
4895 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4897 return IOPMWillAckLater
;
4901 // No power state change necessary
4902 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4905 return IOPMAckImplied
;
4908 //******************************************************************************
4909 // [private] ParentChangeRootChangeDown
4911 // Root domain has finished the transition to the system sleep state. And all
4912 // drivers in the power plane should have powered down. Cancel the idle timer,
4913 // and also reset the device desire for those drivers that don't want power
4914 // automatically restored on wake.
4915 //******************************************************************************
4918 IOService::ParentChangeRootChangeDown( void )
4920 // Always stop the idle timer before root power down
4921 if (fIdleTimerPeriod
&& !fIdleTimerStopped
) {
4922 fIdleTimerStopped
= true;
4923 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
)) {
4928 if (fResetPowerStateOnWake
) {
4929 // Reset device desire down to the lowest power state.
4930 // Advisory tickle desire is intentionally untouched since
4931 // it has no effect until system is promoted to full wake.
4933 if (fDeviceDesire
!= kPowerStateZero
) {
4934 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4935 computeDesiredState(kPowerStateZero
, true);
4936 requestDomainPower( fDesiredPowerState
);
4937 PM_LOG1("%s: tickle desire removed\n", fName
);
4940 // Invalidate tickle cache so the next tickle will issue a request
4941 IOLockLock(fActivityLock
);
4942 fDeviceWasActive
= false;
4943 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4944 IOLockUnlock(fActivityLock
);
4946 fIdleTimerMinPowerState
= kPowerStateZero
;
4947 } else if (fAdvisoryTickleUsed
) {
4948 // Less aggressive mechanism to accelerate idle timer expiration
4949 // before system sleep. May not always allow the driver to wake
4950 // up from system sleep in the min power state.
4954 bool dropTickleDesire
= false;
4956 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
4957 (fIdleTimerMinPowerState
== kPowerStateZero
) &&
4958 (fDeviceDesire
!= kPowerStateZero
)) {
4959 IOLockLock(fActivityLock
);
4961 if (!fDeviceWasActive
) {
4962 // No tickles since the last idle timer expiration.
4963 // Safe to drop the device desire to zero.
4964 dropTickleDesire
= true;
4966 // Was tickled since the last idle timer expiration,
4967 // but not in the last minute.
4968 clock_get_uptime(&now
);
4969 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
4970 absolutetime_to_nanoseconds(now
, &nsec
);
4971 if (nsec
>= kNoTickleCancelWindow
) {
4972 dropTickleDesire
= true;
4976 if (dropTickleDesire
) {
4977 // Force the next tickle to raise power state
4978 fDeviceWasActive
= false;
4979 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4982 IOLockUnlock(fActivityLock
);
4985 if (dropTickleDesire
) {
4986 // Advisory tickle desire is intentionally untouched since
4987 // it has no effect until system is promoted to full wake.
4989 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4990 computeDesiredState(kPowerStateZero
, true);
4991 PM_LOG1("%s: tickle desire dropped\n", fName
);
4996 //*********************************************************************************
4997 // [private] ParentChangeTellPriorityClientsPowerDown
4999 // All applications and kernel clients have acknowledged our intention to drop
5000 // power. Here we notify "priority" clients that we are lowering power.
5001 //*********************************************************************************
5004 IOService::ParentChangeTellPriorityClientsPowerDown( void )
5006 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
5007 tellChangeDown2(fHeadNotePowerState
);
5010 //*********************************************************************************
5011 // [private] ParentChangeTellCapabilityWillChange
5013 // All (legacy) applications and kernel clients have acknowledged, extra stage for
5014 // root domain to notify apps and drivers about the system capability change.
5015 //*********************************************************************************
5018 IOService::ParentChangeTellCapabilityWillChange( void )
5020 if (!IS_ROOT_DOMAIN
) {
5021 return ParentChangeNotifyInterestedDriversWillChange();
5024 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
5027 //*********************************************************************************
5028 // [private] ParentChangeNotifyInterestedDriversWillChange
5030 // All applications and kernel clients have acknowledged our power state change.
5031 // Here we notify interested drivers pre-change.
5032 //*********************************************************************************
5035 IOService::ParentChangeNotifyInterestedDriversWillChange( void )
5037 notifyAll( kIOPM_ParentChangeSetPowerState
);
5040 //*********************************************************************************
5041 // [private] ParentChangeSetPowerState
5043 // Instruct our controlling driver to program the hardware for the power state
5044 // change. Wait for async completions.
5045 //*********************************************************************************
5048 IOService::ParentChangeSetPowerState( void )
5050 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
5051 fMachineState
= kIOPM_DriverThreadCallDone
;
5052 fDriverCallReason
= kDriverCallSetPowerState
;
5054 if (notifyControllingDriver() == false) {
5055 notifyControllingDriverDone();
5059 //*********************************************************************************
5060 // [private] ParentChangeWaitForPowerSettle
5062 // Our controlling driver has completed the power state change initiated by our
5063 // parent. Wait for the driver specified settle time to expire.
5064 //*********************************************************************************
5067 IOService::ParentChangeWaitForPowerSettle( void )
5069 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
5073 //*********************************************************************************
5074 // [private] ParentChangeNotifyInterestedDriversDidChange
5076 // Power has settled on a power change initiated by our parent. Here we notify
5077 // all our interested drivers post-change.
5078 //*********************************************************************************
5081 IOService::ParentChangeNotifyInterestedDriversDidChange( void )
5083 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
5086 //*********************************************************************************
5087 // [private] ParentChangeTellCapabilityDidChange
5089 // For root domain to notify capability power-change.
5090 //*********************************************************************************
5093 IOService::ParentChangeTellCapabilityDidChange( void )
5095 if (!IS_ROOT_DOMAIN
) {
5096 return ParentChangeAcknowledgePowerChange();
5099 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
5102 //*********************************************************************************
5103 // [private] ParentAcknowledgePowerChange
5105 // Acknowledge our power parent that our power change is done.
5106 //*********************************************************************************
5109 IOService::ParentChangeAcknowledgePowerChange( void )
5111 IORegistryEntry
* nub
;
5114 nub
= fHeadNoteParentConnection
;
5117 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
5119 parent
->acknowledgePowerChange((IOService
*)nub
);
5126 // MARK: Ack and Settle timers
5128 //*********************************************************************************
5129 // [private] settleTimerExpired
5131 // Power has settled after our last change. Notify interested parties that
5132 // there is a new power state.
5133 //*********************************************************************************
5136 IOService::settleTimerExpired( void )
5139 gIOPMWorkQueue
->signalWorkAvailable();
5142 //*********************************************************************************
5143 // settle_timer_expired
5145 // Holds a retain while the settle timer callout is in flight.
5146 //*********************************************************************************
5149 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5151 IOService
* me
= (IOService
*) arg0
;
5153 if (gIOPMWorkLoop
&& gIOPMWorkQueue
) {
5154 gIOPMWorkLoop
->runAction(
5155 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5161 //*********************************************************************************
5162 // [private] startSettleTimer
5164 // Calculate a power-settling delay in microseconds and start a timer.
5165 //*********************************************************************************
5168 IOService::startSettleTimer( void )
5171 // This function is broken and serves no useful purpose since it never
5172 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5173 // yet it starts a delay timer. It appears no driver relies on a delay
5174 // from settleUpTime and settleDownTime in the power state table.
5176 AbsoluteTime deadline
;
5177 IOPMPowerStateIndex stateIndex
;
5178 IOPMPowerStateIndex currentOrder
, newOrder
, i
;
5179 uint32_t settleTime
= 0;
5182 PM_ASSERT_IN_GATE();
5184 currentOrder
= StateOrder(fCurrentPowerState
);
5185 newOrder
= StateOrder(fHeadNotePowerState
);
5190 if (newOrder
< currentOrder
) {
5191 while (i
> newOrder
) {
5192 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
5193 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleDownTime
;
5199 if (newOrder
> currentOrder
) {
5200 while (i
< newOrder
) {
5201 stateIndex
= fPowerStates
[i
+ 1].stateOrderToIndex
;
5202 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleUpTime
;
5209 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5210 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5218 //*********************************************************************************
5219 // [private] ackTimerTick
5221 // The acknowledgement timeout periodic timer has ticked.
5222 // If we are awaiting acks for a power change notification,
5223 // we decrement the timer word of each interested driver which hasn't acked.
5224 // If a timer word becomes zero, we pretend the driver aknowledged.
5225 // If we are waiting for the controlling driver to change the power
5226 // state of the hardware, we decrement its timer word, and if it becomes
5227 // zero, we pretend the driver acknowledged.
5229 // Returns true if the timer tick made it possible to advance to the next
5230 // machine state, false otherwise.
5231 //*********************************************************************************
5238 IOService::ack_timer_ticked( void )
5242 #endif /* !__LP64__ */
5245 IOService::ackTimerTick( void )
5247 IOPMinformee
* nextObject
;
5250 PM_ASSERT_IN_GATE();
5251 switch (fMachineState
) {
5252 case kIOPM_OurChangeWaitForPowerSettle
:
5253 case kIOPM_ParentChangeWaitForPowerSettle
:
5254 // are we waiting for controlling driver to acknowledge?
5255 if (fDriverTimer
> 0) {
5256 // yes, decrement timer tick
5258 if (fDriverTimer
== 0) {
5259 // controlling driver is tardy
5260 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5261 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
5262 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
5263 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5264 fName
, OBFUSCATE(this), fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5266 #if DEBUG || DEVELOPMENT || CONFIG_EMBEDDED
5267 uint32_t panic_allowed
= -1;
5268 PE_parse_boot_argn("setpowerstate_panic", &panic_allowed
, sizeof(panic_allowed
));
5269 if (panic_allowed
!= 0) {
5270 // rdar://problem/48743340 - excluding AppleSEPManager from panic
5271 const char *whitelist
= "AppleSEPManager";
5272 if (strncmp(fName
, whitelist
, strlen(whitelist
))) {
5273 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5274 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5277 PM_ERROR("setPowerState panic disabled by setpowerstate_panic boot-arg\n");
5280 if (gIOKitDebug
& kIOLogDebugPower
) {
5281 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5282 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5284 // panic for first party kexts
5285 const void *function_addr
= NULL
;
5286 OSKext
*kext
= NULL
;
5287 function_addr
= OSMemberFunctionCast(const void *, fControllingDriver
, &IOService::setPowerState
);
5288 kext
= OSKext::lookupKextWithAddress((vm_address_t
)function_addr
);
5290 const char *bundleID
= kext
->getIdentifierCString();
5291 const char *apple_prefix
= "com.apple";
5292 const char *kernel_prefix
= "__kernel__";
5293 if (strncmp(bundleID
, apple_prefix
, strlen(apple_prefix
)) == 0 || strncmp(bundleID
, kernel_prefix
, strlen(kernel_prefix
)) == 0) {
5294 // first party client
5295 panic("%s::setPowerState(%p : %p, %lu -> %lu) timed out after %d ms",
5296 fName
, this, function_addr
, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5300 // Unblock state machine and pretend driver has acked.
5304 getPMRootDomain()->reset_watchdog_timer(this, 0);
5306 // still waiting, set timer again
5312 case kIOPM_NotifyChildrenStart
:
5313 // are we waiting for interested parties to acknowledge?
5314 if (fHeadNotePendingAcks
!= 0) {
5315 // yes, go through the list of interested drivers
5316 nextObject
= fInterestedDrivers
->firstInList();
5317 // and check each one
5318 while (nextObject
!= NULL
) {
5319 if (nextObject
->timer
> 0) {
5320 nextObject
->timer
--;
5321 // this one should have acked by now
5322 if (nextObject
->timer
== 0) {
5323 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5324 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5325 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5326 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5327 nextObject
->whatObject
->getName(),
5328 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5329 OBFUSCATE(nextObject
->whatObject
), fName
, fCurrentPowerState
, fHeadNotePowerState
,
5332 // Pretend driver has acked.
5333 fHeadNotePendingAcks
--;
5336 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5339 // is that the last?
5340 if (fHeadNotePendingAcks
== 0) {
5341 // yes, we can continue
5343 getPMRootDomain()->reset_watchdog_timer(this, 0);
5345 // no, set timer again
5351 // TODO: aggreggate this
5352 case kIOPM_OurChangeTellClientsPowerDown
:
5353 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
5354 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5355 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5356 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5357 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5358 case kIOPM_SyncTellClientsPowerDown
:
5359 case kIOPM_SyncTellPriorityClientsPowerDown
:
5360 case kIOPM_SyncNotifyWillChange
:
5361 case kIOPM_TellCapabilityChangeDone
:
5362 // apps didn't respond in time
5363 cleanClientResponses(true);
5364 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5365 // tardy equates to approval
5370 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5371 getName(), fMachineState
);
5377 //*********************************************************************************
5378 // [private] start_watchdog_timer
5379 //*********************************************************************************
5381 IOService::start_watchdog_timer( void )
5386 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5390 IOLockLock(fWatchdogLock
);
5392 timeout
= getPMRootDomain()->getWatchdogTimeout();
5393 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5394 fWatchdogDeadline
= deadline
;
5395 start_watchdog_timer(deadline
);
5396 IOLockUnlock(fWatchdogLock
);
5400 IOService::start_watchdog_timer(uint64_t deadline
)
5402 IOLockAssert(fWatchdogLock
, kIOLockAssertOwned
);
5404 if (!thread_call_isactive(fWatchdogTimer
)) {
5405 thread_call_enter_delayed(fWatchdogTimer
, deadline
);
5409 //*********************************************************************************
5410 // [private] stop_watchdog_timer
5411 //*********************************************************************************
5414 IOService::stop_watchdog_timer( void )
5416 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5420 IOLockLock(fWatchdogLock
);
5422 thread_call_cancel(fWatchdogTimer
);
5423 fWatchdogDeadline
= 0;
5425 while (fBlockedArray
->getCount()) {
5426 IOService
*obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(0));
5428 PM_ERROR("WDOG:Object %s unexpected in blocked array\n", obj
->fName
);
5429 fBlockedArray
->removeObject(0);
5433 IOLockUnlock(fWatchdogLock
);
5436 //*********************************************************************************
5437 // reset_watchdog_timer
5438 //*********************************************************************************
5441 IOService::reset_watchdog_timer(IOService
*blockedObject
, int pendingResponseTimeout
)
5447 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5452 IOLockLock(fWatchdogLock
);
5453 if (!fWatchdogDeadline
) {
5457 i
= fBlockedArray
->getNextIndexOfObject(blockedObject
, 0);
5458 if (pendingResponseTimeout
== 0) {
5459 blockedObject
->fPendingResponseDeadline
= 0;
5460 if (i
== (unsigned int)-1) {
5463 fBlockedArray
->removeObject(i
);
5465 // Set deadline 2secs after the expected response timeout to allow
5466 // ack timer to handle the timeout.
5467 clock_interval_to_deadline(pendingResponseTimeout
+ 2, kSecondScale
, &deadline
);
5469 if (i
!= (unsigned int)-1) {
5470 PM_ERROR("WDOG:Object %s is already blocked for responses. Ignoring timeout %d\n",
5471 fName
, pendingResponseTimeout
);
5475 for (i
= 0; i
< fBlockedArray
->getCount(); i
++) {
5476 obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(i
));
5477 if (obj
&& (obj
->fPendingResponseDeadline
< deadline
)) {
5478 blockedObject
->fPendingResponseDeadline
= deadline
;
5479 fBlockedArray
->setObject(i
, blockedObject
);
5483 if (i
== fBlockedArray
->getCount()) {
5484 blockedObject
->fPendingResponseDeadline
= deadline
;
5485 fBlockedArray
->setObject(blockedObject
);
5489 obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(0));
5491 int timeout
= getPMRootDomain()->getWatchdogTimeout();
5492 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5494 deadline
= obj
->fPendingResponseDeadline
;
5497 thread_call_cancel(fWatchdogTimer
);
5498 start_watchdog_timer(deadline
);
5501 IOLockUnlock(fWatchdogLock
);
5505 //*********************************************************************************
5506 // [static] watchdog_timer_expired
5508 // Inside PM work loop's gate.
5509 //*********************************************************************************
5512 IOService::watchdog_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5514 IOService
* me
= (IOService
*) arg0
;
5517 gIOPMWatchDogThread
= current_thread();
5518 getPMRootDomain()->sleepWakeDebugTrig(true);
5519 gIOPMWatchDogThread
= NULL
;
5520 thread_call_free(me
->fWatchdogTimer
);
5521 me
->fWatchdogTimer
= NULL
;
5528 IOService::getIOPMWorkloop( void )
5530 return gIOPMWorkLoop
;
5535 //*********************************************************************************
5536 // [private] start_ack_timer
5537 //*********************************************************************************
5540 IOService::start_ack_timer( void )
5542 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5546 IOService::start_ack_timer( UInt32 interval
, UInt32 scale
)
5548 AbsoluteTime deadline
;
5551 clock_interval_to_deadline(interval
, scale
, &deadline
);
5554 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5560 //*********************************************************************************
5561 // [private] stop_ack_timer
5562 //*********************************************************************************
5565 IOService::stop_ack_timer( void )
5569 pending
= thread_call_cancel(fAckTimer
);
5575 //*********************************************************************************
5576 // [static] actionAckTimerExpired
5578 // Inside PM work loop's gate.
5579 //*********************************************************************************
5582 IOService::actionAckTimerExpired(
5584 void * arg0
, void * arg1
,
5585 void * arg2
, void * arg3
)
5587 IOService
* me
= (IOService
*) target
;
5590 // done will be true if the timer tick unblocks the machine state,
5591 // otherwise no need to signal the work loop.
5593 done
= me
->ackTimerTick();
5594 if (done
&& gIOPMWorkQueue
) {
5595 gIOPMWorkQueue
->signalWorkAvailable();
5598 return kIOReturnSuccess
;
5601 //*********************************************************************************
5602 // ack_timer_expired
5604 // Thread call function. Holds a retain while the callout is in flight.
5605 //*********************************************************************************
5608 IOService::ack_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5610 IOService
* me
= (IOService
*) arg0
;
5612 if (gIOPMWorkLoop
) {
5613 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5620 // MARK: Client Messaging
5622 //*********************************************************************************
5623 // [private] tellSystemCapabilityChange
5624 //*********************************************************************************
5627 IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5630 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5631 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5634 // Notify app first on pre-change.
5635 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5637 // Notify kernel clients first on post-change.
5638 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5641 tellClientsWithResponse( fOutOfBandMessage
);
5644 //*********************************************************************************
5645 // [public] askChangeDown
5647 // Ask registered applications and kernel clients if we can change to a lower
5650 // Subclass can override this to send a different message type. Parameter is
5651 // the destination state number.
5653 // Return true if we don't have to wait for acknowledgements
5654 //*********************************************************************************
5657 IOService::askChangeDown( unsigned long stateNum
)
5659 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5662 //*********************************************************************************
5663 // [private] tellChangeDown1
5665 // Notify registered applications and kernel clients that we are definitely
5668 // Return true if we don't have to wait for acknowledgements
5669 //*********************************************************************************
5672 IOService::tellChangeDown1( unsigned long stateNum
)
5674 fOutOfBandParameter
= kNotifyApps
;
5675 return tellChangeDown(stateNum
);
5678 //*********************************************************************************
5679 // [private] tellChangeDown2
5681 // Notify priority clients that we are definitely dropping power.
5683 // Return true if we don't have to wait for acknowledgements
5684 //*********************************************************************************
5687 IOService::tellChangeDown2( unsigned long stateNum
)
5689 fOutOfBandParameter
= kNotifyPriority
;
5690 return tellChangeDown(stateNum
);
5693 //*********************************************************************************
5694 // [public] tellChangeDown
5696 // Notify registered applications and kernel clients that we are definitely
5699 // Subclass can override this to send a different message type. Parameter is
5700 // the destination state number.
5702 // Return true if we don't have to wait for acknowledgements
5703 //*********************************************************************************
5706 IOService::tellChangeDown( unsigned long stateNum
)
5708 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5711 //*********************************************************************************
5712 // cleanClientResponses
5714 //*********************************************************************************
5717 logAppTimeouts( OSObject
* object
, void * arg
)
5719 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5721 unsigned int clientIndex
;
5725 if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
5726 // Discover the 'counter' value or index assigned to this client
5727 // when it was notified, by searching for the array index of the
5728 // client in an array holding the cached interested clients.
5730 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5732 if ((clientIndex
!= (unsigned int) -1) &&
5733 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5734 (flag
!= kOSBooleanTrue
)) {
5735 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5739 pid
= clientID
->unsigned32BitValue();
5740 proc_name(pid
, name
, sizeof(name
));
5741 clientID
->release();
5744 PM_ERROR(context
->errorLog
, pid
, name
);
5746 // TODO: record message type if possible
5747 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5748 gIOPMStatsResponseTimedOut
,
5749 name
, 0, (30 * 1000), pid
, object
);
5755 IOService::cleanClientResponses( bool logErrors
)
5757 if (logErrors
&& fResponseArray
) {
5758 switch (fOutOfBandParameter
) {
5760 case kNotifyCapabilityChangeApps
:
5761 if (fNotifyClientArray
) {
5762 IOPMInterestContext context
;
5764 context
.responseArray
= fResponseArray
;
5765 context
.notifyClients
= fNotifyClientArray
;
5766 context
.serialNumber
= fSerialNumber
;
5767 context
.messageType
= kIOMessageCopyClientID
;
5768 context
.notifyType
= kNotifyApps
;
5769 context
.isPreChange
= fIsPreChange
;
5770 context
.enableTracing
= false;
5772 context
.maxTimeRequested
= 0;
5773 context
.stateNumber
= fHeadNotePowerState
;
5774 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5775 context
.changeFlags
= fHeadNoteChangeFlags
;
5776 context
.errorLog
= "PM notification timeout (pid %d, %s)\n";
5778 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5783 // kNotifyPriority, kNotifyCapabilityChangePriority
5784 // TODO: identify the priority client that has not acked
5785 PM_ERROR("PM priority notification timeout\n");
5786 if (gIOKitDebug
& kIOLogDebugPower
) {
5787 panic("PM priority notification timeout");
5793 if (IS_ROOT_DOMAIN
) {
5794 getPMRootDomain()->reset_watchdog_timer(this, 0);
5796 if (fResponseArray
) {
5797 fResponseArray
->release();
5798 fResponseArray
= NULL
;
5800 if (fNotifyClientArray
) {
5801 fNotifyClientArray
->release();
5802 fNotifyClientArray
= NULL
;
5806 //*********************************************************************************
5807 // [protected] tellClientsWithResponse
5809 // Notify registered applications and kernel clients that we are definitely
5812 // Return true if we don't have to wait for acknowledgements
5813 //*********************************************************************************
5816 IOService::tellClientsWithResponse( int messageType
)
5818 IOPMInterestContext context
;
5819 bool isRootDomain
= IS_ROOT_DOMAIN
;
5820 uint32_t maxTimeOut
= kMaxTimeRequested
;
5822 PM_ASSERT_IN_GATE();
5823 assert( fResponseArray
== NULL
);
5824 assert( fNotifyClientArray
== NULL
);
5826 if (messageType
== (int)kIOPMMessageLastCallBeforeSleep
) {
5827 RD_LOG("tellClientsWithResponse( kIOPMMessageLastCallBeforeSleep, %d )\n",
5828 fOutOfBandParameter
);
5830 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5831 getIOMessageString(messageType
), fOutOfBandParameter
);
5834 fResponseArray
= OSArray::withCapacity( 1 );
5835 if (!fResponseArray
) {
5839 fResponseArray
->setCapacityIncrement(8);
5840 if (++fSerialNumber
== 0) {
5844 context
.responseArray
= fResponseArray
;
5845 context
.notifyClients
= NULL
;
5846 context
.serialNumber
= fSerialNumber
;
5847 context
.messageType
= messageType
;
5848 context
.notifyType
= fOutOfBandParameter
;
5849 context
.skippedInDark
= 0;
5850 context
.notSkippedInDark
= 0;
5851 context
.isPreChange
= fIsPreChange
;
5852 context
.enableTracing
= false;
5854 context
.maxTimeRequested
= 0;
5855 context
.stateNumber
= fHeadNotePowerState
;
5856 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5857 context
.changeFlags
= fHeadNoteChangeFlags
;
5858 context
.messageFilter
= (isRootDomain
) ?
5859 OSMemberFunctionCast(
5862 &IOPMrootDomain::systemMessageFilter
) : NULL
;
5864 switch (fOutOfBandParameter
) {
5866 applyToInterested( gIOAppPowerStateInterest
,
5867 pmTellAppWithResponse
, (void *) &context
);
5870 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5871 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
) &&
5872 (context
.messageType
!= kIOPMMessageLastCallBeforeSleep
)) {
5873 // Notify capability app for tellChangeDown1()
5874 // but not for askChangeDown().
5875 context
.notifyType
= kNotifyCapabilityChangeApps
;
5876 context
.messageType
= kIOMessageSystemCapabilityChange
;
5877 applyToInterested( gIOAppPowerStateInterest
,
5878 pmTellCapabilityAppWithResponse
, (void *) &context
);
5879 context
.notifyType
= fOutOfBandParameter
;
5880 context
.messageType
= messageType
;
5882 if (context
.messageType
== kIOMessageCanSystemSleep
) {
5883 maxTimeOut
= kCanSleepMaxTimeReq
;
5884 if (gCanSleepTimeout
) {
5885 maxTimeOut
= (gCanSleepTimeout
* us_per_s
);
5888 context
.maxTimeRequested
= maxTimeOut
;
5889 context
.enableTracing
= isRootDomain
;
5890 applyToInterested( gIOGeneralInterest
,
5891 pmTellClientWithResponse
, (void *) &context
);
5895 case kNotifyPriority
:
5896 context
.enableTracing
= isRootDomain
;
5897 applyToInterested( gIOPriorityPowerStateInterest
,
5898 pmTellClientWithResponse
, (void *) &context
);
5901 // Notify capability clients for tellChangeDown2().
5902 context
.notifyType
= kNotifyCapabilityChangePriority
;
5903 context
.messageType
= kIOMessageSystemCapabilityChange
;
5904 applyToInterested( gIOPriorityPowerStateInterest
,
5905 pmTellCapabilityClientWithResponse
, (void *) &context
);
5909 case kNotifyCapabilityChangeApps
:
5910 applyToInterested( gIOAppPowerStateInterest
,
5911 pmTellCapabilityAppWithResponse
, (void *) &context
);
5912 if (context
.messageType
== kIOMessageCanSystemSleep
) {
5913 maxTimeOut
= kCanSleepMaxTimeReq
;
5914 if (gCanSleepTimeout
) {
5915 maxTimeOut
= (gCanSleepTimeout
* us_per_s
);
5918 context
.maxTimeRequested
= maxTimeOut
;
5921 case kNotifyCapabilityChangePriority
:
5922 context
.enableTracing
= isRootDomain
;
5923 applyToInterested( gIOPriorityPowerStateInterest
,
5924 pmTellCapabilityClientWithResponse
, (void *) &context
);
5927 fNotifyClientArray
= context
.notifyClients
;
5929 if (context
.skippedInDark
) {
5930 IOLog("tellClientsWithResponse(%s, %d) %d of %d skipped in dark\n",
5931 getIOMessageString(messageType
), fOutOfBandParameter
,
5932 context
.skippedInDark
, context
.skippedInDark
+ context
.notSkippedInDark
);
5935 // do we have to wait for somebody?
5936 if (!checkForDone()) {
5937 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5938 if (context
.enableTracing
) {
5939 getPMRootDomain()->traceDetail(context
.messageType
, 0, context
.maxTimeRequested
/ 1000);
5940 getPMRootDomain()->reset_watchdog_timer(this, context
.maxTimeRequested
/ USEC_PER_SEC
+ 1);
5942 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5947 // everybody responded
5948 if (fResponseArray
) {
5949 fResponseArray
->release();
5950 fResponseArray
= NULL
;
5952 if (fNotifyClientArray
) {
5953 fNotifyClientArray
->release();
5954 fNotifyClientArray
= NULL
;
5960 //*********************************************************************************
5961 // [static private] pmTellAppWithResponse
5963 // We send a message to an application, and we expect a response, so we compute a
5964 // cookie we can identify the response with.
5965 //*********************************************************************************
5968 IOService::pmTellAppWithResponse( OSObject
* object
, void * arg
)
5970 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5971 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5972 uint32_t msgIndex
, msgRef
, msgType
;
5973 OSNumber
*clientID
= NULL
;
5975 boolean_t proc_suspended
= FALSE
;
5976 OSObject
* waitForReply
= kOSBooleanTrue
;
5977 #if LOG_APP_RESPONSE_TIMES
5981 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
5985 if (context
->us
== getPMRootDomain()) {
5986 if ((clientID
= copyClientIDForNotification(object
, context
))) {
5987 uint32_t clientPID
= clientID
->unsigned32BitValue();
5988 clientID
->release();
5989 proc
= proc_find(clientPID
);
5992 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
5993 if (proc_suspended
) {
5994 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
5995 } else if (getPMRootDomain()->isAOTMode() && get_task_suspended((task_t
) proc
->task
)) {
5996 proc_suspended
= true;
5997 context
->skippedInDark
++;
6000 if (proc_suspended
) {
6007 if (context
->messageFilter
&&
6008 !context
->messageFilter(context
->us
, object
, context
, NULL
, &waitForReply
)) {
6009 if (kIOLogDebugPower
& gIOKitDebug
) {
6010 logClientIDForNotification(object
, context
, "DROP App");
6014 context
->notSkippedInDark
++;
6016 // Create client array (for tracking purposes) only if the service
6017 // has app clients. Usually only root domain does.
6018 if (NULL
== context
->notifyClients
) {
6019 context
->notifyClients
= OSArray::withCapacity( 32 );
6022 msgType
= context
->messageType
;
6023 msgIndex
= context
->responseArray
->getCount();
6024 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6026 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6027 if (kIOLogDebugPower
& gIOKitDebug
) {
6028 logClientIDForNotification(object
, context
, "MESG App");
6031 if (waitForReply
== kOSBooleanTrue
) {
6033 clock_get_uptime(&now
);
6034 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6036 context
->responseArray
->setObject(msgIndex
, num
);
6039 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6042 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6043 if (kIOLogDebugPower
& gIOKitDebug
) {
6044 logClientIDForNotification(object
, context
, "App response ignored");
6048 if (context
->notifyClients
) {
6049 context
->notifyClients
->setObject(msgIndex
, object
);
6052 context
->us
->messageClient(msgType
, object
, (void *)(uintptr_t) msgRef
);
6055 //*********************************************************************************
6056 // [static private] pmTellClientWithResponse
6058 // We send a message to an in-kernel client, and we expect a response,
6059 // so we compute a cookie we can identify the response with.
6060 //*********************************************************************************
6063 IOService::pmTellClientWithResponse( OSObject
* object
, void * arg
)
6065 IOPowerStateChangeNotification notify
;
6066 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6067 OSObject
* replied
= kOSBooleanTrue
;
6068 _IOServiceInterestNotifier
* notifier
;
6069 uint32_t msgIndex
, msgRef
, msgType
;
6071 AbsoluteTime start
, end
;
6074 if (context
->messageFilter
&&
6075 !context
->messageFilter(context
->us
, object
, context
, NULL
, NULL
)) {
6076 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6077 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6078 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6079 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6080 context
->us
->getName(),
6081 getIOMessageString(context
->messageType
),
6082 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6087 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6088 msgType
= context
->messageType
;
6089 msgIndex
= context
->responseArray
->getCount();
6090 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6092 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6093 if (gIOKitDebug
& kIOLogPower
) {
6094 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6095 if (OSDynamicCast(IOService
, object
)) {
6096 const char *who
= ((IOService
*) object
)->getName();
6097 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6098 } else if (notifier
) {
6099 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6102 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
) {
6103 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6104 context
->us
->getName(),
6105 getIOMessageString(msgType
),
6106 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6109 if (NULL
== context
->notifyClients
) {
6110 context
->notifyClients
= OSArray::withCapacity( 32 );
6113 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
6114 notify
.returnValue
= 0;
6115 notify
.stateNumber
= context
->stateNumber
;
6116 notify
.stateFlags
= context
->stateFlags
;
6118 if (context
->enableTracing
&& (notifier
!= NULL
)) {
6119 getPMRootDomain()->traceDetail(notifier
, true);
6122 clock_get_uptime(&start
);
6123 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
6124 clock_get_uptime(&end
);
6126 if (context
->enableTracing
&& (notifier
!= NULL
)) {
6127 getPMRootDomain()->traceDetail(notifier
, false);
6131 if (kIOReturnSuccess
== retCode
) {
6132 if (0 == notify
.returnValue
) {
6133 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6134 context
->responseArray
->setObject(msgIndex
, replied
);
6136 replied
= kOSBooleanFalse
;
6137 if (notify
.returnValue
> context
->maxTimeRequested
) {
6138 if (notify
.returnValue
> kPriorityClientMaxWait
) {
6139 context
->maxTimeRequested
= kPriorityClientMaxWait
;
6140 PM_ERROR("%s: client %p returned %llu for %s\n",
6141 context
->us
->getName(),
6142 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6143 (uint64_t) notify
.returnValue
,
6144 getIOMessageString(msgType
));
6146 context
->maxTimeRequested
= notify
.returnValue
;
6150 // Track time taken to ack, by storing the timestamp of
6151 // callback completion
6153 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6155 context
->responseArray
->setObject(msgIndex
, num
);
6158 context
->responseArray
->setObject(msgIndex
, replied
);
6162 if (context
->enableTracing
) {
6163 SUB_ABSOLUTETIME(&end
, &start
);
6164 absolutetime_to_nanoseconds(end
, &nsec
);
6166 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (notify
.returnValue
!= 0)) {
6167 getPMRootDomain()->traceAckDelay(notifier
, notify
.returnValue
/ 1000, NS_TO_MS(nsec
));
6171 // not a client of ours
6172 // so we won't be waiting for response
6173 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6174 context
->responseArray
->setObject(msgIndex
, replied
);
6176 if (context
->notifyClients
) {
6177 context
->notifyClients
->setObject(msgIndex
, object
);
6181 //*********************************************************************************
6182 // [static private] pmTellCapabilityAppWithResponse
6183 //*********************************************************************************
6186 IOService::pmTellCapabilityAppWithResponse( OSObject
* object
, void * arg
)
6188 IOPMSystemCapabilityChangeParameters msgArg
;
6189 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6190 OSObject
* replied
= kOSBooleanTrue
;
6191 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6192 uint32_t msgIndex
, msgRef
, msgType
;
6193 #if LOG_APP_RESPONSE_TIMES
6197 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
6201 memset(&msgArg
, 0, sizeof(msgArg
));
6202 if (context
->messageFilter
&&
6203 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
)) {
6207 if (context
->us
== getPMRootDomain() &&
6208 getPMRootDomain()->isAOTMode()
6210 OSNumber
*clientID
= NULL
;
6211 boolean_t proc_suspended
= FALSE
;
6213 if ((clientID
= copyClientIDForNotification(object
, context
))) {
6214 uint32_t clientPID
= clientID
->unsigned32BitValue();
6215 clientID
->release();
6216 proc
= proc_find(clientPID
);
6218 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6219 if (proc_suspended
) {
6220 logClientIDForNotification(object
, context
, "PMTellCapablityAppWithResponse - Suspended");
6221 } else if (get_task_suspended((task_t
) proc
->task
)) {
6222 proc_suspended
= true;
6223 context
->skippedInDark
++;
6226 if (proc_suspended
) {
6232 context
->notSkippedInDark
++;
6234 // Create client array (for tracking purposes) only if the service
6235 // has app clients. Usually only root domain does.
6236 if (NULL
== context
->notifyClients
) {
6237 context
->notifyClients
= OSArray::withCapacity( 32 );
6240 msgType
= context
->messageType
;
6241 msgIndex
= context
->responseArray
->getCount();
6242 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6244 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6245 if (kIOLogDebugPower
& gIOKitDebug
) {
6246 // Log client pid/name and client array index.
6247 OSNumber
* clientID
= NULL
;
6248 OSString
* clientIDString
= NULL
;;
6249 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6251 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6254 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
6255 context
->us
->getName(),
6256 msgIndex
, getIOMessageString(msgType
),
6257 (replied
!= kOSBooleanTrue
),
6258 clientIDString
? clientIDString
->getCStringNoCopy() : "");
6260 clientID
->release();
6262 if (clientIDString
) {
6263 clientIDString
->release();
6267 msgArg
.notifyRef
= msgRef
;
6268 msgArg
.maxWaitForReply
= 0;
6270 if (replied
== kOSBooleanTrue
) {
6271 msgArg
.notifyRef
= 0;
6272 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6273 if (context
->notifyClients
) {
6274 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
6278 clock_get_uptime(&now
);
6279 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6281 context
->responseArray
->setObject(msgIndex
, num
);
6284 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6287 if (context
->notifyClients
) {
6288 context
->notifyClients
->setObject(msgIndex
, object
);
6292 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6295 //*********************************************************************************
6296 // [static private] pmTellCapabilityClientWithResponse
6297 //*********************************************************************************
6300 IOService::pmTellCapabilityClientWithResponse(
6301 OSObject
* object
, void * arg
)
6303 IOPMSystemCapabilityChangeParameters msgArg
;
6304 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6305 OSObject
* replied
= kOSBooleanTrue
;
6306 _IOServiceInterestNotifier
* notifier
;
6307 uint32_t msgIndex
, msgRef
, msgType
;
6309 AbsoluteTime start
, end
;
6312 memset(&msgArg
, 0, sizeof(msgArg
));
6313 if (context
->messageFilter
&&
6314 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, NULL
)) {
6315 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6316 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6317 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6318 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6319 context
->us
->getName(),
6320 getIOMessageString(context
->messageType
),
6321 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6326 if (NULL
== context
->notifyClients
) {
6327 context
->notifyClients
= OSArray::withCapacity( 32 );
6329 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6330 msgType
= context
->messageType
;
6331 msgIndex
= context
->responseArray
->getCount();
6332 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6334 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6335 if (gIOKitDebug
& kIOLogPower
) {
6336 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6337 if (OSDynamicCast(IOService
, object
)) {
6338 const char *who
= ((IOService
*) object
)->getName();
6339 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6340 } else if (notifier
) {
6341 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6344 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
) {
6345 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6346 context
->us
->getName(),
6347 getIOMessageString(msgType
),
6348 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6351 msgArg
.notifyRef
= msgRef
;
6352 msgArg
.maxWaitForReply
= 0;
6354 if (context
->enableTracing
&& (notifier
!= NULL
)) {
6355 getPMRootDomain()->traceDetail(notifier
, true);
6358 clock_get_uptime(&start
);
6359 retCode
= context
->us
->messageClient(
6360 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6361 clock_get_uptime(&end
);
6362 if (context
->enableTracing
&& (notifier
!= NULL
)) {
6363 getPMRootDomain()->traceDetail(notifier
, false);
6366 if (kIOReturnSuccess
== retCode
) {
6367 if (0 == msgArg
.maxWaitForReply
) {
6368 // client doesn't want time to respond
6369 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6370 context
->responseArray
->setObject(msgIndex
, replied
);
6372 replied
= kOSBooleanFalse
;
6373 if (msgArg
.maxWaitForReply
> context
->maxTimeRequested
) {
6374 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
) {
6375 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
6376 PM_ERROR("%s: client %p returned %u for %s\n",
6377 context
->us
->getName(),
6378 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6379 msgArg
.maxWaitForReply
,
6380 getIOMessageString(msgType
));
6382 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6386 // Track time taken to ack, by storing the timestamp of
6387 // callback completion
6389 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6391 context
->responseArray
->setObject(msgIndex
, num
);
6394 context
->responseArray
->setObject(msgIndex
, replied
);
6398 if (context
->enableTracing
) {
6399 SUB_ABSOLUTETIME(&end
, &start
);
6400 absolutetime_to_nanoseconds(end
, &nsec
);
6402 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (msgArg
.maxWaitForReply
!= 0)) {
6403 getPMRootDomain()->traceAckDelay(notifier
, msgArg
.maxWaitForReply
/ 1000, NS_TO_MS(nsec
));
6407 // not a client of ours
6408 // so we won't be waiting for response
6409 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6410 context
->responseArray
->setObject(msgIndex
, replied
);
6412 if (context
->notifyClients
) {
6413 context
->notifyClients
->setObject(msgIndex
, object
);
6417 //*********************************************************************************
6418 // [public] tellNoChangeDown
6420 // Notify registered applications and kernel clients that we are not
6423 // Subclass can override this to send a different message type. Parameter is
6424 // the aborted destination state number.
6425 //*********************************************************************************
6428 IOService::tellNoChangeDown( unsigned long )
6430 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6433 //*********************************************************************************
6434 // [public] tellChangeUp
6436 // Notify registered applications and kernel clients that we are raising power.
6438 // Subclass can override this to send a different message type. Parameter is
6439 // the aborted destination state number.
6440 //*********************************************************************************
6443 IOService::tellChangeUp( unsigned long )
6445 return tellClients( kIOMessageDeviceHasPoweredOn
);
6448 //*********************************************************************************
6449 // [protected] tellClients
6451 // Notify registered applications and kernel clients of something.
6452 //*********************************************************************************
6455 IOService::tellClients( int messageType
)
6457 IOPMInterestContext context
;
6459 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6461 memset(&context
, 0, sizeof(context
));
6462 context
.messageType
= messageType
;
6463 context
.isPreChange
= fIsPreChange
;
6465 context
.stateNumber
= fHeadNotePowerState
;
6466 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6467 context
.changeFlags
= fHeadNoteChangeFlags
;
6468 context
.enableTracing
= IS_ROOT_DOMAIN
;
6469 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6470 OSMemberFunctionCast(
6473 &IOPMrootDomain::systemMessageFilter
) : NULL
;
6475 context
.notifyType
= kNotifyPriority
;
6476 applyToInterested( gIOPriorityPowerStateInterest
,
6477 tellKernelClientApplier
, (void *) &context
);
6479 context
.notifyType
= kNotifyApps
;
6480 applyToInterested( gIOAppPowerStateInterest
,
6481 tellAppClientApplier
, (void *) &context
);
6483 applyToInterested( gIOGeneralInterest
,
6484 tellKernelClientApplier
, (void *) &context
);
6487 //*********************************************************************************
6488 // [private] tellKernelClientApplier
6490 // Message a kernel client.
6491 //*********************************************************************************
6494 tellKernelClientApplier( OSObject
* object
, void * arg
)
6496 IOPowerStateChangeNotification notify
;
6497 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6499 if (context
->messageFilter
&&
6500 !context
->messageFilter(context
->us
, object
, context
, NULL
, NULL
)) {
6501 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6502 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6503 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6504 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6505 context
->us
->getName(),
6506 IOService::getIOMessageString(context
->messageType
),
6507 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6512 notify
.powerRef
= (void *) NULL
;
6513 notify
.returnValue
= 0;
6514 notify
.stateNumber
= context
->stateNumber
;
6515 notify
.stateFlags
= context
->stateFlags
;
6517 if (context
->enableTracing
&& object
) {
6518 IOService::getPMRootDomain()->traceDetail(object
, true);
6520 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6521 if (context
->enableTracing
&& object
) {
6522 IOService::getPMRootDomain()->traceDetail(object
, false);
6527 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6528 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6529 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6530 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6531 context
->us
->getName(),
6532 IOService::getIOMessageString(context
->messageType
),
6533 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6538 copyClientIDForNotification(
6540 IOPMInterestContext
*context
)
6542 OSNumber
*clientID
= NULL
;
6543 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6548 logClientIDForNotification(
6550 IOPMInterestContext
*context
,
6551 const char *logString
)
6553 OSString
*logClientID
= NULL
;
6554 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6558 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6561 PM_LOG("%s %s %s, %s\n",
6562 context
->us
->getName(), logString
,
6563 IOService::getIOMessageString(context
->messageType
),
6564 logClientID
? logClientID
->getCStringNoCopy() : "");
6567 logClientID
->release();
6572 clientID
->release();
6579 tellAppClientApplier( OSObject
* object
, void * arg
)
6581 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6582 OSNumber
* clientID
= NULL
;
6584 boolean_t proc_suspended
= FALSE
;
6586 if (context
->us
== IOService::getPMRootDomain()) {
6587 if ((clientID
= copyClientIDForNotification(object
, context
))) {
6588 uint32_t clientPID
= clientID
->unsigned32BitValue();
6589 clientID
->release();
6590 proc
= proc_find(clientPID
);
6593 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6594 if (proc_suspended
) {
6595 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6596 } else if (IOService::getPMRootDomain()->isAOTMode() && get_task_suspended((task_t
) proc
->task
)) {
6597 proc_suspended
= true;
6598 context
->skippedInDark
++;
6601 if (proc_suspended
) {
6608 if (context
->messageFilter
&&
6609 !context
->messageFilter(context
->us
, object
, context
, NULL
, NULL
)) {
6610 if (kIOLogDebugPower
& gIOKitDebug
) {
6611 logClientIDForNotification(object
, context
, "DROP App");
6615 context
->notSkippedInDark
++;
6617 if (kIOLogDebugPower
& gIOKitDebug
) {
6618 logClientIDForNotification(object
, context
, "MESG App");
6621 context
->us
->messageClient(context
->messageType
, object
, NULL
);
6624 //*********************************************************************************
6625 // [private] checkForDone
6626 //*********************************************************************************
6629 IOService::checkForDone( void )
6634 if (fResponseArray
== NULL
) {
6639 theFlag
= fResponseArray
->getObject(i
);
6641 if (NULL
== theFlag
) {
6645 if (kOSBooleanTrue
!= theFlag
) {
6652 //*********************************************************************************
6653 // [public] responseValid
6654 //*********************************************************************************
6657 IOService::responseValid( uint32_t refcon
, int pid
)
6659 UInt16 serialComponent
;
6660 UInt16 ordinalComponent
;
6662 OSObject
*object
= NULL
;
6664 serialComponent
= (refcon
>> 16) & 0xFFFF;
6665 ordinalComponent
= (refcon
& 0xFFFF);
6667 if (serialComponent
!= fSerialNumber
) {
6671 if (fResponseArray
== NULL
) {
6675 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6677 if (theFlag
== NULL
) {
6681 if (fNotifyClientArray
) {
6682 object
= fNotifyClientArray
->getObject(ordinalComponent
);
6686 if ((num
= OSDynamicCast(OSNumber
, theFlag
))) {
6692 clock_get_uptime(&now
);
6693 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6694 SUB_ABSOLUTETIME(&now
, &start
);
6695 absolutetime_to_nanoseconds(now
, &nsec
);
6699 proc_name(pid
, name
, sizeof(name
));
6701 if (nsec
> LOG_APP_RESPONSE_TIMES
) {
6702 IOLog("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec
),
6707 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
) {
6708 // TODO: populate the messageType argument
6709 getPMRootDomain()->pmStatsRecordApplicationResponse(
6710 gIOPMStatsResponseSlow
,
6711 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6713 getPMRootDomain()->pmStatsRecordApplicationResponse(
6714 gIOPMStatsResponsePrompt
,
6715 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6718 getPMRootDomain()->traceAckDelay(object
, 0, NS_TO_MS(nsec
));
6721 if (kIOLogDebugPower
& gIOKitDebug
) {
6722 PM_LOG("Ack(%u) %u ms\n",
6723 (uint32_t) ordinalComponent
,
6726 theFlag
= kOSBooleanFalse
;
6727 } else if (object
) {
6728 getPMRootDomain()->pmStatsRecordApplicationResponse(
6729 gIOPMStatsResponsePrompt
,
6730 NULL
, 0, 0, pid
, object
);
6733 if (kOSBooleanFalse
== theFlag
) {
6734 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6740 //*********************************************************************************
6741 // [public] allowPowerChange
6743 // Our power state is about to lower, and we have notified applications
6744 // and kernel clients, and one of them has acknowledged. If this is the last to do
6745 // so, and all acknowledgements are positive, we continue with the power change.
6746 //*********************************************************************************
6749 IOService::allowPowerChange( unsigned long refcon
)
6751 IOPMRequest
* request
;
6755 return kIOReturnSuccess
;
6758 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6760 return kIOReturnNoMemory
;
6763 request
->fArg0
= (void *) refcon
;
6764 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6765 request
->fArg2
= (void *) NULL
;
6766 submitPMRequest( request
);
6768 return kIOReturnSuccess
;
6773 IOService::serializedAllowPowerChange2( unsigned long refcon
)
6775 // [deprecated] public
6776 return kIOReturnUnsupported
;
6778 #endif /* !__LP64__ */
6780 //*********************************************************************************
6781 // [public] cancelPowerChange
6783 // Our power state is about to lower, and we have notified applications
6784 // and kernel clients, and one of them has vetoed the change. If this is the last
6785 // client to respond, we abandon the power change.
6786 //*********************************************************************************
6789 IOService::cancelPowerChange( unsigned long refcon
)
6791 IOPMRequest
* request
;
6793 pid_t pid
= proc_selfpid();
6797 return kIOReturnSuccess
;
6801 proc_name(pid
, name
, sizeof(name
));
6802 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid
, name
);
6804 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6806 return kIOReturnNoMemory
;
6809 request
->fArg0
= (void *) refcon
;
6810 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6811 request
->fArg2
= (void *) OSString::withCString(name
);
6812 submitPMRequest( request
);
6814 return kIOReturnSuccess
;
6817 //*********************************************************************************
6818 // cancelIdlePowerDown
6820 // Internal method to trigger an idle cancel or revert
6821 //*********************************************************************************
6824 IOService::cancelIdlePowerDown( IOService
* service
)
6826 IOPMRequest
* request
;
6828 request
= acquirePMRequest(service
, kIOPMRequestTypeIdleCancel
);
6830 submitPMRequest(request
);
6836 IOService::serializedCancelPowerChange2( unsigned long refcon
)
6838 // [deprecated] public
6839 return kIOReturnUnsupported
;
6842 //*********************************************************************************
6843 // PM_Clamp_Timer_Expired
6845 // called when clamp timer expires...set power state to 0.
6846 //*********************************************************************************
6849 IOService::PM_Clamp_Timer_Expired( void )
6853 //*********************************************************************************
6856 // Set to highest available power state for a minimum of duration milliseconds
6857 //*********************************************************************************
6860 IOService::clampPowerOn( unsigned long duration
)
6863 #endif /* !__LP64__ */
6865 //*********************************************************************************
6866 // configurePowerStateReport
6868 // Configures the IOStateReport for kPMPowerStateChannel
6869 //*********************************************************************************
6871 IOService::configurePowerStatesReport( IOReportConfigureAction action
, void *result
)
6873 IOReturn rc
= kIOReturnSuccess
;
6879 return kIOReturnUnsupported
;
6882 if (!fNumberOfPowerStates
) {
6883 return kIOReturnSuccess
; // For drivers which are in power plane, but haven't called registerPowerDriver()
6888 case kIOReportEnable
:
6893 reportSize
= STATEREPORT_BUFSIZE(fNumberOfPowerStates
);
6894 fReportBuf
= IOMalloc(reportSize
);
6896 rc
= kIOReturnNoMemory
;
6899 memset(fReportBuf
, 0, reportSize
);
6901 STATEREPORT_INIT(fNumberOfPowerStates
, fReportBuf
, reportSize
,
6902 getRegistryEntryID(), kPMPowerStatesChID
, kIOReportCategoryPower
);
6904 for (i
= 0; i
< fNumberOfPowerStates
; i
++) {
6907 if (fPowerStates
[i
].capabilityFlags
& kIOPMPowerOn
) {
6908 bits
|= kPMReportPowerOn
;
6910 if (fPowerStates
[i
].capabilityFlags
& kIOPMDeviceUsable
) {
6911 bits
|= kPMReportDeviceUsable
;
6913 if (fPowerStates
[i
].capabilityFlags
& kIOPMLowPower
) {
6914 bits
|= kPMReportLowPower
;
6917 STATEREPORT_SETSTATEID(fReportBuf
, i
, ((bits
& 0xff) << 8) |
6918 ((StateOrder(fMaxPowerState
) & 0xf) << 4) | (StateOrder(i
) & 0xf));
6920 ts
= mach_absolute_time();
6921 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
6924 case kIOReportDisable
:
6925 if (fReportClientCnt
== 0) {
6926 rc
= kIOReturnBadArgument
;
6929 if (fReportClientCnt
== 1) {
6930 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
6936 case kIOReportGetDimensions
:
6938 STATEREPORT_UPDATERES(fReportBuf
, kIOReportGetDimensions
, result
);
6948 //*********************************************************************************
6949 // updatePowerStateReport
6951 // Updates the IOStateReport for kPMPowerStateChannel
6952 //*********************************************************************************
6954 IOService::updatePowerStatesReport( IOReportConfigureAction action
, void *result
, void *destination
)
6959 IOReturn rc
= kIOReturnSuccess
;
6960 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6964 return kIOReturnUnsupported
;
6966 if (!fNumberOfPowerStates
) {
6967 return kIOReturnSuccess
;
6970 if (!result
|| !dest
) {
6971 return kIOReturnBadArgument
;
6976 case kIOReportCopyChannelData
:
6978 rc
= kIOReturnNotOpen
;
6982 ts
= mach_absolute_time();
6983 STATEREPORT_UPDATEPREP(fReportBuf
, ts
, data2cpy
, size2cpy
);
6984 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
6985 rc
= kIOReturnOverrun
;
6989 STATEREPORT_UPDATERES(fReportBuf
, kIOReportCopyChannelData
, result
);
6990 dest
->appendBytes(data2cpy
, size2cpy
);
7002 //*********************************************************************************
7003 // configureSimplePowerReport
7005 // Configures the IOSimpleReport for given channel id
7006 //*********************************************************************************
7008 IOService::configureSimplePowerReport(IOReportConfigureAction action
, void *result
)
7010 IOReturn rc
= kIOReturnSuccess
;
7013 return kIOReturnUnsupported
;
7016 if (!fNumberOfPowerStates
) {
7021 case kIOReportEnable
:
7022 case kIOReportDisable
:
7025 case kIOReportGetDimensions
:
7026 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
7034 //*********************************************************************************
7035 // updateSimplePowerReport
7037 // Updates the IOSimpleReport for the given chanel id
7038 //*********************************************************************************
7040 IOService::updateSimplePowerReport( IOReportConfigureAction action
, void *result
, void *destination
)
7044 uint64_t buf
[SIMPLEREPORT_BUFSIZE
/ sizeof(uint64_t) + 1]; // Force a 8-byte alignment
7045 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
7046 IOReturn rc
= kIOReturnSuccess
;
7051 return kIOReturnUnsupported
;
7053 if (!result
|| !dest
) {
7054 return kIOReturnBadArgument
;
7057 if (!fNumberOfPowerStates
) {
7063 case kIOReportCopyChannelData
:
7065 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), kPMCurrStateChID
, kIOReportCategoryPower
);
7067 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMPowerOn
) {
7068 bits
|= kPMReportPowerOn
;
7070 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMDeviceUsable
) {
7071 bits
|= kPMReportDeviceUsable
;
7073 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMLowPower
) {
7074 bits
|= kPMReportLowPower
;
7078 SIMPLEREPORT_SETVALUE(buf
, ((bits
& 0xff) << 8) | ((StateOrder(fMaxPowerState
) & 0xf) << 4) |
7079 (StateOrder(fCurrentPowerState
) & 0xf));
7081 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
7082 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
7083 rc
= kIOReturnOverrun
;
7087 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
7088 dest
->appendBytes(data2cpy
, size2cpy
);
7097 return kIOReturnSuccess
;
7103 // MARK: Driver Overrides
7105 //*********************************************************************************
7106 // [public] setPowerState
7108 // Does nothing here. This should be implemented in a subclass driver.
7109 //*********************************************************************************
7112 IOService::setPowerState(
7113 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
7118 //*********************************************************************************
7119 // [public] maxCapabilityForDomainState
7121 // Finds the highest power state in the array whose input power requirement
7122 // is equal to the input parameter. Where a more intelligent decision is
7123 // possible, override this in the subclassed driver.
7124 //*********************************************************************************
7127 IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags
)
7129 IOPMPowerStateIndex stateIndex
;
7131 if (!fNumberOfPowerStates
) {
7132 return kPowerStateZero
;
7135 for (int order
= fNumberOfPowerStates
- 1; order
>= 0; order
--) {
7136 stateIndex
= fPowerStates
[order
].stateOrderToIndex
;
7138 if ((flags
& fPowerStates
[stateIndex
].inputPowerFlags
) ==
7139 fPowerStates
[stateIndex
].inputPowerFlags
) {
7143 return kPowerStateZero
;
7147 IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState
)
7149 return getPowerStateForDomainFlags(domainState
);
7152 //*********************************************************************************
7153 // [public] initialPowerStateForDomainState
7155 // Called to query the power state for the initial power transition.
7156 //*********************************************************************************
7159 IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState
)
7161 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
)) {
7162 // Return lowest power state for any root power domain changes
7163 return kPowerStateZero
;
7166 return getPowerStateForDomainFlags(domainState
);
7169 //*********************************************************************************
7170 // [public] powerStateForDomainState
7172 // This method is not called from PM.
7173 //*********************************************************************************
7176 IOService::powerStateForDomainState( IOPMPowerFlags domainState
)
7178 return getPowerStateForDomainFlags(domainState
);
7182 //*********************************************************************************
7183 // [deprecated] didYouWakeSystem
7185 // Does nothing here. This should be implemented in a subclass driver.
7186 //*********************************************************************************
7189 IOService::didYouWakeSystem( void )
7193 #endif /* !__LP64__ */
7195 //*********************************************************************************
7196 // [public] powerStateWillChangeTo
7198 // Does nothing here. This should be implemented in a subclass driver.
7199 //*********************************************************************************
7202 IOService::powerStateWillChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7204 return kIOPMAckImplied
;
7207 //*********************************************************************************
7208 // [public] powerStateDidChangeTo
7210 // Does nothing here. This should be implemented in a subclass driver.
7211 //*********************************************************************************
7214 IOService::powerStateDidChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7216 return kIOPMAckImplied
;
7219 //*********************************************************************************
7220 // [protected] powerChangeDone
7222 // Called from PM work loop thread.
7223 // Does nothing here. This should be implemented in a subclass policy-maker.
7224 //*********************************************************************************
7227 IOService::powerChangeDone( unsigned long )
7232 //*********************************************************************************
7233 // [deprecated] newTemperature
7235 // Does nothing here. This should be implemented in a subclass driver.
7236 //*********************************************************************************
7239 IOService::newTemperature( long currentTemp
, IOService
* whichZone
)
7243 #endif /* !__LP64__ */
7245 //*********************************************************************************
7246 // [public] systemWillShutdown
7248 // System shutdown and restart notification.
7249 //*********************************************************************************
7252 IOService::systemWillShutdown( IOOptionBits specifier
)
7254 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
7256 rootDomain
->acknowledgeSystemWillShutdown( this );
7261 // MARK: PM State Machine
7263 //*********************************************************************************
7264 // [private static] acquirePMRequest
7265 //*********************************************************************************
7268 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
7269 IOPMRequest
* active
)
7271 IOPMRequest
* request
;
7275 request
= IOPMRequest::create();
7277 request
->init( target
, requestType
);
7279 IOPMRequest
* root
= active
->getRootRequest();
7281 request
->attachRootRequest(root
);
7285 PM_ERROR("%s: No memory for PM request type 0x%x\n",
7286 target
->getName(), (uint32_t) requestType
);
7291 //*********************************************************************************
7292 // [private static] releasePMRequest
7293 //*********************************************************************************
7296 IOService::releasePMRequest( IOPMRequest
* request
)
7304 //*********************************************************************************
7305 // [private static] submitPMRequest
7306 //*********************************************************************************
7309 IOService::submitPMRequest( IOPMRequest
* request
)
7312 assert( gIOPMReplyQueue
);
7313 assert( gIOPMRequestQueue
);
7315 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7316 (long)request
->getType(), OBFUSCATE(request
),
7317 OBFUSCATE(request
->getTarget()), request
->getTarget()->getName(),
7318 OBFUSCATE(request
->fArg0
),
7319 OBFUSCATE(request
->fArg1
), OBFUSCATE(request
->fArg2
));
7321 if (request
->isReplyType()) {
7322 gIOPMReplyQueue
->queuePMRequest( request
);
7324 gIOPMRequestQueue
->queuePMRequest( request
);
7329 IOService::submitPMRequests( IOPMRequest
** requests
, IOItemCount count
)
7332 assert( count
> 0 );
7333 assert( gIOPMRequestQueue
);
7335 for (IOItemCount i
= 0; i
< count
; i
++) {
7336 IOPMRequest
* req
= requests
[i
];
7337 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7338 (long)req
->getType(), OBFUSCATE(req
),
7339 OBFUSCATE(req
->getTarget()), req
->getTarget()->getName(),
7340 OBFUSCATE(req
->fArg0
),
7341 OBFUSCATE(req
->fArg1
), OBFUSCATE(req
->fArg2
));
7344 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
7347 //*********************************************************************************
7348 // [private] actionPMRequestQueue
7350 // IOPMRequestQueue::checkForWork() passing a new request to the request target.
7351 //*********************************************************************************
7354 IOService::actionPMRequestQueue(
7355 IOPMRequest
* request
,
7356 IOPMRequestQueue
* queue
)
7361 // Work queue will immediately execute the request if the per-service
7362 // request queue is empty. Note pwrMgt is the target's IOServicePM.
7364 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
7366 // Calling PM without PMinit() is not allowed, fail the request.
7367 // Need to signal more when completing attached requests.
7369 PM_LOG("%s: PM not initialized\n", getName());
7370 PM_LOG1("[- %02x] %p [%p %s] !initialized\n",
7371 request
->getType(), OBFUSCATE(request
),
7372 OBFUSCATE(this), getName());
7374 more
= gIOPMCompletionQueue
->queuePMRequest(request
);
7376 gIOPMWorkQueue
->incrementProducerCount();
7383 //*********************************************************************************
7384 // [private] actionPMCompletionQueue
7386 // IOPMCompletionQueue::checkForWork() passing a completed request to the
7388 //*********************************************************************************
7391 IOService::actionPMCompletionQueue(
7392 IOPMRequest
* request
,
7393 IOPMCompletionQueue
* queue
)
7395 bool more
= (request
->getNextRequest() != NULL
);
7396 IOPMRequest
* root
= request
->getRootRequest();
7398 if (root
&& (root
!= request
)) {
7402 gIOPMWorkQueue
->incrementProducerCount();
7405 releasePMRequest( request
);
7409 //*********************************************************************************
7410 // [private] actionPMWorkQueueRetire
7412 // IOPMWorkQueue::checkForWork() passing a retired request to the request target.
7413 //*********************************************************************************
7416 IOService::actionPMWorkQueueRetire( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7418 assert(request
&& queue
);
7420 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7421 request
->getType(), OBFUSCATE(request
),
7422 OBFUSCATE(this), getName(),
7423 fMachineState
, gIOPMBusyRequestCount
);
7425 // Catch requests created by idleTimerExpired()
7426 if (request
->getType() == kIOPMRequestTypeActivityTickle
) {
7427 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
7429 if ((tickleFlags
& kTickleTypePowerDrop
) && fIdleTimerPeriod
) {
7431 } else if (tickleFlags
== (kTickleTypeActivity
| kTickleTypePowerRise
)) {
7432 // Invalidate any idle power drop that got queued while
7433 // processing this request.
7434 fIdleTimerGeneration
++;
7438 // When the completed request is linked, tell work queue there is
7439 // more work pending.
7441 return gIOPMCompletionQueue
->queuePMRequest( request
);
7444 //*********************************************************************************
7445 // [private] isPMBlocked
7447 // Check if machine state transition is blocked.
7448 //*********************************************************************************
7451 IOService::isPMBlocked( IOPMRequest
* request
, int count
)
7456 if (kIOPM_Finished
== fMachineState
) {
7460 if (kIOPM_DriverThreadCallDone
== fMachineState
) {
7461 // 5 = kDriverCallInformPreChange
7462 // 6 = kDriverCallInformPostChange
7463 // 7 = kDriverCallSetPowerState
7464 // 8 = kRootDomainInformPreChange
7465 if (fDriverCallBusy
) {
7466 reason
= 5 + fDriverCallReason
;
7471 // Waiting on driver's setPowerState() timeout.
7476 // Child or interested driver acks pending.
7477 if (fHeadNotePendingAcks
) {
7481 // Waiting on apps or priority power interest clients.
7482 if (fResponseArray
) {
7486 // Waiting on settle timer expiration.
7487 if (fSettleTimeUS
) {
7492 fWaitReason
= reason
;
7496 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7497 request
->getType(), OBFUSCATE(request
),
7498 OBFUSCATE(this), getName(),
7499 fMachineState
, reason
);
7508 //*********************************************************************************
7509 // [private] actionPMWorkQueueInvoke
7511 // IOPMWorkQueue::checkForWork() passing a request to the
7512 // request target for execution.
7513 //*********************************************************************************
7516 IOService::actionPMWorkQueueInvoke( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7521 assert(request
&& queue
);
7523 while (isPMBlocked(request
, loop
++) == false) {
7524 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7525 request
->getType(), OBFUSCATE(request
),
7526 OBFUSCATE(this), getName(), fMachineState
);
7528 gIOPMRequest
= request
;
7529 gIOPMWorkInvokeCount
++;
7531 // Every PM machine states must be handled in one of the cases below.
7533 switch (fMachineState
) {
7534 case kIOPM_Finished
:
7535 start_watchdog_timer();
7537 executePMRequest( request
);
7540 case kIOPM_OurChangeTellClientsPowerDown
:
7541 // Root domain might self cancel due to assertions.
7542 if (IS_ROOT_DOMAIN
) {
7543 bool cancel
= (bool) fDoNotPowerDown
;
7544 getPMRootDomain()->askChangeDownDone(
7545 &fHeadNoteChangeFlags
, &cancel
);
7546 fDoNotPowerDown
= cancel
;
7549 // askChangeDown() done, was it vetoed?
7550 if (!fDoNotPowerDown
) {
7551 // no, we can continue
7552 OurChangeTellClientsPowerDown();
7554 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7555 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7556 if (IS_ROOT_DOMAIN
) {
7557 // RootDomain already sent "WillSleep" to its clients
7558 tellChangeUp(fCurrentPowerState
);
7560 tellNoChangeDown(fHeadNotePowerState
);
7562 // mark the change note un-actioned
7563 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7569 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
7570 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7571 if (fDoNotPowerDown
) {
7572 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7573 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7574 if (IS_ROOT_DOMAIN
) {
7575 // RootDomain already sent "WillSleep" to its clients
7576 tellChangeUp(fCurrentPowerState
);
7578 tellNoChangeDown(fHeadNotePowerState
);
7580 // mark the change note un-actioned
7581 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7585 OurChangeTellUserPMPolicyPowerDown();
7589 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
7590 // PMRD: LastCallBeforeSleep notify done
7591 // Non-PMRD: tellChangeDown/kNotifyApps done
7592 if (fDoNotPowerDown
) {
7593 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7594 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7595 // no, tell clients we're back in the old state
7596 tellChangeUp(fCurrentPowerState
);
7597 // mark the change note un-actioned
7598 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7602 // yes, we can continue
7603 OurChangeTellPriorityClientsPowerDown();
7607 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
7608 OurChangeNotifyInterestedDriversWillChange();
7611 case kIOPM_OurChangeSetPowerState
:
7612 OurChangeSetPowerState();
7615 case kIOPM_OurChangeWaitForPowerSettle
:
7616 OurChangeWaitForPowerSettle();
7619 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
7620 OurChangeNotifyInterestedDriversDidChange();
7623 case kIOPM_OurChangeTellCapabilityDidChange
:
7624 OurChangeTellCapabilityDidChange();
7627 case kIOPM_OurChangeFinish
:
7631 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
7632 ParentChangeTellPriorityClientsPowerDown();
7635 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
7636 ParentChangeNotifyInterestedDriversWillChange();
7639 case kIOPM_ParentChangeSetPowerState
:
7640 ParentChangeSetPowerState();
7643 case kIOPM_ParentChangeWaitForPowerSettle
:
7644 ParentChangeWaitForPowerSettle();
7647 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7648 ParentChangeNotifyInterestedDriversDidChange();
7651 case kIOPM_ParentChangeTellCapabilityDidChange
:
7652 ParentChangeTellCapabilityDidChange();
7655 case kIOPM_ParentChangeAcknowledgePowerChange
:
7656 ParentChangeAcknowledgePowerChange();
7659 case kIOPM_DriverThreadCallDone
:
7660 switch (fDriverCallReason
) {
7661 case kDriverCallInformPreChange
:
7662 case kDriverCallInformPostChange
:
7663 notifyInterestedDriversDone();
7665 case kDriverCallSetPowerState
:
7666 notifyControllingDriverDone();
7668 case kRootDomainInformPreChange
:
7669 notifyRootDomainDone();
7672 panic("%s: bad call reason %x",
7673 getName(), fDriverCallReason
);
7677 case kIOPM_NotifyChildrenOrdered
:
7678 notifyChildrenOrdered();
7681 case kIOPM_NotifyChildrenDelayed
:
7682 notifyChildrenDelayed();
7685 case kIOPM_NotifyChildrenStart
:
7686 // pop notifyAll() state saved by notifyInterestedDriversDone()
7691 case kIOPM_SyncTellClientsPowerDown
:
7692 // Root domain might self cancel due to assertions.
7693 if (IS_ROOT_DOMAIN
) {
7694 bool cancel
= (bool) fDoNotPowerDown
;
7695 getPMRootDomain()->askChangeDownDone(
7696 &fHeadNoteChangeFlags
, &cancel
);
7697 fDoNotPowerDown
= cancel
;
7699 if (!fDoNotPowerDown
) {
7700 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7701 fOutOfBandParameter
= kNotifyApps
;
7702 tellChangeDown(fHeadNotePowerState
);
7704 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7705 // askChangeDown/kNotifyApps
7706 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7707 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7708 tellNoChangeDown(fHeadNotePowerState
);
7709 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7714 case kIOPM_SyncTellPriorityClientsPowerDown
:
7715 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7716 if (!fDoNotPowerDown
) {
7717 fMachineState
= kIOPM_SyncNotifyWillChange
;
7718 fOutOfBandParameter
= kNotifyPriority
;
7719 tellChangeDown(fHeadNotePowerState
);
7721 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7722 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7723 tellChangeUp(fCurrentPowerState
);
7724 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7729 case kIOPM_SyncNotifyWillChange
:
7730 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
) {
7731 fMachineState
= kIOPM_SyncFinish
;
7734 fMachineState
= kIOPM_SyncNotifyDidChange
;
7735 fDriverCallReason
= kDriverCallInformPreChange
;
7739 case kIOPM_SyncNotifyDidChange
:
7740 fIsPreChange
= false;
7742 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
7743 fMachineState
= kIOPM_SyncFinish
;
7745 assert(IS_ROOT_DOMAIN
);
7746 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7749 fDriverCallReason
= kDriverCallInformPostChange
;
7753 case kIOPM_SyncTellCapabilityDidChange
:
7754 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7757 case kIOPM_SyncFinish
:
7758 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
7759 ParentChangeAcknowledgePowerChange();
7765 case kIOPM_TellCapabilityChangeDone
:
7767 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
) {
7768 MS_POP(); // tellSystemCapabilityChange()
7771 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7773 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
) {
7774 MS_POP(); // tellSystemCapabilityChange()
7777 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7779 tellClientsWithResponse( fOutOfBandMessage
);
7783 panic("PMWorkQueueInvoke: unknown machine state %x",
7787 gIOPMRequest
= NULL
;
7789 if (fMachineState
== kIOPM_Finished
) {
7790 stop_watchdog_timer();
7799 //*********************************************************************************
7800 // [private] executePMRequest
7801 //*********************************************************************************
7804 IOService::executePMRequest( IOPMRequest
* request
)
7806 assert( kIOPM_Finished
== fMachineState
);
7808 switch (request
->getType()) {
7809 case kIOPMRequestTypePMStop
:
7810 handlePMstop( request
);
7813 case kIOPMRequestTypeAddPowerChild1
:
7814 addPowerChild1( request
);
7817 case kIOPMRequestTypeAddPowerChild2
:
7818 addPowerChild2( request
);
7821 case kIOPMRequestTypeAddPowerChild3
:
7822 addPowerChild3( request
);
7825 case kIOPMRequestTypeRegisterPowerDriver
:
7826 handleRegisterPowerDriver( request
);
7829 case kIOPMRequestTypeAdjustPowerState
:
7830 fAdjustPowerScheduled
= false;
7834 case kIOPMRequestTypePowerDomainWillChange
:
7835 handlePowerDomainWillChangeTo( request
);
7838 case kIOPMRequestTypePowerDomainDidChange
:
7839 handlePowerDomainDidChangeTo( request
);
7842 case kIOPMRequestTypeRequestPowerState
:
7843 case kIOPMRequestTypeRequestPowerStateOverride
:
7844 handleRequestPowerState( request
);
7847 case kIOPMRequestTypePowerOverrideOnPriv
:
7848 case kIOPMRequestTypePowerOverrideOffPriv
:
7849 handlePowerOverrideChanged( request
);
7852 case kIOPMRequestTypeActivityTickle
:
7853 handleActivityTickle( request
);
7856 case kIOPMRequestTypeSynchronizePowerTree
:
7857 handleSynchronizePowerTree( request
);
7860 case kIOPMRequestTypeSetIdleTimerPeriod
:
7862 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7863 fNextIdleTimerPeriod
= fIdleTimerPeriod
;
7864 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0)) {
7870 case kIOPMRequestTypeIgnoreIdleTimer
:
7871 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7874 case kIOPMRequestTypeQuiescePowerTree
:
7875 gIOPMWorkQueue
->finishQuiesceRequest(request
);
7879 panic("executePMRequest: unknown request type %x", request
->getType());
7883 //*********************************************************************************
7884 // [private] actionPMReplyQueue
7886 // IOPMRequestQueue::checkForWork() passing a reply-type request to the
7888 //*********************************************************************************
7891 IOService::actionPMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7895 assert( request
&& queue
);
7896 assert( request
->isReplyType());
7898 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7899 request
->getType(), OBFUSCATE(request
),
7900 OBFUSCATE(this), getName(), fMachineState
);
7902 switch (request
->getType()) {
7903 case kIOPMRequestTypeAllowPowerChange
:
7904 case kIOPMRequestTypeCancelPowerChange
:
7905 // Check if we are expecting this response.
7906 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7907 (int)(uintptr_t) request
->fArg1
)) {
7908 if (kIOPMRequestTypeCancelPowerChange
== request
->getType()) {
7909 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7910 // flag is set. Only root domain will set this flag.
7911 // However, there is one exception to this rule. User-space PM
7912 // policy may choose to cancel sleep even after all clients have
7913 // been notified that we will lower power.
7915 if ((fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7916 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7917 || ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0)) {
7918 fDoNotPowerDown
= true;
7920 OSString
* name
= (OSString
*) request
->fArg2
;
7921 getPMRootDomain()->pmStatsRecordApplicationResponse(
7922 gIOPMStatsResponseCancel
,
7923 name
? name
->getCStringNoCopy() : "", 0,
7924 0, (int)(uintptr_t) request
->fArg1
, NULL
);
7928 if (checkForDone()) {
7930 cleanClientResponses(false);
7934 // OSString containing app name in Arg2 must be released.
7935 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
) {
7936 OSObject
* obj
= (OSObject
*) request
->fArg2
;
7943 case kIOPMRequestTypeAckPowerChange
:
7944 more
= handleAcknowledgePowerChange( request
);
7947 case kIOPMRequestTypeAckSetPowerState
:
7948 if (fDriverTimer
== -1) {
7949 // driver acked while setPowerState() call is in-flight.
7950 // take this ack, return value from setPowerState() is irrelevant.
7951 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
7952 (uintptr_t) this, fDriverTimer
);
7954 } else if (fDriverTimer
> 0) {
7955 // expected ack, stop the timer
7958 getPMRootDomain()->reset_watchdog_timer(this, 0);
7960 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
7961 if (nsec
> LOG_SETPOWER_TIMES
) {
7962 getPMRootDomain()->pmStatsRecordApplicationResponse(
7963 gIOPMStatsDriverPSChangeSlow
,
7964 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
7965 NULL
, fHeadNotePowerState
);
7968 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
7973 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
7977 case kIOPMRequestTypeInterestChanged
:
7978 handleInterestChanged( request
);
7982 case kIOPMRequestTypeIdleCancel
:
7983 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
7984 || (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7985 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7986 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
7987 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
)) {
7988 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7989 PM_LOG2("%s: cancel from machine state %d\n",
7990 getName(), fMachineState
);
7991 fDoNotPowerDown
= true;
7992 // Stop waiting for app replys.
7993 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
7994 (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
) ||
7995 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
) ||
7996 (fMachineState
== kIOPM_SyncTellClientsPowerDown
)) {
7997 cleanClientResponses(false);
8003 case kIOPMRequestTypeChildNotifyDelayCancel
:
8004 if (fMachineState
== kIOPM_NotifyChildrenDelayed
) {
8005 PM_LOG2("%s: delay notify cancelled\n", getName());
8006 notifyChildrenDelayed();
8011 panic("PMReplyQueue: unknown reply type %x", request
->getType());
8014 more
|= gIOPMCompletionQueue
->queuePMRequest(request
);
8016 gIOPMWorkQueue
->incrementProducerCount();
8022 //*********************************************************************************
8023 // [private] assertPMDriverCall / deassertPMDriverCall
8024 //*********************************************************************************
8027 IOService::assertPMDriverCall(
8028 IOPMDriverCallEntry
* entry
,
8029 IOOptionBits method
,
8030 const IOPMinformee
* inform
,
8031 IOOptionBits options
)
8033 IOService
* target
= NULL
;
8042 if (fLockedFlags
.PMStop
) {
8046 if (((options
& kIOPMDriverCallNoInactiveCheck
) == 0) && isInactive()) {
8051 if (!inform
->active
) {
8054 target
= inform
->whatObject
;
8055 if (target
->isInactive()) {
8060 // Record calling address for sleep failure diagnostics
8062 case kIOPMDriverCallMethodSetPowerState
:
8063 entry
->callMethod
= OSMemberFunctionCast(const void *, fControllingDriver
, &IOService::setPowerState
);
8065 case kIOPMDriverCallMethodWillChange
:
8066 entry
->callMethod
= OSMemberFunctionCast(const void *, target
, &IOService::powerStateWillChangeTo
);
8068 case kIOPMDriverCallMethodDidChange
:
8069 entry
->callMethod
= OSMemberFunctionCast(const void *, target
, &IOService::powerStateDidChangeTo
);
8071 case kIOPMDriverCallMethodUnknown
:
8072 case kIOPMDriverCallMethodSetAggressive
:
8074 entry
->callMethod
= NULL
;
8078 entry
->thread
= current_thread();
8079 entry
->target
= target
;
8080 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8090 IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
8092 bool wakeup
= false;
8096 assert( !queue_empty(&fPMDriverCallQueue
));
8097 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8098 if (fLockedFlags
.PMDriverCallWait
) {
8105 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
8110 IOService::getBlockingDriverCall(thread_t
*thread
, const void **callMethod
)
8112 const IOPMDriverCallEntry
* entry
= NULL
;
8113 bool blocked
= false;
8119 if (current_thread() != gIOPMWatchDogThread
) {
8120 // Meant to be accessed only from watchdog thread
8125 entry
= qe_queue_first(&fPMDriverCallQueue
, IOPMDriverCallEntry
, link
);
8127 *thread
= entry
->thread
;
8128 *callMethod
= entry
->callMethod
;
8138 IOService::waitForPMDriverCall( IOService
* target
)
8140 const IOPMDriverCallEntry
* entry
;
8141 thread_t thread
= current_thread();
8142 AbsoluteTime deadline
;
8149 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
8151 // Target of interested driver call
8152 if (target
&& (target
!= entry
->target
)) {
8156 if (entry
->thread
== thread
) {
8158 PM_LOG("%s: %s(%s) on PM thread\n",
8159 fName
, __FUNCTION__
, target
? target
->getName() : "");
8160 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
8161 fName
, __FUNCTION__
, target
? target
->getName() : "");
8172 fLockedFlags
.PMDriverCallWait
= true;
8173 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
8174 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
8175 fLockedFlags
.PMDriverCallWait
= false;
8176 if (THREAD_TIMED_OUT
== waitResult
) {
8177 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
8184 //*********************************************************************************
8185 // [private] Debug helpers
8186 //*********************************************************************************
8189 IOService::getIOMessageString( uint32_t msg
)
8191 #define MSG_ENTRY(x) {(int) x, #x}
8193 static const IONamedValue msgNames
[] = {
8194 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
8195 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
8196 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
8197 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
8198 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
8199 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
8200 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
8201 MSG_ENTRY( kIOMessageCanSystemSleep
),
8202 MSG_ENTRY( kIOMessageSystemWillSleep
),
8203 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
8204 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
8205 MSG_ENTRY( kIOMessageSystemWillRestart
),
8206 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
8207 MSG_ENTRY( kIOMessageSystemCapabilityChange
),
8208 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep
),
8209 MSG_ENTRY( kIOMessageSystemPagingOff
),
8213 return IOFindNameForValue(msg
, msgNames
);
8218 // MARK: IOPMRequest
8220 //*********************************************************************************
8221 // IOPMRequest Class
8223 // Requests from PM clients, and also used for inter-object messaging within PM.
8224 //*********************************************************************************
8226 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
8229 IOPMRequest::create( void )
8231 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
8232 if (me
&& !me
->init(NULL
, kIOPMRequestTypeInvalid
)) {
8240 IOPMRequest::init( IOService
* target
, IOOptionBits type
)
8242 if (!IOCommand::init()) {
8246 fRequestType
= type
;
8253 // Root node and root domain requests does not prevent the power tree from
8254 // becoming quiescent.
8256 fIsQuiesceBlocker
= ((fTarget
!= gIOPMRootNode
) &&
8257 (fTarget
!= IOService::getPMRootDomain()));
8263 IOPMRequest::reset( void )
8265 assert( fWorkWaitCount
== 0 );
8266 assert( fFreeWaitCount
== 0 );
8268 detachNextRequest();
8269 detachRootRequest();
8271 if (fCompletionAction
&& (fRequestType
== kIOPMRequestTypeQuiescePowerTree
)) {
8272 // Call the completion on PM work loop context
8273 fCompletionAction(fCompletionTarget
, fCompletionParam
);
8274 fCompletionAction
= NULL
;
8277 fRequestType
= kIOPMRequestTypeInvalid
;
8286 IOPMRequest::attachNextRequest( IOPMRequest
* next
)
8290 if (!fRequestNext
) {
8291 // Postpone the execution of the next request after
8293 fRequestNext
= next
;
8294 fRequestNext
->fWorkWaitCount
++;
8295 #if LOG_REQUEST_ATTACH
8296 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8297 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8298 fRequestNext
->fRequestType
,
8299 (uint32_t) fRequestNext
->fWorkWaitCount
,
8300 fTarget
->getName());
8308 IOPMRequest::detachNextRequest( void )
8313 assert(fRequestNext
->fWorkWaitCount
);
8314 if (fRequestNext
->fWorkWaitCount
) {
8315 fRequestNext
->fWorkWaitCount
--;
8317 #if LOG_REQUEST_ATTACH
8318 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8319 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8320 fRequestNext
->fRequestType
,
8321 (uint32_t) fRequestNext
->fWorkWaitCount
,
8322 fTarget
->getName());
8324 fRequestNext
= NULL
;
8331 IOPMRequest::attachRootRequest( IOPMRequest
* root
)
8335 if (!fRequestRoot
) {
8336 // Delay the completion of the root request after
8338 fRequestRoot
= root
;
8339 fRequestRoot
->fFreeWaitCount
++;
8340 #if LOG_REQUEST_ATTACH
8341 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8342 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8343 (uint32_t) fRequestRoot
->fType
,
8344 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8345 fTarget
->getName());
8353 IOPMRequest::detachRootRequest( void )
8358 assert(fRequestRoot
->fFreeWaitCount
);
8359 if (fRequestRoot
->fFreeWaitCount
) {
8360 fRequestRoot
->fFreeWaitCount
--;
8362 #if LOG_REQUEST_ATTACH
8363 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8364 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8365 (uint32_t) fRequestRoot
->fType
,
8366 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8367 fTarget
->getName());
8369 fRequestRoot
= NULL
;
8376 // MARK: IOPMRequestQueue
8378 //*********************************************************************************
8379 // IOPMRequestQueue Class
8381 // Global queues. Queues are created once and never released.
8382 //*********************************************************************************
8384 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
8387 IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
8389 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
8390 if (me
&& !me
->init(inOwner
, inAction
)) {
8398 IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
8400 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
)) {
8404 queue_init(&fQueue
);
8405 fLock
= IOLockAlloc();
8406 return fLock
!= NULL
;
8410 IOPMRequestQueue::free( void )
8416 return IOEventSource::free();
8420 IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
8424 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8425 IOLockUnlock(fLock
);
8427 signalWorkAvailable();
8432 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
8436 assert(requests
&& count
);
8441 queue_enter(&fQueue
, next
, typeof(next
), fCommandChain
);
8443 IOLockUnlock(fLock
);
8445 signalWorkAvailable();
8450 IOPMRequestQueue::checkForWork( void )
8452 Action dqAction
= (Action
) action
;
8453 IOPMRequest
* request
;
8455 int dequeueCount
= 0;
8458 IOLockLock( fLock
);
8460 while (!queue_empty(&fQueue
)) {
8461 if (dequeueCount
++ >= kMaxDequeueCount
) {
8462 // Allow other queues a chance to work
8467 queue_remove_first(&fQueue
, request
, typeof(request
), fCommandChain
);
8468 IOLockUnlock(fLock
);
8469 target
= request
->getTarget();
8471 more
|= (*dqAction
)( target
, request
, this );
8472 IOLockLock( fLock
);
8475 IOLockUnlock( fLock
);
8480 // MARK: IOPMWorkQueue
8482 //*********************************************************************************
8483 // IOPMWorkQueue Class
8485 // Queue of IOServicePM objects, each with a queue of IOPMRequest sharing the
8487 //*********************************************************************************
8489 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
8492 IOPMWorkQueue::create( IOService
* inOwner
, Action invoke
, Action retire
)
8494 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
8495 if (me
&& !me
->init(inOwner
, invoke
, retire
)) {
8503 IOPMWorkQueue::init( IOService
* inOwner
, Action invoke
, Action retire
)
8505 if (!invoke
|| !retire
||
8506 !IOEventSource::init(inOwner
, (IOEventSourceAction
)NULL
)) {
8510 queue_init(&fWorkQueue
);
8512 fInvokeAction
= invoke
;
8513 fRetireAction
= retire
;
8514 fConsumerCount
= fProducerCount
= 0;
8520 IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
8522 queue_head_t
* requestQueue
;
8528 assert( onThread());
8529 assert( queue_next(&request
->fCommandChain
) ==
8530 queue_prev(&request
->fCommandChain
));
8532 gIOPMBusyRequestCount
++;
8534 if (request
->isQuiesceType()) {
8535 if ((request
->getTarget() == gIOPMRootNode
) && !fQuiesceStartTime
) {
8536 // Attach new quiesce request to all quiesce blockers in the queue
8537 fQuiesceStartTime
= mach_absolute_time();
8538 attachQuiesceRequest(request
);
8539 fQuiesceRequest
= request
;
8541 } else if (fQuiesceRequest
&& request
->isQuiesceBlocker()) {
8542 // Attach the new quiesce blocker to the blocked quiesce request
8543 request
->attachNextRequest(fQuiesceRequest
);
8546 // Add new request to the tail of the per-service request queue.
8547 // Then immediately check the request queue to minimize latency
8548 // if the queue was empty.
8550 requestQueue
= &pwrMgt
->RequestHead
;
8551 empty
= queue_empty(requestQueue
);
8552 queue_enter(requestQueue
, request
, typeof(request
), fCommandChain
);
8554 more
= checkRequestQueue(requestQueue
, &empty
);
8556 // Request just added is blocked, add its target IOServicePM
8557 // to the work queue.
8558 assert( queue_next(&pwrMgt
->WorkChain
) ==
8559 queue_prev(&pwrMgt
->WorkChain
));
8561 queue_enter(&fWorkQueue
, pwrMgt
, typeof(pwrMgt
), WorkChain
);
8563 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8564 fQueueLength
, pwrMgt
->Name
, OBFUSCATE(pwrMgt
));
8572 IOPMWorkQueue::checkRequestQueue( queue_head_t
* requestQueue
, bool * empty
)
8574 IOPMRequest
* request
;
8579 assert(!queue_empty(requestQueue
));
8581 request
= (typeof(request
))queue_first(requestQueue
);
8582 if (request
->isWorkBlocked()) {
8583 break; // request dispatch blocked on attached request
8585 target
= request
->getTarget();
8586 if (fInvokeAction
) {
8587 done
= (*fInvokeAction
)( target
, request
, this );
8589 PM_LOG("PM request 0x%x dropped\n", request
->getType());
8593 break; // PM state machine blocked
8595 assert(gIOPMBusyRequestCount
> 0);
8596 if (gIOPMBusyRequestCount
) {
8597 gIOPMBusyRequestCount
--;
8600 if (request
== fQuiesceRequest
) {
8601 fQuiesceRequest
= NULL
;
8604 queue_remove_first(requestQueue
, request
, typeof(request
), fCommandChain
);
8605 more
|= (*fRetireAction
)( target
, request
, this );
8606 done
= queue_empty(requestQueue
);
8612 // Retired a request that may unblock a previously visited request
8613 // that is still waiting on the work queue. Must trigger another
8622 IOPMWorkQueue::checkForWork( void )
8624 IOServicePM
* entry
;
8629 #if WORK_QUEUE_STATS
8630 fStatCheckForWork
++;
8633 // Iterate over all IOServicePM entries in the work queue,
8634 // and check each entry's request queue.
8636 while (fConsumerCount
!= fProducerCount
) {
8637 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8638 fProducerCount
, fConsumerCount
);
8640 fConsumerCount
= fProducerCount
;
8642 #if WORK_QUEUE_STATS
8643 if (queue_empty(&fWorkQueue
)) {
8648 uint32_t cachedWorkCount
= gIOPMWorkInvokeCount
;
8651 __IGNORE_WCASTALIGN(entry
= (typeof(entry
))queue_first(&fWorkQueue
));
8652 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
)) {
8653 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
8655 // Get next entry, points to head if current entry is last.
8656 __IGNORE_WCASTALIGN(next
= (typeof(next
))queue_next(&entry
->WorkChain
));
8658 // if request queue is empty, remove IOServicePM from work queue.
8660 assert(fQueueLength
);
8664 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8665 fQueueLength
, entry
->Name
, OBFUSCATE(entry
));
8666 queue_remove(&fWorkQueue
, entry
, typeof(entry
), WorkChain
);
8671 #if WORK_QUEUE_STATS
8672 if (cachedWorkCount
== gIOPMWorkInvokeCount
) {
8682 IOPMWorkQueue::signalWorkAvailable( void )
8685 IOEventSource::signalWorkAvailable();
8689 IOPMWorkQueue::incrementProducerCount( void )
8695 IOPMWorkQueue::attachQuiesceRequest( IOPMRequest
* quiesceRequest
)
8697 IOServicePM
* entry
;
8698 IOPMRequest
* request
;
8700 if (queue_empty(&fWorkQueue
)) {
8704 queue_iterate(&fWorkQueue
, entry
, typeof(entry
), WorkChain
)
8706 queue_iterate(&entry
->RequestHead
, request
, typeof(request
), fCommandChain
)
8708 // Attach the quiesce request to any request in the queue that
8709 // is not linked to a next request. These requests will block
8710 // the quiesce request.
8712 if (request
->isQuiesceBlocker()) {
8713 request
->attachNextRequest(quiesceRequest
);
8720 IOPMWorkQueue::finishQuiesceRequest( IOPMRequest
* quiesceRequest
)
8722 if (fQuiesceRequest
&& (quiesceRequest
== fQuiesceRequest
) &&
8723 (fQuiesceStartTime
!= 0)) {
8724 fInvokeAction
= NULL
;
8725 fQuiesceFinishTime
= mach_absolute_time();
8730 // MARK: IOPMCompletionQueue
8732 //*********************************************************************************
8733 // IOPMCompletionQueue Class
8734 //*********************************************************************************
8736 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
8738 IOPMCompletionQueue
*
8739 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
8741 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
8742 if (me
&& !me
->init(inOwner
, inAction
)) {
8750 IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
8752 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
)) {
8756 queue_init(&fQueue
);
8761 IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
8766 // unblock dependent request
8767 more
= request
->detachNextRequest();
8768 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8773 IOPMCompletionQueue::checkForWork( void )
8775 Action dqAction
= (Action
) action
;
8776 IOPMRequest
* request
;
8781 request
= (typeof(request
))queue_first(&fQueue
);
8782 while (!queue_end(&fQueue
, (queue_entry_t
) request
)) {
8783 next
= (typeof(next
))queue_next(&request
->fCommandChain
);
8784 if (!request
->isFreeBlocked()) {
8785 queue_remove(&fQueue
, request
, typeof(request
), fCommandChain
);
8786 target
= request
->getTarget();
8788 more
|= (*dqAction
)( target
, request
, this );
8797 // MARK: IOServicePM
8799 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8801 //*********************************************************************************
8804 // Serialize IOServicePM for debugging.
8805 //*********************************************************************************
8808 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8810 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8812 dict
->setObject(key
, num
);
8818 IOServicePM::gatedSerialize( OSSerialize
* s
) const
8820 OSDictionary
* dict
;
8822 int powerClamp
= -1;
8825 if (IdleTimerPeriod
) {
8829 if (PMActions
.parameter
& kPMActionsFlagLimitPower
) {
8832 if (PMActions
.parameter
&
8833 (kPMActionsFlagIsDisplayWrangler
| kPMActionsFlagIsGraphicsDevice
)) {
8838 #if WORK_QUEUE_STATS
8839 if (gIOPMRootNode
== ControllingDriver
) {
8845 dict
= OSDictionary::withDictionary(
8846 PowerClients
, PowerClients
->getCount() + dictSize
);
8848 dict
= OSDictionary::withCapacity(dictSize
);
8852 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8853 setPMProperty(dict
, "CapabilityFlags", CurrentCapabilityFlags
);
8854 if (NumberOfPowerStates
) {
8855 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
- 1);
8857 if (DesiredPowerState
!= CurrentPowerState
) {
8858 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8860 if (kIOPM_Finished
!= MachineState
) {
8861 setPMProperty(dict
, "MachineState", MachineState
);
8863 if (DeviceOverrideEnabled
) {
8864 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8866 if (powerClamp
>= 0) {
8867 setPMProperty(dict
, "PowerClamp", powerClamp
);
8870 if (IdleTimerPeriod
) {
8875 clock_get_uptime(&now
);
8877 // The idle timer period in milliseconds
8878 setPMProperty(dict
, "IdleTimerPeriod", NextIdleTimerPeriod
* 1000ULL);
8880 // Number of tickles since the last idle timer expiration
8881 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8883 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
)) {
8884 // Milliseconds since the last activity tickle
8886 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8887 absolutetime_to_nanoseconds(delta
, &nsecs
);
8888 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
8891 if (!IdleTimerStopped
&& AbsoluteTime_to_scalar(&IdleTimerStartTime
)) {
8892 // Idle timer elapsed time in milliseconds
8894 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
8895 absolutetime_to_nanoseconds(delta
, &nsecs
);
8896 setPMProperty(dict
, "IdleTimerElapsedTime", NS_TO_MS(nsecs
));
8900 #if WORK_QUEUE_STATS
8901 if (gIOPMRootNode
== Owner
) {
8902 setPMProperty(dict
, "WQ-CheckForWork",
8903 gIOPMWorkQueue
->fStatCheckForWork
);
8904 setPMProperty(dict
, "WQ-ScanEntries",
8905 gIOPMWorkQueue
->fStatScanEntries
);
8906 setPMProperty(dict
, "WQ-QueueEmpty",
8907 gIOPMWorkQueue
->fStatQueueEmpty
);
8908 setPMProperty(dict
, "WQ-NoWorkDone",
8909 gIOPMWorkQueue
->fStatNoWorkDone
);
8913 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
) {
8914 // Don't report advisory tickle when it has no influence
8915 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
8918 ok
= dict
->serialize(s
);
8922 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;
8926 IOServicePM::serialize( OSSerialize
* s
) const
8928 IOReturn ret
= kIOReturnNotReady
;
8930 if (gIOPMWatchDogThread
== current_thread()) {
8931 // Calling without lock as this data is collected for debug purpose, before reboot.
8932 // The workloop is probably already hung in state machine.
8933 ret
= gatedSerialize(s
);
8934 } else if (gIOPMWorkLoop
) {
8935 ret
= gIOPMWorkLoop
->runAction(
8936 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
8937 (OSObject
*) this, (void *) s
);
8940 return kIOReturnSuccess
== ret
;
8944 IOServicePM::pmPrint(
8947 uintptr_t param2
) const
8949 gPlatform
->PMLog(Name
, event
, param1
, param2
);
8953 IOServicePM::pmTrace(
8957 uintptr_t param2
) const
8959 uintptr_t nameAsArg
= 0;
8961 assert(event
< KDBG_CODE_MAX
);
8962 assert((eventFunc
& ~KDBG_FUNC_MASK
) == 0);
8964 // Copy the first characters of the name into an uintptr_t.
8965 // NULL termination is not required.
8966 strncpy((char*)&nameAsArg
, Name
, sizeof(nameAsArg
));
8968 IOTimeStampConstant(IODBG_POWER(event
) | eventFunc
, nameAsArg
, (uintptr_t)Owner
->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1
)), (uintptr_t)(OBFUSCATE(param2
)));