2 * Copyright (c) 1998-2020 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/IOUserServer.h>
36 #include <IOKit/IOEventSource.h>
37 #include <IOKit/IOWorkLoop.h>
38 #include <IOKit/IOCommand.h>
39 #include <IOKit/IOTimeStamp.h>
40 #include <IOKit/IOReportMacros.h>
41 #include <IOKit/IODeviceTreeSupport.h>
43 #include <IOKit/pwr_mgt/IOPMlog.h>
44 #include <IOKit/pwr_mgt/IOPMinformee.h>
45 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
46 #include <IOKit/pwr_mgt/IOPowerConnection.h>
47 #include <IOKit/pwr_mgt/RootDomain.h>
48 #include <IOKit/pwr_mgt/IOPMPrivate.h>
51 #include <sys/proc_internal.h>
52 #include <sys/sysctl.h>
53 #include <libkern/OSDebug.h>
54 #include <kern/thread.h>
56 // Required for notification instrumentation
57 #include "IOServicePrivate.h"
58 #include "IOServicePMPrivate.h"
59 #include "IOKitKernelInternal.h"
62 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
64 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
65 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
66 static void tellAppClientApplier(OSObject
* object
, void * arg
);
67 static const char * getNotificationPhaseString(uint32_t phase
);
70 computeTimeDeltaNS( const AbsoluteTime
* start
)
75 clock_get_uptime(&now
);
76 SUB_ABSOLUTETIME(&now
, start
);
77 absolutetime_to_nanoseconds(now
, &nsec
);
82 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
85 //******************************************************************************
87 //******************************************************************************
89 static bool gIOPMInitialized
= false;
90 static uint32_t gIOPMBusyRequestCount
= 0;
91 static uint32_t gIOPMWorkInvokeCount
= 0;
92 static uint32_t gIOPMTickleGeneration
= 0;
93 static IOWorkLoop
* gIOPMWorkLoop
= NULL
;
94 static IOPMRequestQueue
* gIOPMRequestQueue
= NULL
;
95 static IOPMRequestQueue
* gIOPMReplyQueue
= NULL
;
96 static IOPMWorkQueue
* gIOPMWorkQueue
= NULL
;
97 static IOPMCompletionQueue
* gIOPMCompletionQueue
= NULL
;
98 static IOPMRequest
* gIOPMRequest
= NULL
;
99 static IOService
* gIOPMRootNode
= NULL
;
100 static IOPlatformExpert
* gPlatform
= NULL
;
102 // log setPowerStates and powerStateChange longer than (ns):
103 static uint64_t gIOPMSetPowerStateLogNS
=
104 #if defined(__i386__) || defined(__x86_64__)
105 (300ULL * 1000ULL * 1000ULL)
107 (50ULL * 1000ULL * 1000ULL)
111 const OSSymbol
* gIOPMPowerClientDevice
= NULL
;
112 const OSSymbol
* gIOPMPowerClientDriver
= NULL
;
113 const OSSymbol
* gIOPMPowerClientChildProxy
= NULL
;
114 const OSSymbol
* gIOPMPowerClientChildren
= NULL
;
115 const OSSymbol
* gIOPMPowerClientRootDomain
= NULL
;
117 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= NULL
;
118 static bool gIOPMAdvisoryTickleEnabled
= true;
119 static thread_t gIOPMWatchDogThread
= NULL
;
120 uint32_t gCanSleepTimeout
= 0;
123 getPMRequestType( void )
125 uint32_t type
= kIOPMRequestTypeInvalid
;
127 type
= gIOPMRequest
->getType();
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)
175 #if !defined(XNU_TARGET_OS_OSX)
176 #define kCanSleepMaxTimeReq k5Seconds
177 #else /* defined(XNU_TARGET_OS_OSX) */
178 #define kCanSleepMaxTimeReq k30Seconds
179 #endif /* defined(XNU_TARGET_OS_OSX) */
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 app responses longer than (ns):
229 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
230 // use message tracer to log messages longer than (ns):
231 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
233 // log kext responses longer than (ns):
234 #define LOG_KEXT_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
237 kReserveDomainPower
= 1
241 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
242 assert(kIOPM_BadMachineState != n); \
243 fSavedMachineState = n; } while (false)
246 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
247 fMachineState = fSavedMachineState; \
248 fSavedMachineState = kIOPM_BadMachineState; } while (false)
250 #define PM_ACTION_TICKLE(a) \
251 do { if (fPMActions.a) { \
252 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
255 #define PM_ACTION_CHANGE(a, x, y) \
256 do { if (fPMActions.a) { \
257 (fPMActions.a)(fPMActions.target, this, &fPMActions, gIOPMRequest, x, y); } \
260 #define PM_ACTION_CLIENT(a, x, y, z) \
261 do { if (fPMActions.a) { \
262 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, z); } \
265 static OSNumber
* copyClientIDForNotification(
267 IOPMInterestContext
*context
);
269 static void logClientIDForNotification(
271 IOPMInterestContext
*context
,
272 const char *logString
);
274 //*********************************************************************************
277 // Check kgmacros after modifying machine states.
278 //*********************************************************************************
283 kIOPM_OurChangeTellClientsPowerDown
= 1,
284 kIOPM_OurChangeTellUserPMPolicyPowerDown
= 2,
285 kIOPM_OurChangeTellPriorityClientsPowerDown
= 3,
286 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 4,
287 kIOPM_OurChangeSetPowerState
= 5,
288 kIOPM_OurChangeWaitForPowerSettle
= 6,
289 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 7,
290 kIOPM_OurChangeTellCapabilityDidChange
= 8,
291 kIOPM_OurChangeFinish
= 9,
293 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
294 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
295 kIOPM_ParentChangeSetPowerState
= 12,
296 kIOPM_ParentChangeWaitForPowerSettle
= 13,
297 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
298 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
299 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
301 kIOPM_NotifyChildrenStart
= 17,
302 kIOPM_NotifyChildrenOrdered
= 18,
303 kIOPM_NotifyChildrenDelayed
= 19,
304 kIOPM_SyncTellClientsPowerDown
= 20,
305 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
306 kIOPM_SyncNotifyWillChange
= 22,
307 kIOPM_SyncNotifyDidChange
= 23,
308 kIOPM_SyncTellCapabilityDidChange
= 24,
309 kIOPM_SyncFinish
= 25,
310 kIOPM_TellCapabilityChangeDone
= 26,
311 kIOPM_DriverThreadCallDone
= 27,
313 kIOPM_BadMachineState
= 0xFFFFFFFF
316 //*********************************************************************************
319 // Initialize power management.
320 //*********************************************************************************
323 IOService::PMinit( void )
326 if (!gIOPMInitialized
) {
327 gPlatform
= getPlatform();
328 gIOPMWorkLoop
= IOWorkLoop::workLoop();
330 gIOPMRequestQueue
= IOPMRequestQueue::create(
331 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
332 this, &IOService::actionPMRequestQueue
));
334 gIOPMReplyQueue
= IOPMRequestQueue::create(
335 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
336 this, &IOService::actionPMReplyQueue
));
338 gIOPMWorkQueue
= IOPMWorkQueue::create(this,
339 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
340 &IOService::actionPMWorkQueueInvoke
),
341 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
342 &IOService::actionPMWorkQueueRetire
));
344 gIOPMCompletionQueue
= IOPMCompletionQueue::create(
345 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
346 this, &IOService::actionPMCompletionQueue
));
348 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
350 gIOPMRequestQueue
->release();
351 gIOPMRequestQueue
= NULL
;
354 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
356 gIOPMReplyQueue
->release();
357 gIOPMReplyQueue
= NULL
;
360 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
362 gIOPMWorkQueue
->release();
363 gIOPMWorkQueue
= NULL
;
366 // Must be added after the work queue, which pushes request
367 // to the completion queue without signaling the work loop.
368 if (gIOPMWorkLoop
->addEventSource(gIOPMCompletionQueue
) !=
370 gIOPMCompletionQueue
->release();
371 gIOPMCompletionQueue
= NULL
;
374 gIOPMPowerClientDevice
=
375 OSSymbol::withCStringNoCopy( "DevicePowerState" );
377 gIOPMPowerClientDriver
=
378 OSSymbol::withCStringNoCopy( "DriverPowerState" );
380 gIOPMPowerClientChildProxy
=
381 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
383 gIOPMPowerClientChildren
=
384 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
386 gIOPMPowerClientAdvisoryTickle
=
387 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
389 gIOPMPowerClientRootDomain
=
390 OSSymbol::withCStringNoCopy( "RootDomainPower" );
393 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMCompletionQueue
) {
394 gIOPMInitialized
= true;
397 #if (DEVELOPMENT || DEBUG)
398 uint32_t setPowerStateLogMS
= 0;
399 if (PE_parse_boot_argn("setpowerstate_log", &setPowerStateLogMS
, sizeof(setPowerStateLogMS
))) {
400 gIOPMSetPowerStateLogNS
= setPowerStateLogMS
* 1000000ULL;
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);
465 fSettleTimer
= thread_call_allocate(
466 &settle_timer_expired
, (thread_call_param_t
)this);
468 fIdleTimer
= thread_call_allocate(
469 &idle_timer_expired
, (thread_call_param_t
)this);
470 fDriverCallEntry
= thread_call_allocate(
471 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
472 assert(fDriverCallEntry
);
474 // Check for powerChangeDone override.
475 if (OSMemberFunctionCast(void (*)(void),
476 getResourceService(), &IOService::powerChangeDone
) !=
477 OSMemberFunctionCast(void (*)(void),
478 this, &IOService::powerChangeDone
)) {
479 fPCDFunctionOverride
= true;
483 IOPMprot
* prot
= new IOPMprot
;
486 prot
->ourName
= fName
;
487 prot
->thePlatform
= gPlatform
;
492 pm_vars
= (void *) (uintptr_t) true;
499 //*********************************************************************************
502 // Free the data created by PMinit. Only called from IOService::free().
503 //*********************************************************************************
506 IOService::PMfree( void )
512 assert(fMachineState
== kIOPM_Finished
);
513 assert(fInsertInterestSet
== NULL
);
514 assert(fRemoveInterestSet
== NULL
);
515 assert(fNotifyChildArray
== NULL
);
516 assert(queue_empty(&pwrMgt
->RequestHead
));
517 assert(queue_empty(&fPMDriverCallQueue
));
519 if (fWatchdogTimer
) {
520 thread_call_cancel(fWatchdogTimer
);
521 thread_call_free(fWatchdogTimer
);
522 fWatchdogTimer
= NULL
;
526 IOLockFree(fWatchdogLock
);
527 fWatchdogLock
= NULL
;
531 fBlockedArray
->release();
532 fBlockedArray
= NULL
;
536 thread_call_cancel(fSettleTimer
);
537 thread_call_free(fSettleTimer
);
542 thread_call_cancel(fAckTimer
);
543 thread_call_free(fAckTimer
);
547 thread_call_cancel(fIdleTimer
);
548 thread_call_free(fIdleTimer
);
551 if (fDriverCallEntry
) {
552 thread_call_free(fDriverCallEntry
);
553 fDriverCallEntry
= NULL
;
560 IOLockFree(fActivityLock
);
561 fActivityLock
= NULL
;
563 if (fInterestedDrivers
) {
564 fInterestedDrivers
->release();
565 fInterestedDrivers
= NULL
;
567 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
568 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
569 fDriverCallParamPtr
= NULL
;
570 fDriverCallParamSlots
= 0;
572 if (fResponseArray
) {
573 fResponseArray
->release();
574 fResponseArray
= NULL
;
576 if (fNotifyClientArray
) {
577 fNotifyClientArray
->release();
578 fNotifyClientArray
= NULL
;
580 if (fReportBuf
&& fNumberOfPowerStates
) {
581 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
584 if (fPowerStates
&& fNumberOfPowerStates
) {
585 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
586 fNumberOfPowerStates
= 0;
590 fPowerClients
->release();
591 fPowerClients
= NULL
;
607 IOService::PMDebug( uint32_t event
, uintptr_t param1
, uintptr_t param2
)
609 OUR_PMLog(event
, param1
, param2
);
612 //*********************************************************************************
613 // [public] joinPMtree
615 // A policy-maker calls its nub here when initializing, to be attached into
616 // the power management hierarchy. The default function is to call the
617 // platform expert, which knows how to do it. This method is overridden
618 // by a nub subclass which may either know how to do it, or may need to
619 // take other action.
621 // This may be the only "power management" method used in a nub,
622 // meaning it may not be initialized for power management.
623 //*********************************************************************************
626 IOService::joinPMtree( IOService
* driver
)
628 IOPlatformExpert
* platform
;
630 platform
= getPlatform();
631 assert(platform
!= NULL
);
632 platform
->PMRegisterDevice(this, driver
);
636 //*********************************************************************************
637 // [deprecated] youAreRoot
639 // Power Managment is informing us that we are the root power domain.
640 //*********************************************************************************
643 IOService::youAreRoot( void )
647 #endif /* !__LP64__ */
649 //*********************************************************************************
652 // Immediately stop driver callouts. Schedule an async stop request to detach
654 //*********************************************************************************
657 IOService::PMstop( void )
659 IOPMRequest
* request
;
667 if (fLockedFlags
.PMStop
) {
668 PM_LOG2("%s: PMstop() already stopped\n", fName
);
673 // Inhibit future driver calls.
674 fLockedFlags
.PMStop
= true;
676 // Wait for all prior driver calls to finish.
677 waitForPMDriverCall();
681 // The rest of the work is performed async.
682 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
684 PM_LOG2("%s: %p PMstop\n", getName(), OBFUSCATE(this));
685 submitPMRequest( request
);
689 //*********************************************************************************
690 // [private] handlePMstop
692 // Disconnect the node from all parents and children in the power plane.
693 //*********************************************************************************
696 IOService::handlePMstop( IOPMRequest
* request
)
700 IOPowerConnection
* connection
;
701 IOService
* theChild
;
702 IOService
* theParent
;
705 PM_LOG2("%s: %p %s start\n", getName(), OBFUSCATE(this), __FUNCTION__
);
707 // remove driver from prevent system sleep lists
708 getPMRootDomain()->updatePreventIdleSleepList(this, false);
709 getPMRootDomain()->updatePreventSystemSleepList(this, false);
711 // remove the property
712 removeProperty(kPwrMgtKey
);
715 iter
= getParentIterator(gIOPowerPlane
);
717 while ((next
= iter
->getNextObject())) {
718 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
719 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
721 theParent
->removePowerChild(connection
);
722 theParent
->release();
729 // detach IOConnections
730 detachAbove( gIOPowerPlane
);
732 // no more power state changes
733 fParentsKnowState
= false;
736 iter
= getChildIterator(gIOPowerPlane
);
738 while ((next
= iter
->getNextObject())) {
739 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
740 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
742 // detach nub from child
743 connection
->detachFromChild(theChild
, gIOPowerPlane
);
746 // detach us from nub
747 detachFromChild(connection
, gIOPowerPlane
);
753 // Remove all interested drivers from the list, including the power
754 // controlling driver.
756 // Usually, the controlling driver and the policy-maker functionality
757 // are implemented by the same object, and without the deregistration,
758 // the object will be holding an extra retain on itself, and cannot
761 if (fInterestedDrivers
) {
762 IOPMinformeeList
* list
= fInterestedDrivers
;
766 while ((item
= list
->firstInList())) {
767 list
->removeFromList(item
->whatObject
);
772 // Clear idle period to prevent idleTimerExpired() from servicing
773 // idle timer expirations.
775 fIdleTimerPeriod
= 0;
776 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
)) {
780 PM_LOG2("%s: %p %s done\n", getName(), OBFUSCATE(this), __FUNCTION__
);
783 //*********************************************************************************
784 // [public] addPowerChild
786 // Power Management is informing us who our children are.
787 //*********************************************************************************
790 IOService::addPowerChild( IOService
* child
)
792 IOPowerConnection
* connection
= NULL
;
793 IOPMRequest
* requests
[3] = {NULL
, NULL
, NULL
};
798 return kIOReturnBadArgument
;
801 if (!initialized
|| !child
->initialized
) {
802 return IOPMNotYetInitialized
;
805 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
808 // Is this child already one of our children?
810 iter
= child
->getParentIterator( gIOPowerPlane
);
812 IORegistryEntry
* entry
;
815 while ((next
= iter
->getNextObject())) {
816 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
817 isChild(entry
, gIOPowerPlane
)) {
825 PM_LOG2("%s: %s (%p) is already a child\n",
826 getName(), child
->getName(), OBFUSCATE(child
));
830 // Add the child to the power plane immediately, but the
831 // joining connection is marked as not ready.
832 // We want the child to appear in the power plane before
833 // returning to the caller, but don't want the caller to
834 // block on the PM work loop.
836 connection
= new IOPowerConnection
;
841 // Create a chain of PM requests to perform the bottom-half
842 // work from the PM work loop.
844 requests
[0] = acquirePMRequest(
846 /* type */ kIOPMRequestTypeAddPowerChild1
);
848 requests
[1] = acquirePMRequest(
850 /* type */ kIOPMRequestTypeAddPowerChild2
);
852 requests
[2] = acquirePMRequest(
854 /* type */ kIOPMRequestTypeAddPowerChild3
);
856 if (!requests
[0] || !requests
[1] || !requests
[2]) {
860 requests
[0]->attachNextRequest( requests
[1] );
861 requests
[1]->attachNextRequest( requests
[2] );
864 connection
->start(this);
865 connection
->setAwaitingAck(false);
866 connection
->setReadyFlag(false);
868 attachToChild( connection
, gIOPowerPlane
);
869 connection
->attachToChild( child
, gIOPowerPlane
);
871 // connection needs to be released
872 requests
[0]->fArg0
= connection
;
873 requests
[1]->fArg0
= connection
;
874 requests
[2]->fArg0
= connection
;
876 submitPMRequests( requests
, 3 );
877 return kIOReturnSuccess
;
881 connection
->release();
884 releasePMRequest(requests
[0]);
887 releasePMRequest(requests
[1]);
890 releasePMRequest(requests
[2]);
893 // Silent failure, to prevent platform drivers from adding the child
894 // to the root domain.
896 return kIOReturnSuccess
;
899 //*********************************************************************************
900 // [private] addPowerChild1
902 // Step 1/3 of adding a power child. Called on the power parent.
903 //*********************************************************************************
906 IOService::addPowerChild1( IOPMRequest
* request
)
908 IOPMPowerStateIndex tempDesire
= kPowerStateZero
;
910 // Make us temporary usable before adding the child.
913 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
915 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
) {
916 tempDesire
= fHighestPowerState
;
919 if ((tempDesire
!= kPowerStateZero
) &&
920 (IS_PM_ROOT
|| (StateOrder(fMaxPowerState
) >= StateOrder(tempDesire
)))) {
921 adjustPowerState(tempDesire
);
925 //*********************************************************************************
926 // [private] addPowerChild2
928 // Step 2/3 of adding a power child. Called on the joining child.
929 // Execution blocked behind addPowerChild1.
930 //*********************************************************************************
933 IOService::addPowerChild2( IOPMRequest
* request
)
935 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
937 IOPMPowerFlags powerFlags
;
939 IOPMPowerStateIndex powerState
;
940 IOPMPowerStateIndex tempDesire
;
943 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
945 if (!parent
|| !inPlane(gIOPowerPlane
)) {
946 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
950 // Parent will be waiting for us to complete this stage.
951 // It is safe to directly access parent's vars.
953 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
954 powerState
= parent
->fCurrentPowerState
;
957 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
962 // Set our power parent.
964 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
966 setParentInfo( powerFlags
, connection
, knowsState
);
968 connection
->setReadyFlag(true);
970 if (fControllingDriver
&& fParentsKnowState
) {
971 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
972 // initially change into the state we are already in
973 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
974 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
975 adjustPowerState(tempDesire
);
979 //*********************************************************************************
980 // [private] addPowerChild3
982 // Step 3/3 of adding a power child. Called on the parent.
983 // Execution blocked behind addPowerChild2.
984 //*********************************************************************************
987 IOService::addPowerChild3( IOPMRequest
* request
)
989 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
991 IOPMrootDomain
* rootDomain
= getPMRootDomain();
994 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
996 if (child
&& inPlane(gIOPowerPlane
)) {
997 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder")) {
998 PM_LOG1("%s: strict PM order enforced\n", getName());
999 fStrictTreeOrder
= true;
1003 rootDomain
->joinAggressiveness( child
);
1006 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1009 connection
->release();
1013 //*********************************************************************************
1014 // [deprecated] setPowerParent
1016 // Power Management is informing us who our parent is.
1017 // If we have a controlling driver, find out, given our newly-informed
1018 // power domain state, what state it would be in, and then tell it
1019 // to assume that state.
1020 //*********************************************************************************
1023 IOService::setPowerParent(
1024 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
1026 return kIOReturnUnsupported
;
1028 #endif /* !__LP64__ */
1030 //*********************************************************************************
1031 // [public] removePowerChild
1033 // Called on a parent whose child is being removed by PMstop().
1034 //*********************************************************************************
1037 IOService::removePowerChild( IOPowerConnection
* theNub
)
1039 IORegistryEntry
* theChild
;
1041 PM_ASSERT_IN_GATE();
1042 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1046 // detach nub from child
1047 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1049 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1050 theChild
->release();
1052 // detach from the nub
1053 detachFromChild(theNub
, gIOPowerPlane
);
1055 // Are we awaiting an ack from this child?
1056 if (theNub
->getAwaitingAck()) {
1057 // yes, pretend we got one
1058 theNub
->setAwaitingAck(false);
1059 if (fHeadNotePendingAcks
!= 0) {
1060 // that's one fewer ack to worry about
1061 fHeadNotePendingAcks
--;
1063 // is that the last?
1064 if (fHeadNotePendingAcks
== 0) {
1066 getPMRootDomain()->reset_watchdog_timer(this, 0);
1068 // This parent may have a request in the work queue that is
1069 // blocked on fHeadNotePendingAcks=0. And removePowerChild()
1070 // is called while executing the child's PMstop request so they
1071 // can occur simultaneously. IOPMWorkQueue::checkForWork() must
1072 // restart and check all request queues again.
1074 gIOPMWorkQueue
->incrementProducerCount();
1081 // A child has gone away, re-scan children desires and clamp bits.
1082 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1084 if (!fAdjustPowerScheduled
) {
1085 IOPMRequest
* request
;
1086 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1088 submitPMRequest( request
);
1089 fAdjustPowerScheduled
= true;
1096 //*********************************************************************************
1097 // [public] registerPowerDriver
1099 // A driver has called us volunteering to control power to our device.
1100 //*********************************************************************************
1103 IOService::registerPowerDriver(
1104 IOService
* powerDriver
,
1105 IOPMPowerState
* powerStates
,
1106 unsigned long numberOfStates
)
1108 IOPMRequest
* request
;
1109 IOPMPSEntry
* powerStatesCopy
= NULL
;
1110 IOPMPowerStateIndex stateOrder
;
1111 IOReturn error
= kIOReturnSuccess
;
1114 return IOPMNotYetInitialized
;
1117 if (!powerStates
|| (numberOfStates
< 2)) {
1118 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1119 return kIOReturnBadArgument
;
1122 if (!powerDriver
|| !powerDriver
->initialized
) {
1123 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1124 return kIOReturnBadArgument
;
1127 if (powerStates
[0].version
> kIOPMPowerStateVersion2
) {
1128 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1129 return kIOReturnBadArgument
;
1133 // Make a copy of the supplied power state array.
1134 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1135 if (!powerStatesCopy
) {
1136 error
= kIOReturnNoMemory
;
1140 // Initialize to bogus values
1141 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++) {
1142 powerStatesCopy
[i
].stateOrderToIndex
= kIOPMPowerStateMax
;
1145 for (uint32_t i
= 0; i
< numberOfStates
; i
++) {
1146 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1147 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1148 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1149 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1150 #if USE_SETTLE_TIMER
1151 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1152 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1154 if (powerStates
[i
].version
>= kIOPMPowerStateVersion2
) {
1155 stateOrder
= powerStates
[i
].stateOrder
;
1160 if (stateOrder
< numberOfStates
) {
1161 powerStatesCopy
[i
].stateOrder
= stateOrder
;
1162 powerStatesCopy
[stateOrder
].stateOrderToIndex
= i
;
1166 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++) {
1167 if (powerStatesCopy
[i
].stateOrderToIndex
== kIOPMPowerStateMax
) {
1168 // power state order missing
1169 error
= kIOReturnBadArgument
;
1173 if (kIOReturnSuccess
!= error
) {
1177 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1179 error
= kIOReturnNoMemory
;
1183 powerDriver
->retain();
1184 request
->fArg0
= (void *) powerDriver
;
1185 request
->fArg1
= (void *) powerStatesCopy
;
1186 request
->fArg2
= (void *) numberOfStates
;
1188 submitPMRequest( request
);
1189 return kIOReturnSuccess
;
1192 if (powerStatesCopy
) {
1193 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1199 //*********************************************************************************
1200 // [private] handleRegisterPowerDriver
1201 //*********************************************************************************
1204 IOService::handleRegisterPowerDriver( IOPMRequest
* request
)
1206 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1207 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1208 IOPMPowerStateIndex numberOfStates
= (IOPMPowerStateIndex
) request
->fArg2
;
1209 IOPMPowerStateIndex i
, stateIndex
;
1210 IOPMPowerStateIndex lowestPowerState
;
1214 PM_ASSERT_IN_GATE();
1215 assert(powerStates
);
1216 assert(powerDriver
);
1217 assert(numberOfStates
> 1);
1219 if (!fNumberOfPowerStates
) {
1220 OUR_PMLog(kPMLogControllingDriver
, numberOfStates
, kIOPMPowerStateVersion1
);
1222 fPowerStates
= powerStates
;
1223 fNumberOfPowerStates
= numberOfStates
;
1224 fControllingDriver
= powerDriver
;
1225 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1227 lowestPowerState
= fPowerStates
[0].stateOrderToIndex
;
1228 fHighestPowerState
= fPowerStates
[numberOfStates
- 1].stateOrderToIndex
;
1232 IOService
* service
;
1236 // Disallow kIOPMAOTPower states unless device tree enabled
1240 while (service
&& !service
->inPlane(gIODTPlane
)) {
1241 service
= service
->getProvider();
1244 object
= service
->copyProperty(kIOPMAOTPowerKey
, gIODTPlane
);
1245 data
= OSDynamicCast(OSData
, object
);
1246 if (data
&& (data
->getLength() >= sizeof(uint32_t))) {
1247 aotFlags
= ((uint32_t *)data
->getBytesNoCopy())[0];
1249 OSSafeReleaseNULL(object
);
1252 for (i
= 0; i
< numberOfStates
; i
++) {
1253 if (kIOPMAOTPower
& fPowerStates
[i
].inputPowerFlags
) {
1254 fPowerStates
[i
].inputPowerFlags
= 0xFFFFFFFF;
1255 fPowerStates
[i
].capabilityFlags
= 0;
1256 fPowerStates
[i
].outputPowerFlags
= 0;
1262 // OR'in all the output power flags
1263 fMergedOutputPowerFlags
= 0;
1264 fDeviceUsablePowerState
= lowestPowerState
;
1265 for (i
= 0; i
< numberOfStates
; i
++) {
1266 fMergedOutputPowerFlags
|= fPowerStates
[i
].outputPowerFlags
;
1268 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
1269 assert(stateIndex
< numberOfStates
);
1270 if ((fDeviceUsablePowerState
== lowestPowerState
) &&
1271 (fPowerStates
[stateIndex
].capabilityFlags
& IOPMDeviceUsable
)) {
1272 // The minimum power state that the device is usable
1273 fDeviceUsablePowerState
= stateIndex
;
1277 // Register powerDriver as interested, unless already done.
1278 // We don't want to register the default implementation since
1279 // it does nothing. One ramification of not always registering
1280 // is the one fewer retain count held.
1282 root
= getPlatform()->getProvider();
1285 ((OSMemberFunctionCast(void (*)(void),
1286 root
, &IOService::powerStateDidChangeTo
)) !=
1287 ((OSMemberFunctionCast(void (*)(void),
1288 this, &IOService::powerStateDidChangeTo
)))) ||
1289 ((OSMemberFunctionCast(void (*)(void),
1290 root
, &IOService::powerStateWillChangeTo
)) !=
1291 ((OSMemberFunctionCast(void (*)(void),
1292 this, &IOService::powerStateWillChangeTo
))))) {
1293 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
) {
1295 fInterestedDrivers
->appendNewInformee(powerDriver
);
1300 // Examine all existing power clients and perform limit check.
1302 if (fPowerClients
&&
1303 (iter
= OSCollectionIterator::withCollection(fPowerClients
))) {
1304 const OSSymbol
* client
;
1305 while ((client
= (const OSSymbol
*) iter
->getNextObject())) {
1306 IOPMPowerStateIndex powerState
= getPowerStateForClient(client
);
1307 if (powerState
>= numberOfStates
) {
1308 updatePowerClient(client
, fHighestPowerState
);
1314 // Populate IOPMActions for a few special services
1315 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
, fNumberOfPowerStates
- 1);
1317 if (inPlane(gIOPowerPlane
) && fParentsKnowState
) {
1318 IOPMPowerStateIndex tempDesire
;
1319 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1320 // initially change into the state we are already in
1321 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1322 adjustPowerState(tempDesire
);
1325 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1326 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1329 powerDriver
->release();
1332 //*********************************************************************************
1333 // [public] registerInterestedDriver
1335 // Add the caller to our list of interested drivers and return our current
1336 // power state. If we don't have a power-controlling driver yet, we will
1337 // call this interested driver again later when we do get a driver and find
1338 // out what the current power state of the device is.
1339 //*********************************************************************************
1342 IOService::registerInterestedDriver( IOService
* driver
)
1344 IOPMRequest
* request
;
1347 if (!driver
|| !initialized
|| !fInterestedDrivers
) {
1352 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1353 if (fInsertInterestSet
== NULL
) {
1354 fInsertInterestSet
= OSSet::withCapacity(4);
1356 if (fInsertInterestSet
) {
1357 fInsertInterestSet
->setObject(driver
);
1358 if (fRemoveInterestSet
) {
1359 fRemoveInterestSet
->removeObject(driver
);
1365 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1367 submitPMRequest( request
);
1371 // This return value cannot be trusted, but return a value
1372 // for those clients that care.
1374 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1375 return kIOPMDeviceUsable
;
1378 //*********************************************************************************
1379 // [public] deRegisterInterestedDriver
1380 //*********************************************************************************
1383 IOService::deRegisterInterestedDriver( IOService
* driver
)
1385 IOPMinformee
* item
;
1386 IOPMRequest
* request
;
1390 return kIOReturnBadArgument
;
1392 if (!initialized
|| !fInterestedDrivers
) {
1393 return IOPMNotPowerManaged
;
1397 if (fInsertInterestSet
) {
1398 fInsertInterestSet
->removeObject(driver
);
1401 item
= fInterestedDrivers
->findItem(driver
);
1404 return kIOReturnNotFound
;
1407 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1408 if (fRemoveInterestSet
== NULL
) {
1409 fRemoveInterestSet
= OSSet::withCapacity(4);
1411 if (fRemoveInterestSet
) {
1412 fRemoveInterestSet
->setObject(driver
);
1414 item
->active
= false;
1415 waitForPMDriverCall( driver
);
1421 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1423 submitPMRequest( request
);
1430 //*********************************************************************************
1431 // [private] handleInterestChanged
1433 // Handle interest added or removed.
1434 //*********************************************************************************
1437 IOService::handleInterestChanged( IOPMRequest
* request
)
1440 IOPMinformee
* informee
;
1441 IOPMinformeeList
* list
= fInterestedDrivers
;
1445 if (fInsertInterestSet
) {
1446 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject())) {
1447 if (list
->findItem(driver
) == NULL
) {
1448 list
->appendNewInformee(driver
);
1450 fInsertInterestSet
->removeObject(driver
);
1452 fInsertInterestSet
->release();
1453 fInsertInterestSet
= NULL
;
1456 if (fRemoveInterestSet
) {
1457 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject())) {
1458 informee
= list
->findItem(driver
);
1460 // Clean-up async interest acknowledgement
1461 if (fHeadNotePendingAcks
&& informee
->timer
) {
1462 informee
->timer
= 0;
1463 fHeadNotePendingAcks
--;
1465 list
->removeFromList(driver
);
1467 fRemoveInterestSet
->removeObject(driver
);
1469 fRemoveInterestSet
->release();
1470 fRemoveInterestSet
= NULL
;
1476 //*********************************************************************************
1477 // [public] acknowledgePowerChange
1479 // After we notified one of the interested drivers or a power-domain child
1480 // of an impending change in power, it has called to say it is now
1481 // prepared for the change. If this object is the last to
1482 // acknowledge this change, we take whatever action we have been waiting
1484 // That may include acknowledging to our parent. In this case, we do it
1485 // last of all to insure that this doesn't cause the parent to call us some-
1486 // where else and alter data we are relying on here (like the very existance
1487 // of a "current change note".)
1488 //*********************************************************************************
1491 IOService::acknowledgePowerChange( IOService
* whichObject
)
1493 IOPMRequest
* request
;
1496 return IOPMNotYetInitialized
;
1499 return kIOReturnBadArgument
;
1502 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1504 return kIOReturnNoMemory
;
1507 whichObject
->retain();
1508 request
->fArg0
= whichObject
;
1510 submitPMRequest( request
);
1514 //*********************************************************************************
1515 // [private] handleAcknowledgePowerChange
1516 //*********************************************************************************
1519 IOService::handleAcknowledgePowerChange( IOPMRequest
* request
)
1521 IOPMinformee
* informee
;
1522 IOPMPowerStateIndex childPower
= kIOPMUnknown
;
1523 IOService
* theChild
;
1524 IOService
* whichObject
;
1525 bool all_acked
= false;
1527 PM_ASSERT_IN_GATE();
1528 whichObject
= (IOService
*) request
->fArg0
;
1529 assert(whichObject
);
1531 // one of our interested drivers?
1532 informee
= fInterestedDrivers
->findItem( whichObject
);
1533 if (informee
== NULL
) {
1534 if (!isChild(whichObject
, gIOPowerPlane
)) {
1535 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1538 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1541 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1544 if (fHeadNotePendingAcks
!= 0) {
1545 assert(fPowerStates
!= NULL
);
1547 // yes, make sure we're expecting acks
1548 if (informee
!= NULL
) {
1549 // it's an interested driver
1550 // make sure we're expecting this ack
1551 if (informee
->timer
!= 0) {
1552 if (informee
->timer
> 0) {
1553 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1554 if (nsec
> gIOPMSetPowerStateLogNS
) {
1555 getPMRootDomain()->pmStatsRecordApplicationResponse(
1556 gIOPMStatsDriverPSChangeSlow
, informee
->whatObject
->getName(),
1557 fDriverCallReason
, NS_TO_MS(nsec
), informee
->whatObject
->getRegistryEntryID(),
1558 NULL
, fHeadNotePowerState
, true);
1563 informee
->timer
= 0;
1564 // that's one fewer to worry about
1565 fHeadNotePendingAcks
--;
1567 // this driver has already acked
1568 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1572 // make sure we're expecting this ack
1573 if (((IOPowerConnection
*)whichObject
)->getAwaitingAck()) {
1574 // that's one fewer to worry about
1575 fHeadNotePendingAcks
--;
1576 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1577 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1579 childPower
= theChild
->currentPowerConsumption();
1580 theChild
->release();
1582 if (childPower
== kIOPMUnknown
) {
1583 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1585 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
) {
1586 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1592 if (fHeadNotePendingAcks
== 0) {
1593 // yes, stop the timer
1595 // and now we can continue
1597 getPMRootDomain()->reset_watchdog_timer(this, 0);
1600 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1605 whichObject
->release();
1611 //*********************************************************************************
1612 // [public] acknowledgeSetPowerState
1614 // After we instructed our controlling driver to change power states,
1615 // it has called to say it has finished doing so.
1616 // We continue to process the power state change.
1617 //*********************************************************************************
1620 IOService::acknowledgeSetPowerState( void )
1622 IOPMRequest
* request
;
1625 return IOPMNotYetInitialized
;
1628 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1630 return kIOReturnNoMemory
;
1633 submitPMRequest( request
);
1634 return kIOReturnSuccess
;
1637 //*********************************************************************************
1638 // [private] adjustPowerState
1639 //*********************************************************************************
1642 IOService::adjustPowerState( IOPMPowerStateIndex clamp
)
1644 PM_ASSERT_IN_GATE();
1645 computeDesiredState(clamp
, false);
1646 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
)) {
1647 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1649 // Indicate that children desires must be ignored, and do not ask
1650 // apps for permission to drop power. This is used by root domain
1651 // for demand sleep.
1653 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
) {
1654 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1658 /* flags */ changeFlags
,
1659 /* power state */ fDesiredPowerState
,
1660 /* domain flags */ 0,
1661 /* connection */ NULL
,
1662 /* parent flags */ 0);
1666 //*********************************************************************************
1667 // [public] synchronizePowerTree
1668 //*********************************************************************************
1671 IOService::synchronizePowerTree(
1672 IOOptionBits options
,
1673 IOService
* notifyRoot
)
1675 IOPMRequest
* request_c
= NULL
;
1676 IOPMRequest
* request_s
;
1678 if (this != getPMRootDomain()) {
1679 return kIOReturnBadArgument
;
1682 return kIOPMNotYetInitialized
;
1685 OUR_PMLog(kPMLogCSynchronizePowerTree
, options
, (notifyRoot
!= NULL
));
1690 // Cancels don't need to be synchronized.
1691 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1693 submitPMRequest(nr
);
1696 // For display wrangler or any other delay-eligible (dark wake clamped)
1697 // drivers attached to root domain in the power plane.
1698 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1700 submitPMRequest(nr
);
1704 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1706 goto error_no_memory
;
1709 if (options
& kIOPMSyncCancelPowerDown
) {
1710 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1713 request_c
->attachNextRequest( request_s
);
1714 submitPMRequest(request_c
);
1717 request_s
->fArg0
= (void *)(uintptr_t) options
;
1718 submitPMRequest(request_s
);
1720 return kIOReturnSuccess
;
1724 releasePMRequest(request_c
);
1727 releasePMRequest(request_s
);
1729 return kIOReturnNoMemory
;
1732 //*********************************************************************************
1733 // [private] handleSynchronizePowerTree
1734 //*********************************************************************************
1737 IOService::handleSynchronizePowerTree( IOPMRequest
* request
)
1739 PM_ASSERT_IN_GATE();
1740 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1741 (fCurrentPowerState
== fHighestPowerState
)) {
1742 IOPMPowerChangeFlags options
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg0
;
1745 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1746 (options
& kIOPMSyncNoChildNotify
),
1747 /* power state */ fCurrentPowerState
,
1748 /* domain flags */ 0,
1749 /* connection */ NULL
,
1750 /* parent flags */ 0);
1755 //*********************************************************************************
1756 // [deprecated] powerDomainWillChangeTo
1758 // Called by the power-hierarchy parent notifying of a new power state
1759 // in the power domain.
1760 // We enqueue a parent power-change to our queue of power changes.
1761 // This may or may not cause us to change power, depending on what
1762 // kind of change is occuring in the domain.
1763 //*********************************************************************************
1766 IOService::powerDomainWillChangeTo(
1767 IOPMPowerFlags newPowerFlags
,
1768 IOPowerConnection
* whichParent
)
1771 return kIOReturnUnsupported
;
1773 #endif /* !__LP64__ */
1775 //*********************************************************************************
1776 // [private] handlePowerDomainWillChangeTo
1777 //*********************************************************************************
1780 IOService::handlePowerDomainWillChangeTo( IOPMRequest
* request
)
1782 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1783 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1784 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1785 IOPMPowerChangeFlags myChangeFlags
;
1788 IOPowerConnection
* connection
;
1789 IOPMPowerStateIndex maxPowerState
;
1790 IOPMPowerFlags combinedPowerFlags
;
1791 IOReturn result
= IOPMAckImplied
;
1793 PM_ASSERT_IN_GATE();
1794 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1796 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck()) {
1797 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1801 // Combine parents' output power flags.
1803 combinedPowerFlags
= 0;
1805 iter
= getParentIterator(gIOPowerPlane
);
1807 while ((next
= iter
->getNextObject())) {
1808 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
1809 if (connection
== whichParent
) {
1810 combinedPowerFlags
|= parentPowerFlags
;
1812 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1819 // If our initial change has yet to occur, then defer the power change
1820 // until after the power domain has completed its power transition.
1822 if (fControllingDriver
&& !fInitialPowerChange
) {
1823 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1824 combinedPowerFlags
);
1826 if (parentChangeFlags
& kIOPMDomainPowerDrop
) {
1827 // fMaxPowerState set a limit on self-initiated power changes.
1828 // Update it before a parent power drop.
1829 fMaxPowerState
= maxPowerState
;
1832 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1833 // to avoid propagating the root change flags if any service must
1834 // change power state due to root's will-change notification.
1835 // Root does not change power state for kIOPMSynchronize.
1837 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1838 (parentChangeFlags
& kIOPMSynchronize
);
1840 result
= startPowerChange(
1841 /* flags */ myChangeFlags
,
1842 /* power state */ maxPowerState
,
1843 /* domain flags */ combinedPowerFlags
,
1844 /* connection */ whichParent
,
1845 /* parent flags */ parentPowerFlags
);
1848 // If parent is dropping power, immediately update the parent's
1849 // capability flags. Any future merging of parent(s) combined
1850 // power flags should account for this power drop.
1852 if (parentChangeFlags
& kIOPMDomainPowerDrop
) {
1853 setParentInfo(parentPowerFlags
, whichParent
, true);
1856 // Parent is expecting an ACK from us. If we did not embark on a state
1857 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1858 // still required to issue an ACK to our parent.
1860 if (IOPMAckImplied
== result
) {
1862 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1865 parent
->acknowledgePowerChange( whichParent
);
1871 // Drop the retain from notifyChild().
1873 whichParent
->release();
1878 //*********************************************************************************
1879 // [deprecated] powerDomainDidChangeTo
1881 // Called by the power-hierarchy parent after the power state of the power domain
1882 // has settled at a new level.
1883 // We enqueue a parent power-change to our queue of power changes.
1884 // This may or may not cause us to change power, depending on what
1885 // kind of change is occuring in the domain.
1886 //*********************************************************************************
1889 IOService::powerDomainDidChangeTo(
1890 IOPMPowerFlags newPowerFlags
,
1891 IOPowerConnection
* whichParent
)
1894 return kIOReturnUnsupported
;
1896 #endif /* !__LP64__ */
1898 //*********************************************************************************
1899 // [private] handlePowerDomainDidChangeTo
1900 //*********************************************************************************
1903 IOService::handlePowerDomainDidChangeTo( IOPMRequest
* request
)
1905 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1906 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1907 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1908 IOPMPowerChangeFlags myChangeFlags
;
1909 IOPMPowerStateIndex maxPowerState
;
1910 IOPMPowerStateIndex initialDesire
= kPowerStateZero
;
1911 bool computeDesire
= false;
1912 bool desireChanged
= false;
1913 bool savedParentsKnowState
;
1914 IOReturn result
= IOPMAckImplied
;
1916 PM_ASSERT_IN_GATE();
1917 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1919 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck()) {
1920 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1924 savedParentsKnowState
= fParentsKnowState
;
1926 setParentInfo(parentPowerFlags
, whichParent
, true);
1928 if (fControllingDriver
) {
1929 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1930 fParentsCurrentPowerFlags
);
1932 if ((parentChangeFlags
& kIOPMDomainPowerDrop
) == 0) {
1933 // fMaxPowerState set a limit on self-initiated power changes.
1934 // Update it after a parent power rise.
1935 fMaxPowerState
= maxPowerState
;
1938 if (fInitialPowerChange
) {
1939 computeDesire
= true;
1940 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1941 fParentsCurrentPowerFlags
);
1942 } else if (parentChangeFlags
& kIOPMRootChangeUp
) {
1943 if (fAdvisoryTickleUsed
) {
1944 // On system wake, re-compute the desired power state since
1945 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1946 // which is an input to computeDesiredState(). This is not
1947 // necessary for a dark wake because powerChangeDone() will
1948 // handle the dark to full wake case, but it does no harm.
1950 desireChanged
= true;
1953 if (fResetPowerStateOnWake
) {
1954 // Query the driver for the desired power state on system wake.
1955 // Default implementation returns the lowest power state.
1957 IOPMPowerStateIndex wakePowerState
=
1958 fControllingDriver
->initialPowerStateForDomainState(
1959 kIOPMRootDomainState
| kIOPMPowerOn
);
1961 // fDesiredPowerState was adjusted before going to sleep
1962 // with fDeviceDesire at min.
1964 if (StateOrder(wakePowerState
) > StateOrder(fDesiredPowerState
)) {
1965 // Must schedule a power adjustment if we changed the
1966 // device desire. That will update the desired domain
1967 // power on the parent power connection and ping the
1968 // power parent if necessary.
1970 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1971 desireChanged
= true;
1976 if (computeDesire
|| desireChanged
) {
1977 computeDesiredState(initialDesire
, false);
1980 // Absorb and propagate parent's broadcast flags
1981 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1982 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1984 if (kIOPMAOTPower
& fPowerStates
[maxPowerState
].inputPowerFlags
) {
1985 IOLog("aotPS %s0x%qx[%ld]\n", getName(), getRegistryEntryID(), maxPowerState
);
1988 result
= startPowerChange(
1989 /* flags */ myChangeFlags
,
1990 /* power state */ maxPowerState
,
1991 /* domain flags */ fParentsCurrentPowerFlags
,
1992 /* connection */ whichParent
,
1993 /* parent flags */ 0);
1996 // Parent is expecting an ACK from us. If we did not embark on a state
1997 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1998 // still required to issue an ACK to our parent.
2000 if (IOPMAckImplied
== result
) {
2002 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
2005 parent
->acknowledgePowerChange( whichParent
);
2010 // If the parent registers its power driver late, then this is the
2011 // first opportunity to tell our parent about our desire. Or if the
2012 // child's desire changed during a parent change notify.
2014 if (fControllingDriver
&&
2015 ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
)) {
2016 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
2017 getName(), fParentsKnowState
);
2018 requestDomainPower( fDesiredPowerState
);
2022 // Drop the retain from notifyChild().
2024 whichParent
->release();
2028 //*********************************************************************************
2029 // [private] setParentInfo
2031 // Set our connection data for one specific parent, and then combine all the parent
2033 //*********************************************************************************
2036 IOService::setParentInfo(
2037 IOPMPowerFlags newPowerFlags
,
2038 IOPowerConnection
* whichParent
,
2043 IOPowerConnection
* conn
;
2045 PM_ASSERT_IN_GATE();
2047 // set our connection data
2048 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
2049 whichParent
->setParentKnowsState(knowsState
);
2051 // recompute our parent info
2052 fParentsCurrentPowerFlags
= 0;
2053 fParentsKnowState
= true;
2055 iter
= getParentIterator(gIOPowerPlane
);
2057 while ((next
= iter
->getNextObject())) {
2058 if ((conn
= OSDynamicCast(IOPowerConnection
, next
))) {
2059 fParentsKnowState
&= conn
->parentKnowsState();
2060 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
2067 //******************************************************************************
2068 // [private] trackSystemSleepPreventers
2069 //******************************************************************************
2072 IOService::trackSystemSleepPreventers(
2073 IOPMPowerStateIndex oldPowerState
,
2074 IOPMPowerStateIndex newPowerState
,
2075 IOPMPowerChangeFlags changeFlags __unused
)
2077 IOPMPowerFlags oldCapability
, newCapability
;
2079 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2080 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2081 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2082 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2084 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
) {
2087 if (oldCapability
== newCapability
) {
2091 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
) {
2092 bool enablePrevention
= ((oldCapability
& kIOPMPreventIdleSleep
) == 0);
2093 bool idleCancelAllowed
= getPMRootDomain()->updatePreventIdleSleepList(
2094 this, enablePrevention
);
2095 #if SUPPORT_IDLE_CANCEL
2096 if (idleCancelAllowed
&& enablePrevention
) {
2097 IOPMRequest
* cancelRequest
;
2099 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2100 if (cancelRequest
) {
2101 submitPMRequest( cancelRequest
);
2107 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
) {
2108 getPMRootDomain()->updatePreventSystemSleepList(this,
2109 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2113 //*********************************************************************************
2114 // [public] requestPowerDomainState
2116 // Called on a power parent when a child's power requirement changes.
2117 //*********************************************************************************
2120 IOService::requestPowerDomainState(
2121 IOPMPowerFlags childRequestPowerFlags
,
2122 IOPowerConnection
* childConnection
,
2123 unsigned long specification
)
2125 IOPMPowerStateIndex order
, powerState
;
2126 IOPMPowerFlags outputPowerFlags
;
2128 IOPMRequest
* subRequest
;
2129 bool adjustPower
= false;
2132 return IOPMNotYetInitialized
;
2135 if (gIOPMWorkLoop
->onThread() == false) {
2136 PM_LOG("%s::requestPowerDomainState\n", getName());
2137 return kIOReturnSuccess
;
2140 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2142 if (!isChild(childConnection
, gIOPowerPlane
)) {
2143 return kIOReturnNotAttached
;
2146 if (!fControllingDriver
|| !fNumberOfPowerStates
) {
2147 return kIOReturnNotReady
;
2150 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2153 // Remove flags from child request which we can't possibly supply
2154 childRequestPowerFlags
&= fMergedOutputPowerFlags
;
2156 // Merge in the power flags contributed by this power parent
2157 // at its current or impending power state.
2159 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2160 if (fMachineState
!= kIOPM_Finished
) {
2161 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
) {
2162 // Use the lower power state when dropping power.
2163 // Must be careful since a power drop can be cancelled
2164 // from the following states:
2165 // - kIOPM_OurChangeTellClientsPowerDown
2166 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2168 // The child must not wait for this parent to raise power
2169 // if the power drop was cancelled. The solution is to cancel
2170 // the power drop if possible, then schedule an adjustment to
2171 // re-evaluate the parent's power state.
2173 // Root domain is excluded to avoid idle sleep issues. And allow
2174 // root domain children to pop up when system is going to sleep.
2176 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2177 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)) {
2178 fDoNotPowerDown
= true; // cancel power drop
2179 adjustPower
= true;// schedule an adjustment
2180 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2181 getName(), fMachineState
, child
->getName());
2183 // Beyond cancellation point, report the impending state.
2185 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2187 } else if (IS_POWER_RISE
) {
2188 // When raising power, must report the output power flags from
2189 // child's perspective. A child power request may arrive while
2190 // parent is transitioning upwards. If a request arrives after
2191 // setParentInfo() has already recorded the output power flags
2192 // for the next power state, then using the power supplied by
2193 // fCurrentPowerState is incorrect, and might cause the child
2194 // to wait when it should not.
2196 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2199 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2201 // Map child's requested power flags to one of our power state.
2203 for (order
= 0; order
< fNumberOfPowerStates
; order
++) {
2204 powerState
= fPowerStates
[order
].stateOrderToIndex
;
2205 if ((fPowerStates
[powerState
].outputPowerFlags
& childRequestPowerFlags
)
2206 == childRequestPowerFlags
) {
2210 if (order
>= fNumberOfPowerStates
) {
2211 powerState
= kPowerStateZero
;
2214 // Conditions that warrants a power adjustment on this parent.
2215 // Adjust power will also propagate any changes to the child's
2216 // prevent idle/sleep flags towards the root domain.
2218 if (!childConnection
->childHasRequestedPower() ||
2219 (powerState
!= childConnection
->getDesiredDomainState())) {
2223 #if ENABLE_DEBUG_LOGS
2225 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2226 getName(), child
->getName(),
2227 !childConnection
->childHasRequestedPower(),
2228 (uint32_t) childConnection
->getDesiredDomainState(),
2229 (uint32_t) powerState
);
2233 // Record the child's desires on the connection.
2234 childConnection
->setChildHasRequestedPower();
2235 childConnection
->setDesiredDomainState( powerState
);
2237 // Schedule a request to re-evaluate all children desires and
2238 // adjust power state. Submit a request if one wasn't pending,
2239 // or if the current request is part of a call tree.
2241 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2242 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest())) {
2243 subRequest
= acquirePMRequest(
2244 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2246 submitPMRequest( subRequest
);
2247 fAdjustPowerScheduled
= true;
2251 return kIOReturnSuccess
;
2254 //*********************************************************************************
2255 // [public] temporaryPowerClampOn
2257 // A power domain wants to be clamped to max power until it has children which
2258 // will then determine the power domain state.
2260 // We enter the highest state until addPowerChild is called.
2261 //*********************************************************************************
2264 IOService::temporaryPowerClampOn( void )
2266 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2269 //*********************************************************************************
2270 // [public] makeUsable
2272 // Some client of our device is asking that we become usable. Although
2273 // this has not come from a subclassed device object, treat it exactly
2274 // as if it had. In this way, subsequent requests for lower power from
2275 // a subclassed device object will pre-empt this request.
2277 // We treat this as a subclass object request to switch to the
2278 // highest power state.
2279 //*********************************************************************************
2282 IOService::makeUsable( void )
2284 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2285 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2288 //*********************************************************************************
2289 // [public] currentCapability
2290 //*********************************************************************************
2293 IOService::currentCapability( void )
2296 return IOPMNotPowerManaged
;
2299 return fCurrentCapabilityFlags
;
2302 //*********************************************************************************
2303 // [public] changePowerStateTo
2305 // Called by our power-controlling driver to change power state. The new desired
2306 // power state is computed and compared against the current power state. If those
2307 // power states differ, then a power state change is initiated.
2308 //*********************************************************************************
2311 IOService::changePowerStateTo( unsigned long ordinal
)
2313 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2314 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2317 //*********************************************************************************
2318 // [protected] changePowerStateToPriv
2320 // Called by our driver subclass to change power state. The new desired power
2321 // state is computed and compared against the current power state. If those
2322 // power states differ, then a power state change is initiated.
2323 //*********************************************************************************
2326 IOService::changePowerStateToPriv( unsigned long ordinal
)
2328 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2329 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2332 //*********************************************************************************
2333 // [public] changePowerStateWithOverrideTo
2335 // Called by our driver subclass to change power state. The new desired power
2336 // state is computed and compared against the current power state. If those
2337 // power states differ, then a power state change is initiated.
2338 // Override enforced - Children and Driver desires are ignored.
2339 //*********************************************************************************
2342 IOService::changePowerStateWithOverrideTo( IOPMPowerStateIndex ordinal
,
2343 IOPMRequestTag tag
)
2345 IOPMRequest
* request
;
2348 return kIOPMNotYetInitialized
;
2351 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2353 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2355 return kIOReturnNoMemory
;
2358 gIOPMPowerClientDevice
->retain();
2359 request
->fTag
= tag
;
2360 request
->fArg0
= (void *) ordinal
;
2361 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2362 request
->fArg2
= NULL
;
2365 request
->installCompletionAction( action
, target
, param
);
2369 // Prevent needless downwards power transitions by clamping power
2370 // until the scheduled request is executed.
2372 // TODO: review fOverrideMaxPowerState
2374 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
)) {
2375 fTempClampPowerState
= StateMax(fTempClampPowerState
, ordinal
);
2377 request
->fArg2
= (void *)(uintptr_t) true;
2379 // Place a power state ceiling to prevent any transition to a
2380 // power state higher than fOverrideMaxPowerState.
2381 fOverrideMaxPowerState
= ordinal
;
2384 submitPMRequest( request
);
2388 //*********************************************************************************
2389 // Tagged form of changePowerStateTo()
2390 //*********************************************************************************
2393 IOService::changePowerStateWithTagTo( IOPMPowerStateIndex ordinal
, IOPMRequestTag tag
)
2395 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, tag
);
2396 return requestPowerState(gIOPMPowerClientDriver
, ordinal
, tag
);
2399 //*********************************************************************************
2400 // Tagged form of changePowerStateToPriv()
2401 //*********************************************************************************
2404 IOService::changePowerStateWithTagToPriv( unsigned long ordinal
, IOPMRequestTag tag
)
2406 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, tag
);
2407 return requestPowerState(gIOPMPowerClientDevice
, ordinal
, tag
);
2410 //*********************************************************************************
2411 // [public] changePowerStateForRootDomain
2413 // Adjust the root domain's power desire on the target
2414 //*********************************************************************************
2417 IOService::changePowerStateForRootDomain( IOPMPowerStateIndex ordinal
)
2419 OUR_PMLog(kPMLogChangeStateForRootDomain
, ordinal
, 0);
2420 return requestPowerState( gIOPMPowerClientRootDomain
, ordinal
);
2423 //*********************************************************************************
2424 // [public for PMRD] quiescePowerTree
2426 // For root domain to issue a request to quiesce the power tree.
2427 // Supplied callback invoked upon completion.
2428 //*********************************************************************************
2431 IOService::quiescePowerTree(
2432 void * target
, IOPMCompletionAction action
, void * param
)
2434 IOPMRequest
* request
;
2437 return kIOPMNotYetInitialized
;
2439 if (!target
|| !action
) {
2440 return kIOReturnBadArgument
;
2443 OUR_PMLog(kPMLogQuiescePowerTree
, 0, 0);
2445 // Target the root node instead of root domain. This is to avoid blocking
2446 // the quiesce request behind an existing root domain request in the work
2447 // queue. Root parent and root domain requests in the work queue must not
2448 // block the completion of the quiesce request.
2450 request
= acquirePMRequest(gIOPMRootNode
, kIOPMRequestTypeQuiescePowerTree
);
2452 return kIOReturnNoMemory
;
2455 request
->installCompletionAction(target
, action
, param
);
2457 // Submit through the normal request flow. This will make sure any request
2458 // already in the request queue will get pushed over to the work queue for
2459 // execution. Any request submitted after this request may not be serviced.
2461 submitPMRequest( request
);
2462 return kIOReturnSuccess
;
2465 //*********************************************************************************
2466 // [private] requestPowerState
2467 //*********************************************************************************
2470 IOService::requestPowerState(
2471 const OSSymbol
* client
,
2472 IOPMPowerStateIndex state
,
2473 IOPMRequestTag tag
)
2475 IOPMRequest
* request
;
2477 if (!client
|| (state
> UINT_MAX
)) {
2478 return kIOReturnBadArgument
;
2481 return kIOPMNotYetInitialized
;
2484 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2486 return kIOReturnNoMemory
;
2490 request
->fTag
= tag
;
2491 request
->fArg0
= (void *)(uintptr_t) state
;
2492 request
->fArg1
= (void *) client
;
2493 request
->fArg2
= NULL
;
2496 request
->installCompletionAction( action
, target
, param
);
2500 // Prevent needless downwards power transitions by clamping power
2501 // until the scheduled request is executed.
2503 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
)) {
2504 fTempClampPowerState
= StateMax(fTempClampPowerState
, state
);
2506 request
->fArg2
= (void *)(uintptr_t) true;
2509 submitPMRequest( request
);
2513 //*********************************************************************************
2514 // [private] handleRequestPowerState
2515 //*********************************************************************************
2518 IOService::handleRequestPowerState( IOPMRequest
* request
)
2520 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2521 IOPMPowerStateIndex state
= (IOPMPowerStateIndex
) request
->fArg0
;
2523 PM_ASSERT_IN_GATE();
2524 if (request
->fArg2
) {
2525 assert(fTempClampCount
!= 0);
2526 if (fTempClampCount
) {
2529 if (!fTempClampCount
) {
2530 fTempClampPowerState
= kPowerStateZero
;
2534 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
)) {
2535 state
= fHighestPowerState
;
2538 // The power suppression due to changePowerStateWithOverrideTo() expires
2539 // upon the next "device" power request - changePowerStateToPriv().
2541 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2542 (client
== gIOPMPowerClientDevice
)) {
2543 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2546 if ((state
== kPowerStateZero
) &&
2547 (client
!= gIOPMPowerClientDevice
) &&
2548 (client
!= gIOPMPowerClientDriver
) &&
2549 (client
!= gIOPMPowerClientChildProxy
)) {
2550 removePowerClient(client
);
2552 updatePowerClient(client
, state
);
2559 //*********************************************************************************
2560 // [private] Helper functions to update/remove power clients.
2561 //*********************************************************************************
2564 IOService::updatePowerClient( const OSSymbol
* client
, IOPMPowerStateIndex powerState
)
2566 IOPMPowerStateIndex oldPowerState
= kPowerStateZero
;
2568 if (powerState
> UINT_MAX
) {
2573 if (!fPowerClients
) {
2574 fPowerClients
= OSDictionary::withCapacity(4);
2576 if (fPowerClients
&& client
) {
2577 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2579 oldPowerState
= num
->unsigned32BitValue();
2580 num
->setValue(powerState
);
2582 num
= OSNumber::withNumber(powerState
, 32);
2584 fPowerClients
->setObject(client
, num
);
2589 PM_ACTION_CLIENT(actionUpdatePowerClient
, client
, oldPowerState
, powerState
);
2594 IOService::removePowerClient( const OSSymbol
* client
)
2596 if (fPowerClients
&& client
) {
2597 fPowerClients
->removeObject(client
);
2602 IOService::getPowerStateForClient( const OSSymbol
* client
)
2604 IOPMPowerStateIndex powerState
= kPowerStateZero
;
2606 if (fPowerClients
&& client
) {
2607 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2609 powerState
= num
->unsigned32BitValue();
2615 //*********************************************************************************
2616 // [protected] powerOverrideOnPriv
2617 //*********************************************************************************
2620 IOService::powerOverrideOnPriv( void )
2622 IOPMRequest
* request
;
2625 return IOPMNotYetInitialized
;
2628 if (gIOPMWorkLoop
->inGate()) {
2629 fDeviceOverrideEnabled
= true;
2633 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2635 return kIOReturnNoMemory
;
2638 submitPMRequest( request
);
2642 //*********************************************************************************
2643 // [protected] powerOverrideOffPriv
2644 //*********************************************************************************
2647 IOService::powerOverrideOffPriv( void )
2649 IOPMRequest
* request
;
2652 return IOPMNotYetInitialized
;
2655 if (gIOPMWorkLoop
->inGate()) {
2656 fDeviceOverrideEnabled
= false;
2660 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2662 return kIOReturnNoMemory
;
2665 submitPMRequest( request
);
2669 //*********************************************************************************
2670 // [private] handlePowerOverrideChanged
2671 //*********************************************************************************
2674 IOService::handlePowerOverrideChanged( IOPMRequest
* request
)
2676 PM_ASSERT_IN_GATE();
2677 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
) {
2678 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2679 fDeviceOverrideEnabled
= true;
2681 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2682 fDeviceOverrideEnabled
= false;
2688 //*********************************************************************************
2689 // [private] computeDesiredState
2690 //*********************************************************************************
2693 IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2697 IOPowerConnection
* connection
;
2698 IOPMPowerStateIndex desiredState
= kPowerStateZero
;
2699 IOPMPowerStateIndex newPowerState
= kPowerStateZero
;
2700 bool hasChildren
= false;
2702 // Desired power state is always 0 without a controlling driver.
2704 if (!fNumberOfPowerStates
) {
2705 fDesiredPowerState
= kPowerStateZero
;
2709 // Examine the children's desired power state.
2711 iter
= getChildIterator(gIOPowerPlane
);
2713 while ((next
= iter
->getNextObject())) {
2714 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
2715 if (connection
->getReadyFlag() == false) {
2716 PM_LOG3("[%s] %s: connection not ready\n",
2717 getName(), __FUNCTION__
);
2720 if (connection
->childHasRequestedPower()) {
2723 desiredState
= StateMax(connection
->getDesiredDomainState(), desiredState
);
2729 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2731 removePowerClient(gIOPMPowerClientChildren
);
2734 // Iterate through all power clients to determine the min power state.
2736 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2738 const OSSymbol
* client
;
2739 while ((client
= (const OSSymbol
*) iter
->getNextObject())) {
2740 // Ignore child and driver when override is in effect.
2741 if ((fDeviceOverrideEnabled
||
2742 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2743 ((client
== gIOPMPowerClientChildren
) ||
2744 (client
== gIOPMPowerClientDriver
))) {
2748 // Ignore child proxy when children are present.
2749 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
)) {
2753 // Advisory tickles are irrelevant unless system is in full wake
2754 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2755 !gIOPMAdvisoryTickleEnabled
) {
2759 desiredState
= getPowerStateForClient(client
);
2760 assert(desiredState
< fNumberOfPowerStates
);
2762 (uint32_t) desiredState
, client
->getCStringNoCopy());
2764 newPowerState
= StateMax(newPowerState
, desiredState
);
2766 if (client
== gIOPMPowerClientDevice
) {
2767 fDeviceDesire
= desiredState
;
2773 // Factor in the temporary power desires.
2775 newPowerState
= StateMax(newPowerState
, localClamp
);
2776 newPowerState
= StateMax(newPowerState
, fTempClampPowerState
);
2778 // Limit check against max power override.
2780 newPowerState
= StateMin(newPowerState
, fOverrideMaxPowerState
);
2782 // Limit check against number of power states.
2784 if (newPowerState
>= fNumberOfPowerStates
) {
2785 newPowerState
= fHighestPowerState
;
2788 if (getPMRootDomain()->isAOTMode()) {
2789 if ((kIOPMPreventIdleSleep
& fPowerStates
[newPowerState
].capabilityFlags
)
2790 && !(kIOPMPreventIdleSleep
& fPowerStates
[fDesiredPowerState
].capabilityFlags
)) {
2791 getPMRootDomain()->claimSystemWakeEvent(this, kIOPMWakeEventAOTExit
, getName(), NULL
);
2795 fDesiredPowerState
= newPowerState
;
2797 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2798 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2799 (uint32_t) fCurrentPowerState
, (uint32_t) newPowerState
);
2802 // Restart idle timer if possible when device desire has increased.
2803 // Or if an advisory desire exists.
2805 if (fIdleTimerPeriod
&& fIdleTimerStopped
) {
2809 // Invalidate cached tickle power state when desires change, and not
2810 // due to a tickle request. In case the driver has requested a lower
2811 // power state, but the tickle is caching a higher power state which
2812 // will drop future tickles until the cached value is lowered or in-
2813 // validated. The invalidation must occur before the power transition
2814 // to avoid dropping a necessary tickle.
2816 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2817 (fActivityTicklePowerState
!= kInvalidTicklePowerState
)) {
2818 IOLockLock(fActivityLock
);
2819 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2820 IOLockUnlock(fActivityLock
);
2825 //*********************************************************************************
2826 // [public] currentPowerConsumption
2828 //*********************************************************************************
2831 IOService::currentPowerConsumption( void )
2834 return kIOPMUnknown
;
2837 return fCurrentPowerConsumption
;
2840 //*********************************************************************************
2841 // [deprecated] getPMworkloop
2842 //*********************************************************************************
2846 IOService::getPMworkloop( void )
2848 return gIOPMWorkLoop
;
2854 //*********************************************************************************
2855 // Power Parent/Children Applier
2856 //*********************************************************************************
2859 applyToPowerChildren(
2860 IOService
* service
,
2861 IOServiceApplierFunction applier
,
2863 IOOptionBits options
)
2865 PM_ASSERT_IN_GATE();
2867 IORegistryEntry
* entry
;
2868 IORegistryIterator
* iter
;
2869 IOPowerConnection
* connection
;
2872 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2874 while ((entry
= iter
->getNextObject())) {
2875 // Get child of IOPowerConnection objects
2876 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
))) {
2877 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2879 (*applier
)(child
, context
);
2890 IOService
* service
,
2891 IOServiceApplierFunction applier
,
2893 IOOptionBits options
)
2895 PM_ASSERT_IN_GATE();
2897 IORegistryEntry
* entry
;
2898 IORegistryIterator
* iter
;
2899 IOPowerConnection
* connection
;
2902 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2903 options
| kIORegistryIterateParents
);
2905 while ((entry
= iter
->getNextObject())) {
2906 // Get child of IOPowerConnection objects
2907 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
))) {
2908 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2910 (*applier
)(parent
, context
);
2919 #endif /* NOT_YET */
2922 // MARK: Activity Tickle & Idle Timer
2925 IOService::setAdvisoryTickleEnable( bool enable
)
2927 gIOPMAdvisoryTickleEnabled
= enable
;
2930 //*********************************************************************************
2931 // [public] activityTickle
2933 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2934 // flag to be set, and the device state checked. If the device has been
2935 // powered down, it is powered up again.
2936 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2937 // should be intercepted by a subclass.
2938 //*********************************************************************************
2941 IOService::activityTickle( unsigned long type
, unsigned long stateNumber
)
2943 IOPMRequest
* request
;
2944 bool noPowerChange
= true;
2945 uint32_t tickleFlags
;
2948 return true; // no power change
2950 if ((type
== kIOPMSuperclassPolicy1
) && StateOrder(stateNumber
)) {
2951 IOLockLock(fActivityLock
);
2953 // Record device activity for the idle timer handler.
2955 fDeviceWasActive
= true;
2956 fActivityTickleCount
++;
2957 clock_get_uptime(&fDeviceActiveTimestamp
);
2959 PM_ACTION_TICKLE(actionActivityTickle
);
2961 // Record the last tickle power state.
2962 // This helps to filter out redundant tickles as
2963 // this function may be called from the data path.
2965 if ((fActivityTicklePowerState
== kInvalidTicklePowerState
)
2966 || StateOrder(fActivityTicklePowerState
) < StateOrder(stateNumber
)) {
2967 fActivityTicklePowerState
= stateNumber
;
2968 noPowerChange
= false;
2970 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2971 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2973 request
->fArg0
= (void *) stateNumber
;
2974 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2975 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2976 submitPMRequest(request
);
2980 IOLockUnlock(fActivityLock
);
2981 } else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2982 ((stateNumber
= fDeviceUsablePowerState
) != kPowerStateZero
)) {
2983 IOLockLock(fActivityLock
);
2985 fAdvisoryTickled
= true;
2987 if (fAdvisoryTicklePowerState
!= stateNumber
) {
2988 fAdvisoryTicklePowerState
= stateNumber
;
2989 noPowerChange
= false;
2991 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2992 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2994 request
->fArg0
= (void *) stateNumber
;
2995 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2996 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2997 submitPMRequest(request
);
3001 IOLockUnlock(fActivityLock
);
3004 // Returns false if the activityTickle might cause a transition to a
3005 // higher powered state, true otherwise.
3007 return noPowerChange
;
3010 //*********************************************************************************
3011 // [private] handleActivityTickle
3012 //*********************************************************************************
3015 IOService::handleActivityTickle( IOPMRequest
* request
)
3017 IOPMPowerStateIndex ticklePowerState
= (IOPMPowerStateIndex
) request
->fArg0
;
3018 IOPMPowerStateIndex tickleFlags
= (IOPMPowerStateIndex
) request
->fArg1
;
3019 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
3020 bool adjustPower
= false;
3022 PM_ASSERT_IN_GATE();
3023 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
)) {
3024 // Drivers that don't want power restored on wake will drop any
3025 // tickles that pre-dates the current system wake. The model is
3026 // that each wake is a fresh start, with power state depressed
3027 // until a new tickle or an explicit power up request from the
3028 // driver. It is possible for the PM work loop to enter the
3029 // system sleep path with tickle requests queued.
3034 if (tickleFlags
& kTickleTypeActivity
) {
3035 IOPMPowerStateIndex deviceDesireOrder
= StateOrder(fDeviceDesire
);
3036 IOPMPowerStateIndex idleTimerGeneration
= ticklePowerState
; // kTickleTypePowerDrop
3038 if (tickleFlags
& kTickleTypePowerRise
) {
3039 if ((StateOrder(ticklePowerState
) > deviceDesireOrder
) &&
3040 (ticklePowerState
< fNumberOfPowerStates
)) {
3041 fIdleTimerMinPowerState
= ticklePowerState
;
3042 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
3045 } else if ((deviceDesireOrder
> StateOrder(fIdleTimerMinPowerState
)) &&
3046 (idleTimerGeneration
== fIdleTimerGeneration
)) {
3047 // Power drop due to idle timer expiration.
3048 // Do not allow idle timer to reduce power below tickle power.
3049 // This prevents the idle timer from decreasing the device desire
3050 // to zero and cancelling the effect of a pre-sleep tickle when
3051 // system wakes up to doze state, while the device is unable to
3052 // raise its power state to satisfy the tickle.
3054 deviceDesireOrder
--;
3055 if (deviceDesireOrder
< fNumberOfPowerStates
) {
3056 ticklePowerState
= fPowerStates
[deviceDesireOrder
].stateOrderToIndex
;
3057 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
3061 } else { // advisory tickle
3062 if (tickleFlags
& kTickleTypePowerRise
) {
3063 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
3064 (ticklePowerState
< fNumberOfPowerStates
)) {
3065 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
3066 fHasAdvisoryDesire
= true;
3067 fAdvisoryTickleUsed
= true;
3070 IOLockLock(fActivityLock
);
3071 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3072 IOLockUnlock(fActivityLock
);
3074 } else if (fHasAdvisoryDesire
) {
3075 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
3076 fHasAdvisoryDesire
= false;
3086 //******************************************************************************
3087 // [public] setIdleTimerPeriod
3089 // A subclass policy-maker is using our standard idleness detection service.
3090 // Start the idle timer. Period is in seconds.
3091 //******************************************************************************
3094 IOService::setIdleTimerPeriod( unsigned long period
)
3097 return IOPMNotYetInitialized
;
3100 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
3102 if (period
> INT_MAX
) {
3103 return kIOReturnBadArgument
;
3106 IOPMRequest
* request
=
3107 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
3109 return kIOReturnNoMemory
;
3112 request
->fArg0
= (void *) period
;
3113 submitPMRequest( request
);
3115 return kIOReturnSuccess
;
3119 IOService::setIgnoreIdleTimer( bool ignore
)
3122 return IOPMNotYetInitialized
;
3125 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
3127 IOPMRequest
* request
=
3128 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
3130 return kIOReturnNoMemory
;
3133 request
->fArg0
= (void *) ignore
;
3134 submitPMRequest( request
);
3136 return kIOReturnSuccess
;
3139 //******************************************************************************
3140 // [public] nextIdleTimeout
3142 // Returns how many "seconds from now" the device should idle into its
3143 // next lowest power state.
3144 //******************************************************************************
3147 IOService::nextIdleTimeout(
3148 AbsoluteTime currentTime
,
3149 AbsoluteTime lastActivity
,
3150 unsigned int powerState
)
3157 // Calculate time difference using funky macro from clock.h.
3158 delta
= currentTime
;
3159 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
3161 // Figure it in seconds.
3162 absolutetime_to_nanoseconds(delta
, &delta_ns
);
3163 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
3165 // Be paranoid about delta somehow exceeding timer period.
3166 if (delta_secs
< (int) fIdleTimerPeriod
) {
3167 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3169 delay_secs
= (int) fIdleTimerPeriod
;
3172 return (SInt32
)delay_secs
;
3175 //*********************************************************************************
3176 // [public] start_PM_idle_timer
3177 //*********************************************************************************
3180 IOService::start_PM_idle_timer( void )
3182 static const int maxTimeout
= 100000;
3183 static const int minTimeout
= 1;
3184 AbsoluteTime uptime
, deadline
;
3188 if (!initialized
|| !fIdleTimerPeriod
||
3189 ((unsigned int) fCurrentPowerState
!= fCurrentPowerState
)) {
3193 IOLockLock(fActivityLock
);
3195 clock_get_uptime(&uptime
);
3197 // Subclasses may modify idle sleep algorithm
3198 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, (unsigned int) fCurrentPowerState
);
3200 // Check for out-of range responses
3201 if (idle_in
> maxTimeout
) {
3202 // use standard implementation
3203 idle_in
= IOService::nextIdleTimeout(uptime
,
3204 fDeviceActiveTimestamp
,
3205 (unsigned int) fCurrentPowerState
);
3206 } else if (idle_in
< minTimeout
) {
3207 idle_in
= fIdleTimerPeriod
;
3210 IOLockUnlock(fActivityLock
);
3212 fNextIdleTimerPeriod
= idle_in
;
3213 fIdleTimerStartTime
= uptime
;
3216 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3217 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3218 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3224 //*********************************************************************************
3225 // [private] restartIdleTimer
3226 //*********************************************************************************
3229 IOService::restartIdleTimer( void )
3231 if (fDeviceDesire
!= kPowerStateZero
) {
3232 fIdleTimerStopped
= false;
3233 fActivityTickleCount
= 0;
3234 start_PM_idle_timer();
3235 } else if (fHasAdvisoryDesire
) {
3236 fIdleTimerStopped
= false;
3237 start_PM_idle_timer();
3239 fIdleTimerStopped
= true;
3243 //*********************************************************************************
3244 // idle_timer_expired
3245 //*********************************************************************************
3249 thread_call_param_t arg0
, thread_call_param_t arg1
)
3251 IOService
* me
= (IOService
*) arg0
;
3253 if (gIOPMWorkLoop
) {
3254 gIOPMWorkLoop
->runAction(
3255 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3256 &IOService::idleTimerExpired
),
3263 //*********************************************************************************
3264 // [private] idleTimerExpired
3266 // The idle timer has expired. If there has been activity since the last
3267 // expiration, just restart the timer and return. If there has not been
3268 // activity, switch to the next lower power state and restart the timer.
3269 //*********************************************************************************
3272 IOService::idleTimerExpired( void )
3274 IOPMRequest
* request
;
3275 bool restartTimer
= true;
3276 uint32_t tickleFlags
;
3278 if (!initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3279 fLockedFlags
.PMStop
) {
3283 fIdleTimerStartTime
= 0;
3285 IOLockLock(fActivityLock
);
3287 // Check for device activity (tickles) over last timer period.
3289 if (fDeviceWasActive
) {
3290 // Device was active - do not drop power, restart timer.
3291 fDeviceWasActive
= false;
3292 } else if (!fIdleTimerIgnored
) {
3293 // No device activity - drop power state by one level.
3294 // Decrement the cached tickle power state when possible.
3295 // This value may be kInvalidTicklePowerState before activityTickle()
3296 // is called, but the power drop request must be issued regardless.
3298 if ((fActivityTicklePowerState
!= kInvalidTicklePowerState
) &&
3299 (fActivityTicklePowerState
!= kPowerStateZero
)) {
3300 fActivityTicklePowerState
--;
3303 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3304 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3306 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3307 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3308 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3309 submitPMRequest( request
);
3311 // Do not restart timer until after the tickle request has been
3314 restartTimer
= false;
3318 if (fAdvisoryTickled
) {
3319 fAdvisoryTickled
= false;
3320 } else if (fHasAdvisoryDesire
) {
3321 // Want new tickles to turn into pm request after we drop the lock
3322 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3324 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3325 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3327 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3328 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3329 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3330 submitPMRequest( request
);
3332 // Do not restart timer until after the tickle request has been
3335 restartTimer
= false;
3339 IOLockUnlock(fActivityLock
);
3342 start_PM_idle_timer();
3347 //*********************************************************************************
3348 // [deprecated] PM_idle_timer_expiration
3349 //*********************************************************************************
3352 IOService::PM_idle_timer_expiration( void )
3356 //*********************************************************************************
3357 // [deprecated] command_received
3358 //*********************************************************************************
3361 IOService::command_received( void *statePtr
, void *, void *, void * )
3364 #endif /* !__LP64__ */
3366 //*********************************************************************************
3367 // [public] setAggressiveness
3369 // Pass on the input parameters to all power domain children. All those which are
3370 // power domains will pass it on to their children, etc.
3371 //*********************************************************************************
3374 IOService::setAggressiveness( unsigned long type
, unsigned long newLevel
)
3376 return kIOReturnSuccess
;
3379 //*********************************************************************************
3380 // [public] getAggressiveness
3382 // Called by the user client.
3383 //*********************************************************************************
3386 IOService::getAggressiveness( unsigned long type
, unsigned long * currentLevel
)
3388 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3391 return kIOReturnNotReady
;
3394 return rootDomain
->getAggressiveness( type
, currentLevel
);
3397 //*********************************************************************************
3398 // [public] getPowerState
3400 //*********************************************************************************
3403 IOService::getPowerState( void )
3406 return kPowerStateZero
;
3409 return (UInt32
) fCurrentPowerState
;
3413 //*********************************************************************************
3414 // [deprecated] systemWake
3416 // Pass this to all power domain children. All those which are
3417 // power domains will pass it on to their children, etc.
3418 //*********************************************************************************
3421 IOService::systemWake( void )
3425 IOPowerConnection
* connection
;
3426 IOService
* theChild
;
3428 iter
= getChildIterator(gIOPowerPlane
);
3430 while ((next
= iter
->getNextObject())) {
3431 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
3432 if (connection
->getReadyFlag() == false) {
3433 PM_LOG3("[%s] %s: connection not ready\n",
3434 getName(), __FUNCTION__
);
3438 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3440 theChild
->systemWake();
3441 theChild
->release();
3448 if (fControllingDriver
!= NULL
) {
3449 if (fControllingDriver
->didYouWakeSystem()) {
3457 //*********************************************************************************
3458 // [deprecated] temperatureCriticalForZone
3459 //*********************************************************************************
3462 IOService::temperatureCriticalForZone( IOService
* whichZone
)
3464 IOService
* theParent
;
3467 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3469 if (inPlane(gIOPowerPlane
) && !IS_PM_ROOT
) {
3470 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3472 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3475 theParent
->temperatureCriticalForZone(whichZone
);
3476 theParent
->release();
3482 #endif /* !__LP64__ */
3485 // MARK: Power Change (Common)
3487 //*********************************************************************************
3488 // [private] startPowerChange
3490 // All power state changes starts here.
3491 //*********************************************************************************
3494 IOService::startPowerChange(
3495 IOPMPowerChangeFlags changeFlags
,
3496 IOPMPowerStateIndex powerState
,
3497 IOPMPowerFlags domainFlags
,
3498 IOPowerConnection
* parentConnection
,
3499 IOPMPowerFlags parentFlags
)
3501 uint32_t savedPMActionsState
;
3503 PM_ASSERT_IN_GATE();
3504 assert( fMachineState
== kIOPM_Finished
);
3505 assert( powerState
< fNumberOfPowerStates
);
3507 if (powerState
>= fNumberOfPowerStates
) {
3508 return IOPMAckImplied
;
3511 fIsPreChange
= true;
3512 savedPMActionsState
= fPMActions
.state
;
3513 PM_ACTION_CHANGE(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3515 // rdar://problem/55040032
3516 // Schedule a power adjustment after removing the power clamp
3517 // to inform our power parent(s) about our latest desired domain
3518 // power state. For a self-initiated change, let OurChangeStart()
3519 // automatically request parent power when necessary.
3520 if (!fAdjustPowerScheduled
&&
3521 ((changeFlags
& kIOPMSelfInitiated
) == 0) &&
3522 ((fPMActions
.state
& kPMActionsStatePowerClamped
) == 0) &&
3523 ((savedPMActionsState
& kPMActionsStatePowerClamped
) != 0)) {
3524 IOPMRequest
* request
= acquirePMRequest(this, kIOPMRequestTypeAdjustPowerState
);
3526 submitPMRequest(request
);
3527 fAdjustPowerScheduled
= true;
3531 if (changeFlags
& kIOPMExpireIdleTimer
) {
3532 // Root domain requested removal of tickle influence
3533 if (StateOrder(fDeviceDesire
) > StateOrder(powerState
)) {
3534 // Reset device desire down to the clamped power state
3535 updatePowerClient(gIOPMPowerClientDevice
, powerState
);
3536 computeDesiredState(kPowerStateZero
, true);
3538 // Invalidate tickle cache so the next tickle will issue a request
3539 IOLockLock(fActivityLock
);
3540 fDeviceWasActive
= false;
3541 fActivityTicklePowerState
= kInvalidTicklePowerState
;
3542 IOLockUnlock(fActivityLock
);
3544 fIdleTimerMinPowerState
= kPowerStateZero
;
3548 // Root domain's override handler may cancel the power change by
3549 // setting the kIOPMNotDone flag.
3551 if (changeFlags
& kIOPMNotDone
) {
3552 return IOPMAckImplied
;
3555 // Forks to either Driver or Parent initiated power change paths.
3557 fHeadNoteChangeFlags
= changeFlags
;
3558 fHeadNotePowerState
= powerState
;
3559 fHeadNotePowerArrayEntry
= &fPowerStates
[powerState
];
3560 fHeadNoteParentConnection
= NULL
;
3562 if (changeFlags
& kIOPMSelfInitiated
) {
3563 if (changeFlags
& kIOPMSynchronize
) {
3570 assert(changeFlags
& kIOPMParentInitiated
);
3571 fHeadNoteDomainFlags
= domainFlags
;
3572 fHeadNoteParentFlags
= parentFlags
;
3573 fHeadNoteParentConnection
= parentConnection
;
3574 return ParentChangeStart();
3578 //*********************************************************************************
3579 // [private] notifyInterestedDrivers
3580 //*********************************************************************************
3583 IOService::notifyInterestedDrivers( void )
3585 IOPMinformee
* informee
;
3586 IOPMinformeeList
* list
= fInterestedDrivers
;
3587 DriverCallParam
* param
;
3588 unsigned long numItems
;
3590 uint32_t skipCnt
= 0;
3592 PM_ASSERT_IN_GATE();
3593 assert( fDriverCallParamCount
== 0 );
3594 assert( fHeadNotePendingAcks
== 0 );
3596 fHeadNotePendingAcks
= 0;
3598 numItems
= list
->numberOfItems();
3599 if (!numItems
|| ((uint32_t) numItems
!= numItems
)) {
3600 goto done
; // interested drivers count out of range
3602 count
= (uint32_t) numItems
;
3604 // Allocate an array of interested drivers and their return values
3605 // for the callout thread. Everything else is still "owned" by the
3606 // PM work loop, which can run to process acknowledgePowerChange()
3609 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3610 if (count
> fDriverCallParamSlots
) {
3611 if (fDriverCallParamSlots
) {
3612 assert(fDriverCallParamPtr
);
3613 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3614 fDriverCallParamPtr
= NULL
;
3615 fDriverCallParamSlots
= 0;
3618 param
= IONew(DriverCallParam
, count
);
3620 goto done
; // no memory
3622 fDriverCallParamPtr
= (void *) param
;
3623 fDriverCallParamSlots
= count
;
3626 informee
= list
->firstInList();
3628 for (IOItemCount i
= 0; i
< count
; i
++) {
3629 if (fInitialSetPowerState
|| (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)) {
3630 // Skip notifying self, if 'kIOPMInitialDeviceState' is set and
3631 // this is the initial power state change
3632 if ((this == informee
->whatObject
) &&
3633 (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)) {
3638 informee
->timer
= -1;
3639 param
[i
].Target
= informee
;
3641 informee
= list
->nextInList( informee
);
3648 fDriverCallParamCount
= count
;
3649 fHeadNotePendingAcks
= count
;
3651 // Block state machine and wait for callout completion.
3652 assert(!fDriverCallBusy
);
3653 fDriverCallBusy
= true;
3654 thread_call_enter( fDriverCallEntry
);
3658 // Return false if there are no interested drivers or could not schedule
3659 // callout thread due to error.
3663 //*********************************************************************************
3664 // [private] notifyInterestedDriversDone
3665 //*********************************************************************************
3668 IOService::notifyInterestedDriversDone( void )
3670 IOPMinformee
* informee
;
3672 DriverCallParam
* param
;
3676 PM_ASSERT_IN_GATE();
3677 assert( fDriverCallBusy
== false );
3678 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3680 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3681 count
= fDriverCallParamCount
;
3683 if (param
&& count
) {
3684 for (IOItemCount i
= 0; i
< count
; i
++, param
++) {
3685 informee
= (IOPMinformee
*) param
->Target
;
3686 result
= param
->Result
;
3688 if ((result
== IOPMAckImplied
) || (result
< 0)) {
3689 // Interested driver return IOPMAckImplied.
3690 // If informee timer is zero, it must have de-registered
3691 // interest during the thread callout. That also drops
3692 // the pending ack count.
3694 if (fHeadNotePendingAcks
&& informee
->timer
) {
3695 fHeadNotePendingAcks
--;
3698 informee
->timer
= 0;
3699 } else if (informee
->timer
) {
3700 assert(informee
->timer
== -1);
3702 // Driver has not acked, and has returned a positive result.
3703 // Enforce a minimum permissible timeout value.
3704 // Make the min value large enough so timeout is less likely
3705 // to occur if a driver misinterpreted that the return value
3706 // should be in microsecond units. And make it large enough
3707 // to be noticeable if a driver neglects to ack.
3709 if (result
< kMinAckTimeoutTicks
) {
3710 result
= kMinAckTimeoutTicks
;
3713 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3714 if (result
> maxTimeout
) {
3715 maxTimeout
= result
;
3718 // else, child has already acked or driver has removed interest,
3719 // and head_note_pendingAcks decremented.
3720 // informee may have been removed from the interested drivers list,
3721 // thus the informee must be retained across the callout.
3723 informee
->release();
3726 fDriverCallParamCount
= 0;
3728 if (fHeadNotePendingAcks
) {
3729 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3731 getPMRootDomain()->reset_watchdog_timer(this, maxTimeout
/ USEC_PER_SEC
+ 1);
3735 MS_POP(); // pop the machine state passed to notifyAll()
3737 // If interest acks are outstanding, block the state machine until
3738 // fHeadNotePendingAcks drops to zero before notifying root domain.
3739 // Otherwise notify root domain directly.
3741 if (!fHeadNotePendingAcks
) {
3744 MS_PUSH(fMachineState
);
3745 fMachineState
= kIOPM_NotifyChildrenStart
;
3749 //*********************************************************************************
3750 // [private] notifyRootDomain
3751 //*********************************************************************************
3754 IOService::notifyRootDomain( void )
3756 assert( fDriverCallBusy
== false );
3758 // Only for root domain in the will-change phase.
3759 // On a power up, don't notify children right after the interested drivers.
3760 // Perform setPowerState() first, then notify the children.
3761 if (!IS_ROOT_DOMAIN
|| (fMachineState
!= kIOPM_OurChangeSetPowerState
)) {
3766 MS_PUSH(fMachineState
); // push notifyAll() machine state
3767 fMachineState
= kIOPM_DriverThreadCallDone
;
3769 // Call IOPMrootDomain::willNotifyPowerChildren() on a thread call
3770 // to avoid a deadlock.
3771 fDriverCallReason
= kRootDomainInformPreChange
;
3772 fDriverCallBusy
= true;
3773 thread_call_enter( fDriverCallEntry
);
3777 IOService::notifyRootDomainDone( void )
3779 assert( fDriverCallBusy
== false );
3780 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3782 MS_POP(); // pop notifyAll() machine state
3786 //*********************************************************************************
3787 // [private] notifyChildren
3788 //*********************************************************************************
3791 IOService::notifyChildren( void )
3795 IOPowerConnection
* connection
;
3796 OSArray
* children
= NULL
;
3797 IOPMrootDomain
* rootDomain
;
3798 bool delayNotify
= false;
3800 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3801 (IS_POWER_DROP
== fIsPreChange
) &&
3802 ((rootDomain
= getPMRootDomain()) == this)) {
3803 rootDomain
->tracePoint( IS_POWER_DROP
?
3804 kIOPMTracePointSleepPowerPlaneDrivers
:
3805 kIOPMTracePointWakePowerPlaneDrivers
);
3808 if (fStrictTreeOrder
) {
3809 children
= OSArray::withCapacity(8);
3812 // Sum child power consumption in notifyChild()
3813 fHeadNotePowerArrayEntry
->staticPower
= 0;
3815 iter
= getChildIterator(gIOPowerPlane
);
3817 while ((next
= iter
->getNextObject())) {
3818 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
3819 if (connection
->getReadyFlag() == false) {
3820 PM_LOG3("[%s] %s: connection not ready\n",
3821 getName(), __FUNCTION__
);
3825 // Mechanism to postpone the did-change notification to
3826 // certain power children to order those children last.
3827 // Cannot be used together with strict tree ordering.
3829 if (!fIsPreChange
&&
3830 connection
->delayChildNotification
&&
3831 getPMRootDomain()->shouldDelayChildNotification(this)) {
3833 children
= OSArray::withCapacity(8);
3839 children
->setObject( connection
);
3844 if (!delayNotify
&& children
) {
3845 children
->setObject( connection
);
3847 notifyChild( connection
);
3854 if (children
&& (children
->getCount() == 0)) {
3855 children
->release();
3859 assert(fNotifyChildArray
== NULL
);
3860 fNotifyChildArray
= children
;
3861 MS_PUSH(fMachineState
);
3864 // Block until all non-delayed children have acked their
3865 // notification. Then notify the remaining delayed child
3866 // in the array. This is used to hold off graphics child
3867 // notification while the rest of the system powers up.
3868 // If a hid tickle arrives during this time, the delayed
3869 // children are immediately notified and root domain will
3870 // not clamp power for dark wake.
3872 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3873 PM_LOG2("%s: %d children in delayed array\n",
3874 getName(), children
->getCount());
3876 // Child array created to support strict notification order.
3877 // Notify children in the array one at a time.
3879 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3884 //*********************************************************************************
3885 // [private] notifyChildrenOrdered
3886 //*********************************************************************************
3889 IOService::notifyChildrenOrdered( void )
3891 PM_ASSERT_IN_GATE();
3892 assert(fNotifyChildArray
);
3893 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3895 // Notify one child, wait for it to ack, then repeat for next child.
3896 // This is a workaround for some drivers with multiple instances at
3897 // the same branch in the power tree, but the driver is slow to power
3898 // up unless the tree ordering is observed. Problem observed only on
3899 // system wake, not on system sleep.
3901 // We have the ability to power off in reverse child index order.
3902 // That works nicely on some machines, but not on all HW configs.
3904 if (fNotifyChildArray
->getCount()) {
3905 IOPowerConnection
* connection
;
3906 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3907 notifyChild( connection
);
3908 fNotifyChildArray
->removeObject(0);
3910 fNotifyChildArray
->release();
3911 fNotifyChildArray
= NULL
;
3913 MS_POP(); // pushed by notifyChildren()
3917 //*********************************************************************************
3918 // [private] notifyChildrenDelayed
3919 //*********************************************************************************
3922 IOService::notifyChildrenDelayed( void )
3924 IOPowerConnection
* connection
;
3926 PM_ASSERT_IN_GATE();
3927 assert(fNotifyChildArray
);
3928 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3930 // Wait after all non-delayed children and interested drivers have ack'ed,
3931 // then notify all delayed children. If notify delay is canceled, child
3932 // acks may be outstanding with PM blocked on fHeadNotePendingAcks != 0.
3933 // But the handling for either case is identical.
3935 for (int i
= 0;; i
++) {
3936 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3941 notifyChild( connection
);
3944 PM_LOG2("%s: notified delayed children\n", getName());
3945 fNotifyChildArray
->release();
3946 fNotifyChildArray
= NULL
;
3948 MS_POP(); // pushed by notifyChildren()
3951 //*********************************************************************************
3952 // [private] notifyAll
3953 //*********************************************************************************
3956 IOService::notifyAll( uint32_t nextMS
)
3958 // Save the machine state to be restored by notifyInterestedDriversDone()
3960 PM_ASSERT_IN_GATE();
3962 fMachineState
= kIOPM_DriverThreadCallDone
;
3963 fDriverCallReason
= fIsPreChange
?
3964 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3966 if (!notifyInterestedDrivers()) {
3967 notifyInterestedDriversDone();
3970 return IOPMWillAckLater
;
3973 //*********************************************************************************
3974 // [private, static] pmDriverCallout
3976 // Thread call context
3977 //*********************************************************************************
3980 IOService::actionDriverCalloutDone(
3982 void * arg0
, void * arg1
,
3983 void * arg2
, void * arg3
)
3985 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3987 assert( fDriverCallBusy
);
3988 fDriverCallBusy
= false;
3990 assert(gIOPMWorkQueue
);
3991 gIOPMWorkQueue
->signalWorkAvailable();
3993 return kIOReturnSuccess
;
3997 IOService::pmDriverCallout( IOService
* from
)
4000 switch (from
->fDriverCallReason
) {
4001 case kDriverCallSetPowerState
:
4002 from
->driverSetPowerState();
4005 case kDriverCallInformPreChange
:
4006 case kDriverCallInformPostChange
:
4007 from
->driverInformPowerChange();
4010 case kRootDomainInformPreChange
:
4011 getPMRootDomain()->willNotifyPowerChildren(from
->fHeadNotePowerState
);
4015 panic("IOService::pmDriverCallout bad machine state %x",
4016 from
->fDriverCallReason
);
4019 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
4021 /* arg0 */ (void *) from
->pwrMgt
);
4024 //*********************************************************************************
4025 // [private] driverSetPowerState
4027 // Thread call context
4028 //*********************************************************************************
4031 IOService::driverSetPowerState( void )
4033 IOPMPowerStateIndex powerState
;
4034 DriverCallParam
* param
;
4035 IOPMDriverCallEntry callEntry
;
4038 uint32_t oldPowerState
= getPowerState();
4040 assert( fDriverCallBusy
);
4041 assert( fDriverCallParamPtr
);
4042 assert( fDriverCallParamCount
== 1 );
4044 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4045 powerState
= fHeadNotePowerState
;
4047 if (assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetPowerState
)) {
4048 OUR_PMLogFuncStart(kPMLogProgramHardware
, (uintptr_t) this, powerState
);
4049 clock_get_uptime(&fDriverCallStartTime
);
4051 if (reserved
&& reserved
->uvars
&& reserved
->uvars
->userServer
) {
4052 result
= reserved
->uvars
->userServer
->serviceSetPowerState(fControllingDriver
, this, fHeadNotePowerArrayEntry
->capabilityFlags
, powerState
);
4054 result
= fControllingDriver
->setPowerState( powerState
, this );
4056 clock_get_uptime(&end
);
4057 OUR_PMLogFuncEnd(kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
4059 deassertPMDriverCall(&callEntry
);
4061 // Record the most recent max power state residency timings.
4062 // Use with DeviceActiveTimestamp to diagnose tickle issues.
4063 if (powerState
== fHighestPowerState
) {
4064 fMaxPowerStateEntryTime
= end
;
4065 } else if (oldPowerState
== fHighestPowerState
) {
4066 fMaxPowerStateExitTime
= end
;
4070 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
4071 fName
, OBFUSCATE(this), fCurrentPowerState
, powerState
, result
);
4075 if ((result
== IOPMAckImplied
) || (result
< 0)) {
4078 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
4079 absolutetime_to_nanoseconds(end
, &nsec
);
4080 if (nsec
> gIOPMSetPowerStateLogNS
) {
4081 getPMRootDomain()->pmStatsRecordApplicationResponse(
4082 gIOPMStatsDriverPSChangeSlow
,
4083 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
4088 result
= kIOPMAckImplied
;
4091 param
->Result
= result
;
4094 //*********************************************************************************
4095 // [private] driverInformPowerChange
4097 // Thread call context
4098 //*********************************************************************************
4101 IOService::driverInformPowerChange( void )
4103 IOPMinformee
* informee
;
4105 DriverCallParam
* param
;
4106 IOPMDriverCallEntry callEntry
;
4107 IOPMPowerFlags powerFlags
;
4108 IOPMPowerStateIndex powerState
;
4112 IOOptionBits callMethod
= (fDriverCallReason
== kDriverCallInformPreChange
) ?
4113 kIOPMDriverCallMethodWillChange
: kIOPMDriverCallMethodDidChange
;
4115 assert( fDriverCallBusy
);
4116 assert( fDriverCallParamPtr
);
4117 assert( fDriverCallParamCount
);
4119 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4120 count
= fDriverCallParamCount
;
4122 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4123 powerState
= fHeadNotePowerState
;
4125 for (IOItemCount i
= 0; i
< count
; i
++) {
4126 informee
= (IOPMinformee
*) param
->Target
;
4127 driver
= informee
->whatObject
;
4129 if (assertPMDriverCall(&callEntry
, callMethod
, informee
)) {
4130 if (fDriverCallReason
== kDriverCallInformPreChange
) {
4131 OUR_PMLogFuncStart(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
4132 clock_get_uptime(&informee
->startTime
);
4133 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
4134 clock_get_uptime(&end
);
4135 OUR_PMLogFuncEnd(kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
4137 OUR_PMLogFuncStart(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
4138 clock_get_uptime(&informee
->startTime
);
4139 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
4140 clock_get_uptime(&end
);
4141 OUR_PMLogFuncEnd(kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
4144 deassertPMDriverCall(&callEntry
);
4147 if ((result
== IOPMAckImplied
) || (result
< 0)) {
4150 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
4151 absolutetime_to_nanoseconds(end
, &nsec
);
4152 if (nsec
> gIOPMSetPowerStateLogNS
) {
4153 getPMRootDomain()->pmStatsRecordApplicationResponse(
4154 gIOPMStatsDriverPSChangeSlow
, driver
->getName(),
4155 fDriverCallReason
, NS_TO_MS(nsec
), driver
->getRegistryEntryID(),
4160 result
= kIOPMAckImplied
;
4163 param
->Result
= result
;
4168 //*********************************************************************************
4169 // [private] notifyChild
4171 // Notify a power domain child of an upcoming power change.
4172 // If the object acknowledges the current change, we return TRUE.
4173 //*********************************************************************************
4176 IOService::notifyChild( IOPowerConnection
* theNub
)
4178 IOReturn ret
= IOPMAckImplied
;
4179 unsigned long childPower
;
4180 IOService
* theChild
;
4181 IOPMRequest
* childRequest
;
4182 IOPMPowerChangeFlags requestArg2
;
4185 PM_ASSERT_IN_GATE();
4186 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
4191 // Unless the child handles the notification immediately and returns
4192 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4193 fHeadNotePendingAcks
++;
4194 theNub
->setAwaitingAck(true);
4196 requestArg2
= fHeadNoteChangeFlags
;
4197 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
)) {
4198 requestArg2
|= kIOPMDomainPowerDrop
;
4201 requestType
= fIsPreChange
?
4202 kIOPMRequestTypePowerDomainWillChange
:
4203 kIOPMRequestTypePowerDomainDidChange
;
4205 childRequest
= acquirePMRequest( theChild
, requestType
);
4208 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4209 childRequest
->fArg1
= (void *) theNub
;
4210 childRequest
->fArg2
= (void *)(uintptr_t) requestArg2
;
4211 theChild
->submitPMRequest( childRequest
);
4212 ret
= IOPMWillAckLater
;
4214 ret
= IOPMAckImplied
;
4215 fHeadNotePendingAcks
--;
4216 theNub
->setAwaitingAck(false);
4217 childPower
= theChild
->currentPowerConsumption();
4218 if (childPower
== kIOPMUnknown
) {
4219 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4221 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
) {
4222 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4227 theChild
->release();
4228 return IOPMAckImplied
== ret
;
4231 //*********************************************************************************
4232 // [private] notifyControllingDriver
4233 //*********************************************************************************
4236 IOService::notifyControllingDriver( void )
4238 DriverCallParam
* param
;
4240 PM_ASSERT_IN_GATE();
4241 assert( fDriverCallParamCount
== 0 );
4242 assert( fControllingDriver
);
4244 if (fInitialSetPowerState
) {
4245 fInitialSetPowerState
= false;
4246 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4248 // Driver specified flag to skip the inital setPowerState()
4249 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
) {
4254 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4256 param
= IONew(DriverCallParam
, 1);
4258 return false; // no memory
4260 fDriverCallParamPtr
= (void *) param
;
4261 fDriverCallParamSlots
= 1;
4264 param
->Target
= fControllingDriver
;
4265 fDriverCallParamCount
= 1;
4268 // Block state machine and wait for callout completion.
4269 assert(!fDriverCallBusy
);
4270 fDriverCallBusy
= true;
4271 thread_call_enter( fDriverCallEntry
);
4276 //*********************************************************************************
4277 // [private] notifyControllingDriverDone
4278 //*********************************************************************************
4281 IOService::notifyControllingDriverDone( void )
4283 DriverCallParam
* param
;
4286 PM_ASSERT_IN_GATE();
4287 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4289 assert( fDriverCallBusy
== false );
4290 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4292 if (param
&& fDriverCallParamCount
) {
4293 assert(fDriverCallParamCount
== 1);
4295 // the return value from setPowerState()
4296 result
= param
->Result
;
4298 if ((result
== IOPMAckImplied
) || (result
< 0)) {
4300 } else if (fDriverTimer
) {
4301 assert(fDriverTimer
== -1);
4303 // Driver has not acked, and has returned a positive result.
4304 // Enforce a minimum permissible timeout value.
4305 // Make the min value large enough so timeout is less likely
4306 // to occur if a driver misinterpreted that the return value
4307 // should be in microsecond units. And make it large enough
4308 // to be noticeable if a driver neglects to ack.
4310 if (result
< kMinAckTimeoutTicks
) {
4311 result
= kMinAckTimeoutTicks
;
4314 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4316 // else, child has already acked and driver_timer reset to 0.
4318 fDriverCallParamCount
= 0;
4321 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4323 getPMRootDomain()->reset_watchdog_timer(this, result
/ USEC_PER_SEC
+ 1);
4327 MS_POP(); // pushed by OurChangeSetPowerState()
4328 fIsPreChange
= false;
4331 //*********************************************************************************
4332 // [private] all_done
4334 // A power change is done.
4335 //*********************************************************************************
4338 IOService::all_done( void )
4340 IOPMPowerStateIndex prevPowerState
;
4341 const IOPMPSEntry
* powerStatePtr
;
4342 IOPMDriverCallEntry callEntry
;
4343 uint32_t prevMachineState
= fMachineState
;
4344 bool actionCalled
= false;
4347 fMachineState
= kIOPM_Finished
;
4349 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4350 ((prevMachineState
== kIOPM_Finished
) ||
4351 (prevMachineState
== kIOPM_SyncFinish
))) {
4352 // Sync operation and no power change occurred.
4353 // Do not inform driver and clients about this request completion,
4354 // except for the originator (root domain).
4356 PM_ACTION_CHANGE(actionPowerChangeDone
,
4357 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4359 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
) {
4360 powerChangeDone(fCurrentPowerState
);
4361 } else if (fAdvisoryTickleUsed
) {
4362 // Not root domain and advisory tickle target.
4363 // Re-adjust power after power tree sync at the 'did' pass
4364 // to recompute desire and adjust power state between dark
4365 // and full wake transitions. Root domain is responsible
4366 // for calling setAdvisoryTickleEnable() before starting
4367 // the kIOPMSynchronize power change.
4369 if (!fAdjustPowerScheduled
&&
4370 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
)) {
4371 IOPMRequest
* request
;
4372 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4374 submitPMRequest( request
);
4375 fAdjustPowerScheduled
= true;
4384 if (fHeadNoteChangeFlags
& kIOPMSelfInitiated
) {
4385 // power state changed
4386 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0) {
4387 trackSystemSleepPreventers(
4388 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4390 // we changed, tell our parent
4391 requestDomainPower(fHeadNotePowerState
);
4393 // yes, did power raise?
4394 if (StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
)) {
4395 // yes, inform clients and apps
4396 tellChangeUp(fHeadNotePowerState
);
4398 prevPowerState
= fCurrentPowerState
;
4400 fCurrentPowerState
= fHeadNotePowerState
;
4403 ts
= mach_absolute_time();
4404 STATEREPORT_SETSTATE(fReportBuf
, (uint16_t) fCurrentPowerState
, ts
);
4408 fPMVars
->myCurrentState
= fCurrentPowerState
;
4410 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4411 PM_ACTION_CHANGE(actionPowerChangeDone
,
4412 prevPowerState
, fHeadNoteChangeFlags
);
4413 actionCalled
= true;
4415 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4416 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4417 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
) {
4418 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4421 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
) {
4422 // Bump tickle generation count once the entire tree is down
4423 gIOPMTickleGeneration
++;
4426 // inform subclass policy-maker
4427 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4428 assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodChangeDone
, NULL
, kIOPMDriverCallNoInactiveCheck
)) {
4429 powerChangeDone(prevPowerState
);
4430 deassertPMDriverCall(&callEntry
);
4432 } else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
) {
4433 // changePowerStateWithOverrideTo() was cancelled
4434 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4438 // parent-initiated power change
4439 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
4440 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
) {
4441 ParentChangeRootChangeDown();
4444 // power state changed
4445 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0) {
4446 trackSystemSleepPreventers(
4447 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4450 if (StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
)) {
4451 // yes, inform clients and apps
4452 tellChangeUp(fHeadNotePowerState
);
4455 prevPowerState
= fCurrentPowerState
;
4456 fCurrentPowerState
= fHeadNotePowerState
;
4459 ts
= mach_absolute_time();
4460 STATEREPORT_SETSTATE(fReportBuf
, (uint16_t) fCurrentPowerState
, ts
);
4464 fPMVars
->myCurrentState
= fCurrentPowerState
;
4467 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4468 PM_ACTION_CHANGE(actionPowerChangeDone
,
4469 prevPowerState
, fHeadNoteChangeFlags
);
4470 actionCalled
= true;
4472 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4473 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4474 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
) {
4475 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4478 // inform subclass policy-maker
4479 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4480 assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodChangeDone
, NULL
, kIOPMDriverCallNoInactiveCheck
)) {
4481 powerChangeDone(prevPowerState
);
4482 deassertPMDriverCall(&callEntry
);
4487 // When power rises enough to satisfy the tickle's desire for more power,
4488 // the condition preventing idle-timer from dropping power is removed.
4490 if (StateOrder(fCurrentPowerState
) >= StateOrder(fIdleTimerMinPowerState
)) {
4491 fIdleTimerMinPowerState
= kPowerStateZero
;
4494 if (!actionCalled
) {
4495 PM_ACTION_CHANGE(actionPowerChangeDone
,
4496 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4501 // MARK: Power Change Initiated by Driver
4503 //*********************************************************************************
4504 // [private] OurChangeStart
4506 // Begin the processing of a power change initiated by us.
4507 //*********************************************************************************
4510 IOService::OurChangeStart( void )
4512 PM_ASSERT_IN_GATE();
4513 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4515 // fMaxPowerState is our maximum possible power state based on the current
4516 // power state of our parents. If we are trying to raise power beyond the
4517 // maximum, send an async request for more power to all parents.
4519 if (!IS_PM_ROOT
&& (StateOrder(fMaxPowerState
) < StateOrder(fHeadNotePowerState
))) {
4520 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4521 requestDomainPower(fHeadNotePowerState
);
4526 // Redundant power changes skips to the end of the state machine.
4528 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
)) {
4532 fInitialPowerChange
= false;
4534 // Change started, but may not complete...
4535 // Can be canceled (power drop) or deferred (power rise).
4537 PM_ACTION_CHANGE(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4539 // Two separate paths, depending if power is being raised or lowered.
4540 // Lowering power is subject to approval by clients of this service.
4542 if (IS_POWER_DROP
) {
4543 fDoNotPowerDown
= false;
4545 // Ask for persmission to drop power state
4546 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4547 fOutOfBandParameter
= kNotifyApps
;
4548 askChangeDown(fHeadNotePowerState
);
4550 // This service is raising power and parents are able to support the
4551 // new power state. However a parent may have already committed to
4552 // drop power, which might force this object to temporarily drop power.
4553 // This results in "oscillations" before the state machines converge
4554 // to a steady state.
4556 // To prevent this, a child must make a power reservation against all
4557 // parents before raising power. If the reservation fails, indicating
4558 // that the child will be unable to sustain the higher power state,
4559 // then the child will signal the parent to adjust power, and the child
4560 // will defer its power change.
4564 // Reserve parent power necessary to achieve fHeadNotePowerState.
4565 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4566 if (ret
!= kIOReturnSuccess
) {
4567 // Reservation failed, defer power rise.
4568 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4573 OurChangeTellCapabilityWillChange();
4577 //*********************************************************************************
4578 // [private] requestDomainPowerApplier
4580 // Call requestPowerDomainState() on all power parents.
4581 //*********************************************************************************
4583 struct IOPMRequestDomainPowerContext
{
4584 IOService
* child
; // the requesting child
4585 IOPMPowerFlags requestPowerFlags
;// power flags requested by child
4589 requestDomainPowerApplier(
4590 IORegistryEntry
* entry
,
4593 IOPowerConnection
* connection
;
4595 IOPMRequestDomainPowerContext
* context
;
4597 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == NULL
) {
4600 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4606 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4608 if (connection
->parentKnowsState() && connection
->getReadyFlag()) {
4609 parent
->requestPowerDomainState(
4610 context
->requestPowerFlags
,
4618 //*********************************************************************************
4619 // [private] requestDomainPower
4621 // Called by a power child to broadcast its desired power state to all parents.
4622 // If the child self-initiates a power change, it must call this function to
4623 // allow its parents to adjust power state.
4624 //*********************************************************************************
4627 IOService::requestDomainPower(
4628 IOPMPowerStateIndex ourPowerState
,
4629 IOOptionBits options
)
4631 IOPMPowerFlags requestPowerFlags
;
4632 IOPMPowerStateIndex maxPowerState
;
4633 IOPMRequestDomainPowerContext context
;
4635 PM_ASSERT_IN_GATE();
4636 assert(ourPowerState
< fNumberOfPowerStates
);
4637 if (ourPowerState
>= fNumberOfPowerStates
) {
4638 return kIOReturnBadArgument
;
4641 return kIOReturnSuccess
;
4644 // Fetch our input power flags for the requested power state.
4645 // Parent request is stated in terms of required power flags.
4647 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4649 // Disregard the "previous request" for power reservation.
4651 if (((options
& kReserveDomainPower
) == 0) &&
4652 (fPreviousRequestPowerFlags
== requestPowerFlags
)) {
4653 // skip if domain already knows our requirements
4656 fPreviousRequestPowerFlags
= requestPowerFlags
;
4658 // The results will be collected by fHeadNoteDomainTargetFlags
4659 context
.child
= this;
4660 context
.requestPowerFlags
= requestPowerFlags
;
4661 fHeadNoteDomainTargetFlags
= 0;
4662 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4664 if (options
& kReserveDomainPower
) {
4665 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4666 fHeadNoteDomainTargetFlags
);
4668 if (StateOrder(maxPowerState
) < StateOrder(ourPowerState
)) {
4669 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4671 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4672 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4673 return kIOReturnNoPower
;
4678 return kIOReturnSuccess
;
4681 //*********************************************************************************
4682 // [private] OurSyncStart
4683 //*********************************************************************************
4686 IOService::OurSyncStart( void )
4688 PM_ASSERT_IN_GATE();
4690 if (fInitialPowerChange
) {
4694 PM_ACTION_CHANGE(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4696 if (fHeadNoteChangeFlags
& kIOPMNotDone
) {
4701 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
) {
4702 fDoNotPowerDown
= false;
4704 // Ask for permission to drop power state
4705 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4706 fOutOfBandParameter
= kNotifyApps
;
4707 askChangeDown(fHeadNotePowerState
);
4709 // Only inform capability app and clients.
4710 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4714 //*********************************************************************************
4715 // [private] OurChangeTellClientsPowerDown
4717 // All applications and kernel clients have acknowledged our permission to drop
4718 // power. Here we notify them that we will lower the power and wait for acks.
4719 //*********************************************************************************
4722 IOService::OurChangeTellClientsPowerDown( void )
4724 if (!IS_ROOT_DOMAIN
) {
4725 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4727 fMachineState
= kIOPM_OurChangeTellUserPMPolicyPowerDown
;
4729 tellChangeDown1(fHeadNotePowerState
);
4732 //*********************************************************************************
4733 // [private] OurChangeTellUserPMPolicyPowerDown
4735 // All applications and kernel clients have acknowledged our permission to drop
4736 // power. Here we notify power management policy in user-space and wait for acks
4737 // one last time before we lower power
4738 //*********************************************************************************
4740 IOService::OurChangeTellUserPMPolicyPowerDown( void )
4742 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4743 fOutOfBandParameter
= kNotifyApps
;
4745 tellClientsWithResponse(kIOPMMessageLastCallBeforeSleep
);
4748 //*********************************************************************************
4749 // [private] OurChangeTellPriorityClientsPowerDown
4751 // All applications and kernel clients have acknowledged our intention to drop
4752 // power. Here we notify "priority" clients that we are lowering power.
4753 //*********************************************************************************
4756 IOService::OurChangeTellPriorityClientsPowerDown( void )
4758 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4759 tellChangeDown2(fHeadNotePowerState
);
4762 //*********************************************************************************
4763 // [private] OurChangeTellCapabilityWillChange
4765 // Extra stage for root domain to notify apps and drivers about the
4766 // system capability change when raising power state.
4767 //*********************************************************************************
4770 IOService::OurChangeTellCapabilityWillChange( void )
4772 if (!IS_ROOT_DOMAIN
) {
4773 return OurChangeNotifyInterestedDriversWillChange();
4776 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4779 //*********************************************************************************
4780 // [private] OurChangeNotifyInterestedDriversWillChange
4782 // All applications and kernel clients have acknowledged our power state change.
4783 // Here we notify interested drivers pre-change.
4784 //*********************************************************************************
4787 IOService::OurChangeNotifyInterestedDriversWillChange( void )
4789 IOPMrootDomain
* rootDomain
;
4790 if ((rootDomain
= getPMRootDomain()) == this) {
4791 if (IS_POWER_DROP
) {
4792 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4794 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4798 notifyAll( kIOPM_OurChangeSetPowerState
);
4801 //*********************************************************************************
4802 // [private] OurChangeSetPowerState
4804 // Instruct our controlling driver to program the hardware for the power state
4805 // change. Wait for async completions.
4806 //*********************************************************************************
4809 IOService::OurChangeSetPowerState( void )
4811 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4812 fMachineState
= kIOPM_DriverThreadCallDone
;
4813 fDriverCallReason
= kDriverCallSetPowerState
;
4815 if (notifyControllingDriver() == false) {
4816 notifyControllingDriverDone();
4820 //*********************************************************************************
4821 // [private] OurChangeWaitForPowerSettle
4823 // Our controlling driver has completed the power state change we initiated.
4824 // Wait for the driver specified settle time to expire.
4825 //*********************************************************************************
4828 IOService::OurChangeWaitForPowerSettle( void )
4830 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4834 //*********************************************************************************
4835 // [private] OurChangeNotifyInterestedDriversDidChange
4837 // Power has settled on a power change we initiated. Here we notify
4838 // all our interested drivers post-change.
4839 //*********************************************************************************
4842 IOService::OurChangeNotifyInterestedDriversDidChange( void )
4844 IOPMrootDomain
* rootDomain
;
4845 if ((rootDomain
= getPMRootDomain()) == this) {
4846 rootDomain
->tracePoint( IS_POWER_DROP
?
4847 kIOPMTracePointSleepDidChangeInterests
:
4848 kIOPMTracePointWakeDidChangeInterests
);
4851 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4854 //*********************************************************************************
4855 // [private] OurChangeTellCapabilityDidChange
4857 // For root domain to notify capability power-change.
4858 //*********************************************************************************
4861 IOService::OurChangeTellCapabilityDidChange( void )
4863 if (!IS_ROOT_DOMAIN
) {
4864 return OurChangeFinish();
4867 if (!IS_POWER_DROP
) {
4868 // Notify root domain immediately after notifying interested
4869 // drivers and power children.
4870 getPMRootDomain()->willTellSystemCapabilityDidChange();
4873 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4874 kIOPMTracePointSleepCapabilityClients
:
4875 kIOPMTracePointWakeCapabilityClients
);
4877 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4880 //*********************************************************************************
4881 // [private] OurChangeFinish
4883 // Done with this self-induced power state change.
4884 //*********************************************************************************
4887 IOService::OurChangeFinish( void )
4893 // MARK: Power Change Initiated by Parent
4895 //*********************************************************************************
4896 // [private] ParentChangeStart
4898 // Here we begin the processing of a power change initiated by our parent.
4899 //*********************************************************************************
4902 IOService::ParentChangeStart( void )
4904 PM_ASSERT_IN_GATE();
4905 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4907 // Root power domain has transitioned to its max power state
4908 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4909 (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) {
4910 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4911 if (fIdleTimerPeriod
&& fIdleTimerStopped
) {
4916 // Power domain is forcing us to lower power
4917 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
)) {
4918 PM_ACTION_CHANGE(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4920 // Tell apps and kernel clients
4921 fInitialPowerChange
= false;
4922 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4923 tellChangeDown1(fHeadNotePowerState
);
4924 return IOPMWillAckLater
;
4927 // Power domain is allowing us to raise power up to fHeadNotePowerState
4928 if (StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
)) {
4929 if (StateOrder(fDesiredPowerState
) > StateOrder(fCurrentPowerState
)) {
4930 if (StateOrder(fDesiredPowerState
) < StateOrder(fHeadNotePowerState
)) {
4931 // We power up, but not all the way
4932 fHeadNotePowerState
= fDesiredPowerState
;
4933 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4934 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4937 // We don't need to change
4938 fHeadNotePowerState
= fCurrentPowerState
;
4939 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4940 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4944 if (fHeadNoteChangeFlags
& kIOPMDomainDidChange
) {
4945 if (StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
)) {
4946 PM_ACTION_CHANGE(actionPowerChangeStart
,
4947 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4949 // Parent did change up - start our change up
4950 fInitialPowerChange
= false;
4951 ParentChangeTellCapabilityWillChange();
4952 return IOPMWillAckLater
;
4953 } else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
) {
4954 // No need to change power state, but broadcast change
4956 fMachineState
= kIOPM_SyncNotifyDidChange
;
4957 fDriverCallReason
= kDriverCallInformPreChange
;
4958 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4960 return IOPMWillAckLater
;
4964 // No power state change necessary
4965 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4968 return IOPMAckImplied
;
4971 //******************************************************************************
4972 // [private] ParentChangeRootChangeDown
4974 // Root domain has finished the transition to the system sleep state. And all
4975 // drivers in the power plane should have powered down. Cancel the idle timer,
4976 // and also reset the device desire for those drivers that don't want power
4977 // automatically restored on wake.
4978 //******************************************************************************
4981 IOService::ParentChangeRootChangeDown( void )
4983 // Always stop the idle timer before root power down
4984 if (fIdleTimerPeriod
&& !fIdleTimerStopped
) {
4985 fIdleTimerStopped
= true;
4986 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
)) {
4991 if (fResetPowerStateOnWake
) {
4992 // Reset device desire down to the lowest power state.
4993 // Advisory tickle desire is intentionally untouched since
4994 // it has no effect until system is promoted to full wake.
4996 if (fDeviceDesire
!= kPowerStateZero
) {
4997 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4998 computeDesiredState(kPowerStateZero
, true);
4999 requestDomainPower( fDesiredPowerState
);
5000 PM_LOG1("%s: tickle desire removed\n", fName
);
5003 // Invalidate tickle cache so the next tickle will issue a request
5004 IOLockLock(fActivityLock
);
5005 fDeviceWasActive
= false;
5006 fActivityTicklePowerState
= kInvalidTicklePowerState
;
5007 IOLockUnlock(fActivityLock
);
5009 fIdleTimerMinPowerState
= kPowerStateZero
;
5010 } else if (fAdvisoryTickleUsed
) {
5011 // Less aggressive mechanism to accelerate idle timer expiration
5012 // before system sleep. May not always allow the driver to wake
5013 // up from system sleep in the min power state.
5017 bool dropTickleDesire
= false;
5019 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
5020 (fIdleTimerMinPowerState
== kPowerStateZero
) &&
5021 (fDeviceDesire
!= kPowerStateZero
)) {
5022 IOLockLock(fActivityLock
);
5024 if (!fDeviceWasActive
) {
5025 // No tickles since the last idle timer expiration.
5026 // Safe to drop the device desire to zero.
5027 dropTickleDesire
= true;
5029 // Was tickled since the last idle timer expiration,
5030 // but not in the last minute.
5031 clock_get_uptime(&now
);
5032 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
5033 absolutetime_to_nanoseconds(now
, &nsec
);
5034 if (nsec
>= kNoTickleCancelWindow
) {
5035 dropTickleDesire
= true;
5039 if (dropTickleDesire
) {
5040 // Force the next tickle to raise power state
5041 fDeviceWasActive
= false;
5042 fActivityTicklePowerState
= kInvalidTicklePowerState
;
5045 IOLockUnlock(fActivityLock
);
5048 if (dropTickleDesire
) {
5049 // Advisory tickle desire is intentionally untouched since
5050 // it has no effect until system is promoted to full wake.
5052 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
5053 computeDesiredState(kPowerStateZero
, true);
5054 PM_LOG1("%s: tickle desire dropped\n", fName
);
5059 //*********************************************************************************
5060 // [private] ParentChangeTellPriorityClientsPowerDown
5062 // All applications and kernel clients have acknowledged our intention to drop
5063 // power. Here we notify "priority" clients that we are lowering power.
5064 //*********************************************************************************
5067 IOService::ParentChangeTellPriorityClientsPowerDown( void )
5069 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
5070 tellChangeDown2(fHeadNotePowerState
);
5073 //*********************************************************************************
5074 // [private] ParentChangeTellCapabilityWillChange
5076 // All (legacy) applications and kernel clients have acknowledged, extra stage for
5077 // root domain to notify apps and drivers about the system capability change.
5078 //*********************************************************************************
5081 IOService::ParentChangeTellCapabilityWillChange( void )
5083 if (!IS_ROOT_DOMAIN
) {
5084 return ParentChangeNotifyInterestedDriversWillChange();
5087 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
5090 //*********************************************************************************
5091 // [private] ParentChangeNotifyInterestedDriversWillChange
5093 // All applications and kernel clients have acknowledged our power state change.
5094 // Here we notify interested drivers pre-change.
5095 //*********************************************************************************
5098 IOService::ParentChangeNotifyInterestedDriversWillChange( void )
5100 notifyAll( kIOPM_ParentChangeSetPowerState
);
5103 //*********************************************************************************
5104 // [private] ParentChangeSetPowerState
5106 // Instruct our controlling driver to program the hardware for the power state
5107 // change. Wait for async completions.
5108 //*********************************************************************************
5111 IOService::ParentChangeSetPowerState( void )
5113 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
5114 fMachineState
= kIOPM_DriverThreadCallDone
;
5115 fDriverCallReason
= kDriverCallSetPowerState
;
5117 if (notifyControllingDriver() == false) {
5118 notifyControllingDriverDone();
5122 //*********************************************************************************
5123 // [private] ParentChangeWaitForPowerSettle
5125 // Our controlling driver has completed the power state change initiated by our
5126 // parent. Wait for the driver specified settle time to expire.
5127 //*********************************************************************************
5130 IOService::ParentChangeWaitForPowerSettle( void )
5132 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
5136 //*********************************************************************************
5137 // [private] ParentChangeNotifyInterestedDriversDidChange
5139 // Power has settled on a power change initiated by our parent. Here we notify
5140 // all our interested drivers post-change.
5141 //*********************************************************************************
5144 IOService::ParentChangeNotifyInterestedDriversDidChange( void )
5146 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
5149 //*********************************************************************************
5150 // [private] ParentChangeTellCapabilityDidChange
5152 // For root domain to notify capability power-change.
5153 //*********************************************************************************
5156 IOService::ParentChangeTellCapabilityDidChange( void )
5158 if (!IS_ROOT_DOMAIN
) {
5159 return ParentChangeAcknowledgePowerChange();
5162 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
5165 //*********************************************************************************
5166 // [private] ParentAcknowledgePowerChange
5168 // Acknowledge our power parent that our power change is done.
5169 //*********************************************************************************
5172 IOService::ParentChangeAcknowledgePowerChange( void )
5174 IORegistryEntry
* nub
;
5177 nub
= fHeadNoteParentConnection
;
5180 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
5182 parent
->acknowledgePowerChange((IOService
*)nub
);
5189 // MARK: Ack and Settle timers
5191 //*********************************************************************************
5192 // [private] settleTimerExpired
5194 // Power has settled after our last change. Notify interested parties that
5195 // there is a new power state.
5196 //*********************************************************************************
5199 IOService::settleTimerExpired( void )
5201 #if USE_SETTLE_TIMER
5203 gIOPMWorkQueue
->signalWorkAvailable();
5207 //*********************************************************************************
5208 // settle_timer_expired
5210 // Holds a retain while the settle timer callout is in flight.
5211 //*********************************************************************************
5213 #if USE_SETTLE_TIMER
5215 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5217 IOService
* me
= (IOService
*) arg0
;
5219 if (gIOPMWorkLoop
&& gIOPMWorkQueue
) {
5220 gIOPMWorkLoop
->runAction(
5221 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5228 //*********************************************************************************
5229 // [private] startSettleTimer
5231 // Calculate a power-settling delay in microseconds and start a timer.
5232 //*********************************************************************************
5235 IOService::startSettleTimer( void )
5237 #if USE_SETTLE_TIMER
5238 // This function is broken and serves no useful purpose since it never
5239 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5240 // yet it starts a delay timer. It appears no driver relies on a delay
5241 // from settleUpTime and settleDownTime in the power state table.
5243 AbsoluteTime deadline
;
5244 IOPMPowerStateIndex stateIndex
;
5245 IOPMPowerStateIndex currentOrder
, newOrder
, i
;
5246 uint32_t settleTime
= 0;
5249 PM_ASSERT_IN_GATE();
5251 currentOrder
= StateOrder(fCurrentPowerState
);
5252 newOrder
= StateOrder(fHeadNotePowerState
);
5257 if (newOrder
< currentOrder
) {
5258 while (i
> newOrder
) {
5259 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
5260 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleDownTime
;
5266 if (newOrder
> currentOrder
) {
5267 while (i
< newOrder
) {
5268 stateIndex
= fPowerStates
[i
+ 1].stateOrderToIndex
;
5269 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleUpTime
;
5276 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5277 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5285 //*********************************************************************************
5286 // [private] ackTimerTick
5288 // The acknowledgement timeout periodic timer has ticked.
5289 // If we are awaiting acks for a power change notification,
5290 // we decrement the timer word of each interested driver which hasn't acked.
5291 // If a timer word becomes zero, we pretend the driver aknowledged.
5292 // If we are waiting for the controlling driver to change the power
5293 // state of the hardware, we decrement its timer word, and if it becomes
5294 // zero, we pretend the driver acknowledged.
5296 // Returns true if the timer tick made it possible to advance to the next
5297 // machine state, false otherwise.
5298 //*********************************************************************************
5305 IOService::ack_timer_ticked( void )
5309 #endif /* !__LP64__ */
5312 IOService::ackTimerTick( void )
5314 IOPMinformee
* nextObject
;
5317 PM_ASSERT_IN_GATE();
5318 switch (fMachineState
) {
5319 case kIOPM_OurChangeWaitForPowerSettle
:
5320 case kIOPM_ParentChangeWaitForPowerSettle
:
5321 // are we waiting for controlling driver to acknowledge?
5322 if (fDriverTimer
> 0) {
5323 // yes, decrement timer tick
5325 if (fDriverTimer
== 0) {
5326 // controlling driver is tardy
5327 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5328 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
5329 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
5330 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5331 fName
, OBFUSCATE(this), fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5333 #if DEBUG || DEVELOPMENT || !defined(XNU_TARGET_OS_OSX)
5334 bool panic_allowed
= false;
5335 uint32_t setpowerstate_panic
= -1;
5336 PE_parse_boot_argn("setpowerstate_panic", &setpowerstate_panic
, sizeof(setpowerstate_panic
));
5337 panic_allowed
= setpowerstate_panic
!= 0;
5338 #ifdef CONFIG_XNUPOST
5339 uint64_t kernel_post_args
= 0;
5340 PE_parse_boot_argn("kernPOST", &kernel_post_args
, sizeof(kernel_post_args
));
5341 if (kernel_post_args
!= 0) {
5342 panic_allowed
= false;
5344 #endif /* CONFIG_XNUPOST */
5345 if (panic_allowed
) {
5346 // rdar://problem/48743340 - excluding AppleSEPManager from panic
5347 const char *whitelist
= "AppleSEPManager";
5348 if (strncmp(fName
, whitelist
, strlen(whitelist
))) {
5349 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5350 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5353 #ifdef CONFIG_XNUPOST
5354 if (kernel_post_args
!= 0) {
5355 PM_ERROR("setPowerState panic disabled by kernPOST boot-arg\n");
5357 #endif /* CONFIG_XNUPOST */
5358 if (setpowerstate_panic
!= 0) {
5359 PM_ERROR("setPowerState panic disabled by setpowerstate_panic boot-arg\n");
5362 #else /* !(DEBUG || DEVELOPMENT || !defined(XNU_TARGET_OS_OSX)) */
5363 if (gIOKitDebug
& kIOLogDebugPower
) {
5364 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5365 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5367 // panic for first party kexts
5368 const void *function_addr
= NULL
;
5369 OSKext
*kext
= NULL
;
5370 function_addr
= OSMemberFunctionCast(const void *, fControllingDriver
, &IOService::setPowerState
);
5371 kext
= OSKext::lookupKextWithAddress((vm_address_t
)function_addr
);
5373 #if __has_feature(ptrauth_calls)
5374 function_addr
= (const void*)VM_KERNEL_STRIP_PTR(function_addr
);
5375 #endif /* __has_feature(ptrauth_calls) */
5376 const char *bundleID
= kext
->getIdentifierCString();
5377 const char *apple_prefix
= "com.apple";
5378 const char *kernel_prefix
= "__kernel__";
5379 if (strncmp(bundleID
, apple_prefix
, strlen(apple_prefix
)) == 0 || strncmp(bundleID
, kernel_prefix
, strlen(kernel_prefix
)) == 0) {
5380 // first party client
5381 panic("%s::setPowerState(%p : %p, %lu -> %lu) timed out after %d ms",
5382 fName
, this, function_addr
, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5387 #endif /* !(DEBUG || DEVELOPMENT || !defined(XNU_TARGET_OS_OSX)) */
5388 // Unblock state machine and pretend driver has acked.
5390 getPMRootDomain()->reset_watchdog_timer(this, 0);
5392 // still waiting, set timer again
5398 case kIOPM_NotifyChildrenStart
:
5399 // are we waiting for interested parties to acknowledge?
5400 if (fHeadNotePendingAcks
!= 0) {
5401 // yes, go through the list of interested drivers
5402 nextObject
= fInterestedDrivers
->firstInList();
5403 // and check each one
5404 while (nextObject
!= NULL
) {
5405 if (nextObject
->timer
> 0) {
5406 nextObject
->timer
--;
5407 // this one should have acked by now
5408 if (nextObject
->timer
== 0) {
5409 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5410 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5411 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5412 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5413 nextObject
->whatObject
->getName(),
5414 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5415 OBFUSCATE(nextObject
->whatObject
), fName
, fCurrentPowerState
, fHeadNotePowerState
,
5418 // Pretend driver has acked.
5419 fHeadNotePendingAcks
--;
5422 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5425 // is that the last?
5426 if (fHeadNotePendingAcks
== 0) {
5427 // yes, we can continue
5429 getPMRootDomain()->reset_watchdog_timer(this, 0);
5431 // no, set timer again
5437 // TODO: aggreggate this
5438 case kIOPM_OurChangeTellClientsPowerDown
:
5439 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
5440 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5441 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5442 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5443 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5444 case kIOPM_SyncTellClientsPowerDown
:
5445 case kIOPM_SyncTellPriorityClientsPowerDown
:
5446 case kIOPM_SyncNotifyWillChange
:
5447 case kIOPM_TellCapabilityChangeDone
:
5448 // apps didn't respond in time
5449 cleanClientResponses(true);
5450 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5451 // tardy equates to approval
5456 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5457 getName(), fMachineState
);
5463 //*********************************************************************************
5464 // [private] start_watchdog_timer
5465 //*********************************************************************************
5467 IOService::start_watchdog_timer( void )
5472 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5476 IOLockLock(fWatchdogLock
);
5478 timeout
= getPMRootDomain()->getWatchdogTimeout();
5479 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5480 fWatchdogDeadline
= deadline
;
5481 start_watchdog_timer(deadline
);
5482 IOLockUnlock(fWatchdogLock
);
5486 IOService::start_watchdog_timer(uint64_t deadline
)
5488 IOLockAssert(fWatchdogLock
, kIOLockAssertOwned
);
5490 if (!thread_call_isactive(fWatchdogTimer
)) {
5491 thread_call_enter_delayed(fWatchdogTimer
, deadline
);
5495 //*********************************************************************************
5496 // [private] stop_watchdog_timer
5497 //*********************************************************************************
5500 IOService::stop_watchdog_timer( void )
5502 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5506 IOLockLock(fWatchdogLock
);
5508 thread_call_cancel(fWatchdogTimer
);
5509 fWatchdogDeadline
= 0;
5511 while (fBlockedArray
->getCount()) {
5512 IOService
*obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(0));
5514 PM_ERROR("WDOG:Object %s unexpected in blocked array\n", obj
->fName
);
5515 fBlockedArray
->removeObject(0);
5519 IOLockUnlock(fWatchdogLock
);
5522 //*********************************************************************************
5523 // reset_watchdog_timer
5524 //*********************************************************************************
5527 IOService::reset_watchdog_timer(IOService
*blockedObject
, int pendingResponseTimeout
)
5533 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5538 IOLockLock(fWatchdogLock
);
5539 if (!fWatchdogDeadline
) {
5543 i
= fBlockedArray
->getNextIndexOfObject(blockedObject
, 0);
5544 if (pendingResponseTimeout
== 0) {
5545 blockedObject
->fPendingResponseDeadline
= 0;
5546 if (i
== (unsigned int)-1) {
5549 fBlockedArray
->removeObject(i
);
5551 // Set deadline 2secs after the expected response timeout to allow
5552 // ack timer to handle the timeout.
5553 clock_interval_to_deadline(pendingResponseTimeout
+ 2, kSecondScale
, &deadline
);
5555 if (i
!= (unsigned int)-1) {
5556 PM_ERROR("WDOG:Object %s is already blocked for responses. Ignoring timeout %d\n",
5557 fName
, pendingResponseTimeout
);
5561 for (i
= 0; i
< fBlockedArray
->getCount(); i
++) {
5562 obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(i
));
5563 if (obj
&& (obj
->fPendingResponseDeadline
< deadline
)) {
5564 blockedObject
->fPendingResponseDeadline
= deadline
;
5565 fBlockedArray
->setObject(i
, blockedObject
);
5569 if (i
== fBlockedArray
->getCount()) {
5570 blockedObject
->fPendingResponseDeadline
= deadline
;
5571 fBlockedArray
->setObject(blockedObject
);
5575 obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(0));
5577 int timeout
= getPMRootDomain()->getWatchdogTimeout();
5578 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5580 deadline
= obj
->fPendingResponseDeadline
;
5583 thread_call_cancel(fWatchdogTimer
);
5584 start_watchdog_timer(deadline
);
5587 IOLockUnlock(fWatchdogLock
);
5591 //*********************************************************************************
5592 // [static] watchdog_timer_expired
5594 // Inside PM work loop's gate.
5595 //*********************************************************************************
5598 IOService::watchdog_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5600 IOService
* me
= (IOService
*) arg0
;
5603 gIOPMWatchDogThread
= current_thread();
5604 getPMRootDomain()->sleepWakeDebugTrig(true);
5605 gIOPMWatchDogThread
= NULL
;
5606 thread_call_free(me
->fWatchdogTimer
);
5607 me
->fWatchdogTimer
= NULL
;
5614 IOService::getIOPMWorkloop( void )
5616 return gIOPMWorkLoop
;
5621 //*********************************************************************************
5622 // [private] start_ack_timer
5623 //*********************************************************************************
5626 IOService::start_ack_timer( void )
5628 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5632 IOService::start_ack_timer( UInt32 interval
, UInt32 scale
)
5634 AbsoluteTime deadline
;
5637 clock_interval_to_deadline(interval
, scale
, &deadline
);
5640 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5646 //*********************************************************************************
5647 // [private] stop_ack_timer
5648 //*********************************************************************************
5651 IOService::stop_ack_timer( void )
5655 pending
= thread_call_cancel(fAckTimer
);
5661 //*********************************************************************************
5662 // [static] actionAckTimerExpired
5664 // Inside PM work loop's gate.
5665 //*********************************************************************************
5668 IOService::actionAckTimerExpired(
5670 void * arg0
, void * arg1
,
5671 void * arg2
, void * arg3
)
5673 IOService
* me
= (IOService
*) target
;
5676 // done will be true if the timer tick unblocks the machine state,
5677 // otherwise no need to signal the work loop.
5679 done
= me
->ackTimerTick();
5680 if (done
&& gIOPMWorkQueue
) {
5681 gIOPMWorkQueue
->signalWorkAvailable();
5684 return kIOReturnSuccess
;
5687 //*********************************************************************************
5688 // ack_timer_expired
5690 // Thread call function. Holds a retain while the callout is in flight.
5691 //*********************************************************************************
5694 IOService::ack_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5696 IOService
* me
= (IOService
*) arg0
;
5698 if (gIOPMWorkLoop
) {
5699 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5706 // MARK: Client Messaging
5708 //*********************************************************************************
5709 // [private] tellSystemCapabilityChange
5710 //*********************************************************************************
5713 IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5715 assert(IS_ROOT_DOMAIN
);
5718 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5719 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5722 // Notify app first on pre-change.
5723 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5725 // Notify kernel clients first on post-change.
5726 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5729 tellClientsWithResponse( fOutOfBandMessage
);
5732 //*********************************************************************************
5733 // [public] askChangeDown
5735 // Ask registered applications and kernel clients if we can change to a lower
5738 // Subclass can override this to send a different message type. Parameter is
5739 // the destination state number.
5741 // Return true if we don't have to wait for acknowledgements
5742 //*********************************************************************************
5745 IOService::askChangeDown( unsigned long stateNum
)
5747 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5750 //*********************************************************************************
5751 // [private] tellChangeDown1
5753 // Notify registered applications and kernel clients that we are definitely
5756 // Return true if we don't have to wait for acknowledgements
5757 //*********************************************************************************
5760 IOService::tellChangeDown1( unsigned long stateNum
)
5762 fOutOfBandParameter
= kNotifyApps
;
5763 return tellChangeDown(stateNum
);
5766 //*********************************************************************************
5767 // [private] tellChangeDown2
5769 // Notify priority clients that we are definitely dropping power.
5771 // Return true if we don't have to wait for acknowledgements
5772 //*********************************************************************************
5775 IOService::tellChangeDown2( unsigned long stateNum
)
5777 fOutOfBandParameter
= kNotifyPriority
;
5778 return tellChangeDown(stateNum
);
5781 //*********************************************************************************
5782 // [public] tellChangeDown
5784 // Notify registered applications and kernel clients that we are definitely
5787 // Subclass can override this to send a different message type. Parameter is
5788 // the destination state number.
5790 // Return true if we don't have to wait for acknowledgements
5791 //*********************************************************************************
5794 IOService::tellChangeDown( unsigned long stateNum
)
5796 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5799 //*********************************************************************************
5800 // cleanClientResponses
5802 //*********************************************************************************
5805 logAppTimeouts( OSObject
* object
, void * arg
)
5807 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5809 unsigned int clientIndex
;
5813 if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
5814 // Discover the 'counter' value or index assigned to this client
5815 // when it was notified, by searching for the array index of the
5816 // client in an array holding the cached interested clients.
5818 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5820 if ((clientIndex
!= (unsigned int) -1) &&
5821 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5822 (flag
!= kOSBooleanTrue
)) {
5823 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5827 pid
= clientID
->unsigned32BitValue();
5828 proc_name(pid
, name
, sizeof(name
));
5829 clientID
->release();
5832 PM_ERROR(context
->errorLog
, pid
, name
);
5834 // TODO: record message type if possible
5835 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5836 gIOPMStatsResponseTimedOut
,
5837 name
, 0, (30 * 1000), pid
, object
);
5843 IOService::cleanClientResponses( bool logErrors
)
5845 if (logErrors
&& fResponseArray
) {
5846 switch (fOutOfBandParameter
) {
5848 case kNotifyCapabilityChangeApps
:
5849 if (fNotifyClientArray
) {
5850 IOPMInterestContext context
;
5852 context
.responseArray
= fResponseArray
;
5853 context
.notifyClients
= fNotifyClientArray
;
5854 context
.serialNumber
= fSerialNumber
;
5855 context
.messageType
= kIOMessageCopyClientID
;
5856 context
.notifyType
= kNotifyApps
;
5857 context
.isPreChange
= fIsPreChange
;
5858 context
.enableTracing
= false;
5860 context
.maxTimeRequested
= 0;
5861 context
.stateNumber
= fHeadNotePowerState
;
5862 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5863 context
.changeFlags
= fHeadNoteChangeFlags
;
5864 context
.errorLog
= "PM notification timeout (pid %d, %s)\n";
5866 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5871 // kNotifyPriority, kNotifyCapabilityChangePriority
5872 // TODO: identify the priority client that has not acked
5873 PM_ERROR("PM priority notification timeout\n");
5874 if (gIOKitDebug
& kIOLogDebugPower
) {
5875 panic("PM priority notification timeout");
5881 if (IS_ROOT_DOMAIN
) {
5882 getPMRootDomain()->reset_watchdog_timer(this, 0);
5884 if (fResponseArray
) {
5885 fResponseArray
->release();
5886 fResponseArray
= NULL
;
5888 if (fNotifyClientArray
) {
5889 fNotifyClientArray
->release();
5890 fNotifyClientArray
= NULL
;
5894 //*********************************************************************************
5895 // [protected] tellClientsWithResponse
5897 // Notify registered applications and kernel clients that we are definitely
5900 // Return true if we don't have to wait for acknowledgements
5901 //*********************************************************************************
5904 IOService::tellClientsWithResponse( int messageType
)
5906 IOPMInterestContext context
;
5907 bool isRootDomain
= IS_ROOT_DOMAIN
;
5908 uint32_t maxTimeOut
= kMaxTimeRequested
;
5910 PM_ASSERT_IN_GATE();
5911 assert( fResponseArray
== NULL
);
5912 assert( fNotifyClientArray
== NULL
);
5914 RD_LOG("tellClientsWithResponse( %s, %s )\n", getIOMessageString(messageType
),
5915 getNotificationPhaseString(fOutOfBandParameter
));
5917 fResponseArray
= OSArray::withCapacity( 1 );
5918 if (!fResponseArray
) {
5922 fResponseArray
->setCapacityIncrement(8);
5923 if (++fSerialNumber
== 0) {
5927 context
.responseArray
= fResponseArray
;
5928 context
.notifyClients
= NULL
;
5929 context
.serialNumber
= fSerialNumber
;
5930 context
.messageType
= messageType
;
5931 context
.notifyType
= fOutOfBandParameter
;
5932 context
.skippedInDark
= 0;
5933 context
.notSkippedInDark
= 0;
5934 context
.isPreChange
= fIsPreChange
;
5935 context
.enableTracing
= false;
5937 context
.maxTimeRequested
= 0;
5938 context
.stateNumber
= fHeadNotePowerState
;
5939 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5940 context
.changeFlags
= fHeadNoteChangeFlags
;
5941 context
.messageFilter
= (isRootDomain
) ?
5942 OSMemberFunctionCast(
5944 (IOPMrootDomain
*)this,
5945 &IOPMrootDomain::systemMessageFilter
) : NULL
;
5947 switch (fOutOfBandParameter
) {
5949 applyToInterested( gIOAppPowerStateInterest
,
5950 pmTellAppWithResponse
, (void *) &context
);
5953 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5954 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
) &&
5955 (context
.messageType
!= kIOPMMessageLastCallBeforeSleep
)) {
5956 // Notify capability app for tellChangeDown1()
5957 // but not for askChangeDown().
5958 context
.notifyType
= kNotifyCapabilityChangeApps
;
5959 context
.messageType
= kIOMessageSystemCapabilityChange
;
5960 applyToInterested( gIOAppPowerStateInterest
,
5961 pmTellCapabilityAppWithResponse
, (void *) &context
);
5962 context
.notifyType
= fOutOfBandParameter
;
5963 context
.messageType
= messageType
;
5965 if (context
.messageType
== kIOMessageCanSystemSleep
) {
5966 maxTimeOut
= kCanSleepMaxTimeReq
;
5967 if (gCanSleepTimeout
) {
5968 maxTimeOut
= (gCanSleepTimeout
* us_per_s
);
5971 context
.maxTimeRequested
= maxTimeOut
;
5972 context
.enableTracing
= isRootDomain
;
5973 applyToInterested( gIOGeneralInterest
,
5974 pmTellClientWithResponse
, (void *) &context
);
5978 case kNotifyPriority
:
5979 context
.enableTracing
= isRootDomain
;
5980 applyToInterested( gIOPriorityPowerStateInterest
,
5981 pmTellClientWithResponse
, (void *) &context
);
5984 // Notify capability clients for tellChangeDown2().
5985 context
.notifyType
= kNotifyCapabilityChangePriority
;
5986 context
.messageType
= kIOMessageSystemCapabilityChange
;
5987 applyToInterested( gIOPriorityPowerStateInterest
,
5988 pmTellCapabilityClientWithResponse
, (void *) &context
);
5992 case kNotifyCapabilityChangeApps
:
5993 context
.enableTracing
= isRootDomain
;
5994 applyToInterested( gIOAppPowerStateInterest
,
5995 pmTellCapabilityAppWithResponse
, (void *) &context
);
5996 if (context
.messageType
== kIOMessageCanSystemSleep
) {
5997 maxTimeOut
= kCanSleepMaxTimeReq
;
5998 if (gCanSleepTimeout
) {
5999 maxTimeOut
= (gCanSleepTimeout
* us_per_s
);
6002 context
.maxTimeRequested
= maxTimeOut
;
6005 case kNotifyCapabilityChangePriority
:
6006 context
.enableTracing
= isRootDomain
;
6007 applyToInterested( gIOPriorityPowerStateInterest
,
6008 pmTellCapabilityClientWithResponse
, (void *) &context
);
6011 fNotifyClientArray
= context
.notifyClients
;
6013 if (context
.skippedInDark
) {
6014 IOLog("tellClientsWithResponse(%s, %s) %d of %d skipped in dark\n",
6015 getIOMessageString(messageType
), getNotificationPhaseString(fOutOfBandParameter
),
6016 context
.skippedInDark
, context
.skippedInDark
+ context
.notSkippedInDark
);
6019 // do we have to wait for somebody?
6020 if (!checkForDone()) {
6021 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
6022 if (context
.enableTracing
) {
6023 getPMRootDomain()->traceDetail(context
.messageType
, 0, context
.maxTimeRequested
/ 1000);
6024 getPMRootDomain()->reset_watchdog_timer(this, context
.maxTimeRequested
/ USEC_PER_SEC
+ 1);
6026 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
6031 // everybody responded
6032 if (fResponseArray
) {
6033 fResponseArray
->release();
6034 fResponseArray
= NULL
;
6036 if (fNotifyClientArray
) {
6037 fNotifyClientArray
->release();
6038 fNotifyClientArray
= NULL
;
6044 //*********************************************************************************
6045 // [static private] pmTellAppWithResponse
6047 // We send a message to an application, and we expect a response, so we compute a
6048 // cookie we can identify the response with.
6049 //*********************************************************************************
6052 IOService::pmTellAppWithResponse( OSObject
* object
, void * arg
)
6054 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6055 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6056 uint32_t msgIndex
, msgRef
, msgType
;
6057 OSNumber
*clientID
= NULL
;
6059 boolean_t proc_suspended
= FALSE
;
6060 OSObject
* waitForReply
= kOSBooleanTrue
;
6061 #if LOG_APP_RESPONSE_TIMES
6065 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
6069 if (context
->us
== getPMRootDomain()) {
6070 if ((clientID
= copyClientIDForNotification(object
, context
))) {
6071 uint32_t clientPID
= clientID
->unsigned32BitValue();
6072 clientID
->release();
6073 proc
= proc_find(clientPID
);
6076 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6077 if (proc_suspended
) {
6078 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
6079 } else if (getPMRootDomain()->isAOTMode() && get_task_suspended((task_t
) proc
->task
)) {
6080 proc_suspended
= true;
6081 context
->skippedInDark
++;
6084 if (proc_suspended
) {
6091 if (context
->messageFilter
&&
6092 !context
->messageFilter(context
->us
, object
, context
, NULL
, &waitForReply
)) {
6093 if (kIOLogDebugPower
& gIOKitDebug
) {
6094 logClientIDForNotification(object
, context
, "DROP App");
6098 context
->notSkippedInDark
++;
6100 // Create client array (for tracking purposes) only if the service
6101 // has app clients. Usually only root domain does.
6102 if (NULL
== context
->notifyClients
) {
6103 context
->notifyClients
= OSArray::withCapacity( 32 );
6106 msgType
= context
->messageType
;
6107 msgIndex
= context
->responseArray
->getCount();
6108 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6110 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6111 if (kIOLogDebugPower
& gIOKitDebug
) {
6112 logClientIDForNotification(object
, context
, "MESG App");
6115 if (waitForReply
== kOSBooleanTrue
) {
6117 clock_get_uptime(&now
);
6118 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6120 context
->responseArray
->setObject(msgIndex
, num
);
6123 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6126 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6127 if (kIOLogDebugPower
& gIOKitDebug
) {
6128 logClientIDForNotification(object
, context
, "App response ignored");
6132 if (context
->notifyClients
) {
6133 context
->notifyClients
->setObject(msgIndex
, object
);
6136 context
->us
->messageClient(msgType
, object
, (void *)(uintptr_t) msgRef
);
6139 //*********************************************************************************
6140 // [static private] pmTellClientWithResponse
6142 // We send a message to an in-kernel client, and we expect a response,
6143 // so we compute a cookie we can identify the response with.
6144 //*********************************************************************************
6147 IOService::pmTellClientWithResponse( OSObject
* object
, void * arg
)
6149 IOPowerStateChangeNotification notify
;
6150 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6151 OSObject
* replied
= kOSBooleanTrue
;
6152 _IOServiceInterestNotifier
* notifier
;
6153 uint32_t msgIndex
, msgRef
, msgType
;
6155 AbsoluteTime start
, end
;
6159 if (context
->messageFilter
&&
6160 !context
->messageFilter(context
->us
, object
, context
, NULL
, NULL
)) {
6161 getPMRootDomain()->traceFilteredNotification(object
);
6165 // Besides interest notifiers this applier function can also be invoked against
6166 // IOService clients of context->us, so notifier can be NULL. But for tracing
6167 // purposes the IOService clients can be ignored but each will still consume
6168 // an entry in the responseArray and also advance msgIndex.
6169 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6170 msgType
= context
->messageType
;
6171 msgIndex
= context
->responseArray
->getCount();
6172 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6173 enableTracing
= context
->enableTracing
&& (notifier
!= NULL
);
6175 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6176 if (gIOKitDebug
& kIOLogPower
) {
6177 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6178 if (OSDynamicCast(IOService
, object
)) {
6179 const char *who
= ((IOService
*) object
)->getName();
6180 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6181 } else if (notifier
) {
6182 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6186 if (NULL
== context
->notifyClients
) {
6187 context
->notifyClients
= OSArray::withCapacity(32);
6188 assert(context
->notifyClients
!= NULL
);
6191 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
6192 notify
.returnValue
= 0;
6193 notify
.stateNumber
= context
->stateNumber
;
6194 notify
.stateFlags
= context
->stateFlags
;
6196 clock_get_uptime(&start
);
6197 if (enableTracing
) {
6198 getPMRootDomain()->traceNotification(notifier
, true, start
, msgIndex
);
6201 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
6203 clock_get_uptime(&end
);
6204 if (enableTracing
) {
6205 getPMRootDomain()->traceNotification(notifier
, false, end
);
6208 if (kIOReturnSuccess
== retCode
) {
6209 if (0 == notify
.returnValue
) {
6210 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6211 context
->responseArray
->setObject(msgIndex
, replied
);
6213 replied
= kOSBooleanFalse
;
6214 if (notify
.returnValue
> context
->maxTimeRequested
) {
6215 if (notify
.returnValue
> kPriorityClientMaxWait
) {
6216 context
->maxTimeRequested
= kPriorityClientMaxWait
;
6217 PM_ERROR("%s: client %p returned %llu for %s\n",
6218 context
->us
->getName(),
6219 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6220 (uint64_t) notify
.returnValue
,
6221 getIOMessageString(msgType
));
6223 context
->maxTimeRequested
= (typeof(context
->maxTimeRequested
))notify
.returnValue
;
6227 // Track time taken to ack, by storing the timestamp of
6228 // callback completion
6230 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6232 context
->responseArray
->setObject(msgIndex
, num
);
6235 context
->responseArray
->setObject(msgIndex
, replied
);
6239 if (enableTracing
) {
6240 SUB_ABSOLUTETIME(&end
, &start
);
6241 absolutetime_to_nanoseconds(end
, &nsec
);
6243 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (notify
.returnValue
!= 0)) {
6244 getPMRootDomain()->traceNotificationResponse(notifier
, NS_TO_MS(nsec
), (uint32_t) notify
.returnValue
);
6248 // not a client of ours
6249 // so we won't be waiting for response
6250 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6251 context
->responseArray
->setObject(msgIndex
, replied
);
6253 if (context
->notifyClients
) {
6254 context
->notifyClients
->setObject(msgIndex
, object
);
6258 //*********************************************************************************
6259 // [static private] pmTellCapabilityAppWithResponse
6260 //*********************************************************************************
6263 IOService::pmTellCapabilityAppWithResponse( OSObject
* object
, void * arg
)
6265 IOPMSystemCapabilityChangeParameters msgArg
;
6266 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6267 OSObject
* replied
= kOSBooleanTrue
;
6268 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6269 uint32_t msgIndex
, msgRef
, msgType
;
6270 #if LOG_APP_RESPONSE_TIMES
6274 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
6278 memset(&msgArg
, 0, sizeof(msgArg
));
6279 if (context
->messageFilter
&&
6280 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
)) {
6284 if (context
->us
== getPMRootDomain() &&
6285 getPMRootDomain()->isAOTMode()
6287 OSNumber
*clientID
= NULL
;
6288 boolean_t proc_suspended
= FALSE
;
6290 if ((clientID
= copyClientIDForNotification(object
, context
))) {
6291 uint32_t clientPID
= clientID
->unsigned32BitValue();
6292 clientID
->release();
6293 proc
= proc_find(clientPID
);
6295 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6296 if (proc_suspended
) {
6297 logClientIDForNotification(object
, context
, "PMTellCapablityAppWithResponse - Suspended");
6298 } else if (get_task_suspended((task_t
) proc
->task
)) {
6299 proc_suspended
= true;
6300 context
->skippedInDark
++;
6303 if (proc_suspended
) {
6309 context
->notSkippedInDark
++;
6311 // Create client array (for tracking purposes) only if the service
6312 // has app clients. Usually only root domain does.
6313 if (NULL
== context
->notifyClients
) {
6314 context
->notifyClients
= OSArray::withCapacity(32);
6315 assert(context
->notifyClients
!= NULL
);
6318 msgType
= context
->messageType
;
6319 msgIndex
= context
->responseArray
->getCount();
6320 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6322 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6323 if (kIOLogDebugPower
& gIOKitDebug
) {
6324 // Log client pid/name and client array index.
6325 OSNumber
* clientID
= NULL
;
6326 OSString
* clientIDString
= NULL
;;
6327 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6329 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6332 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
6333 context
->us
->getName(),
6334 msgIndex
, getIOMessageString(msgType
),
6335 (replied
!= kOSBooleanTrue
),
6336 clientIDString
? clientIDString
->getCStringNoCopy() : "");
6338 clientID
->release();
6340 if (clientIDString
) {
6341 clientIDString
->release();
6345 msgArg
.notifyRef
= msgRef
;
6346 msgArg
.maxWaitForReply
= 0;
6348 if (replied
== kOSBooleanTrue
) {
6349 msgArg
.notifyRef
= 0;
6350 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6351 if (context
->notifyClients
) {
6352 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
6356 clock_get_uptime(&now
);
6357 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6359 context
->responseArray
->setObject(msgIndex
, num
);
6362 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6365 if (context
->notifyClients
) {
6366 context
->notifyClients
->setObject(msgIndex
, object
);
6370 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6373 //*********************************************************************************
6374 // [static private] pmTellCapabilityClientWithResponse
6375 //*********************************************************************************
6378 IOService::pmTellCapabilityClientWithResponse(
6379 OSObject
* object
, void * arg
)
6381 IOPMSystemCapabilityChangeParameters msgArg
;
6382 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6383 OSObject
* replied
= kOSBooleanTrue
;
6384 _IOServiceInterestNotifier
* notifier
;
6385 uint32_t msgIndex
, msgRef
, msgType
;
6387 AbsoluteTime start
, end
;
6391 memset(&msgArg
, 0, sizeof(msgArg
));
6392 if (context
->messageFilter
&&
6393 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, NULL
)) {
6394 getPMRootDomain()->traceFilteredNotification(object
);
6398 if (NULL
== context
->notifyClients
) {
6399 context
->notifyClients
= OSArray::withCapacity(32);
6400 assert(context
->notifyClients
!= NULL
);
6403 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6404 msgType
= context
->messageType
;
6405 msgIndex
= context
->responseArray
->getCount();
6406 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6407 enableTracing
= context
->enableTracing
&& (notifier
!= NULL
);
6409 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6410 if (gIOKitDebug
& kIOLogPower
) {
6411 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6412 if (OSDynamicCast(IOService
, object
)) {
6413 const char *who
= ((IOService
*) object
)->getName();
6414 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6415 } else if (notifier
) {
6416 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6420 msgArg
.notifyRef
= msgRef
;
6421 msgArg
.maxWaitForReply
= 0;
6423 clock_get_uptime(&start
);
6424 if (enableTracing
) {
6425 getPMRootDomain()->traceNotification(notifier
, true, start
, msgIndex
);
6428 retCode
= context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6430 clock_get_uptime(&end
);
6431 if (enableTracing
) {
6432 getPMRootDomain()->traceNotification(notifier
, false, end
, msgIndex
);
6435 if (kIOReturnSuccess
== retCode
) {
6436 if (0 == msgArg
.maxWaitForReply
) {
6437 // client doesn't want time to respond
6438 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6439 context
->responseArray
->setObject(msgIndex
, replied
);
6441 replied
= kOSBooleanFalse
;
6442 if (msgArg
.maxWaitForReply
> context
->maxTimeRequested
) {
6443 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
) {
6444 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
6445 PM_ERROR("%s: client %p returned %u for %s\n",
6446 context
->us
->getName(),
6447 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6448 msgArg
.maxWaitForReply
,
6449 getIOMessageString(msgType
));
6451 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6455 // Track time taken to ack, by storing the timestamp of
6456 // callback completion
6458 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6460 context
->responseArray
->setObject(msgIndex
, num
);
6463 context
->responseArray
->setObject(msgIndex
, replied
);
6467 if (enableTracing
) {
6468 SUB_ABSOLUTETIME(&end
, &start
);
6469 absolutetime_to_nanoseconds(end
, &nsec
);
6471 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (msgArg
.maxWaitForReply
!= 0)) {
6472 getPMRootDomain()->traceNotificationResponse(notifier
, NS_TO_MS(nsec
), msgArg
.maxWaitForReply
);
6476 // not a client of ours
6477 // so we won't be waiting for response
6478 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6479 context
->responseArray
->setObject(msgIndex
, replied
);
6481 if (context
->notifyClients
) {
6482 context
->notifyClients
->setObject(msgIndex
, object
);
6486 //*********************************************************************************
6487 // [public] tellNoChangeDown
6489 // Notify registered applications and kernel clients that we are not
6492 // Subclass can override this to send a different message type. Parameter is
6493 // the aborted destination state number.
6494 //*********************************************************************************
6497 IOService::tellNoChangeDown( unsigned long )
6499 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6502 //*********************************************************************************
6503 // [public] tellChangeUp
6505 // Notify registered applications and kernel clients that we are raising power.
6507 // Subclass can override this to send a different message type. Parameter is
6508 // the aborted destination state number.
6509 //*********************************************************************************
6512 IOService::tellChangeUp( unsigned long )
6514 return tellClients( kIOMessageDeviceHasPoweredOn
);
6517 //*********************************************************************************
6518 // [protected] tellClients
6520 // Notify registered applications and kernel clients of something.
6521 //*********************************************************************************
6524 IOService::tellClients( int messageType
)
6526 IOPMInterestContext context
;
6528 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6530 memset(&context
, 0, sizeof(context
));
6531 context
.messageType
= messageType
;
6532 context
.isPreChange
= fIsPreChange
;
6534 context
.stateNumber
= fHeadNotePowerState
;
6535 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6536 context
.changeFlags
= fHeadNoteChangeFlags
;
6537 context
.enableTracing
= IS_ROOT_DOMAIN
;
6538 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6539 OSMemberFunctionCast(
6541 (IOPMrootDomain
*)this,
6542 &IOPMrootDomain::systemMessageFilter
) : NULL
;
6544 context
.notifyType
= kNotifyPriority
;
6545 applyToInterested( gIOPriorityPowerStateInterest
,
6546 tellKernelClientApplier
, (void *) &context
);
6548 context
.notifyType
= kNotifyApps
;
6549 applyToInterested( gIOAppPowerStateInterest
,
6550 tellAppClientApplier
, (void *) &context
);
6552 applyToInterested( gIOGeneralInterest
,
6553 tellKernelClientApplier
, (void *) &context
);
6556 //*********************************************************************************
6557 // [private] tellKernelClientApplier
6559 // Message a kernel client.
6560 //*********************************************************************************
6563 tellKernelClientApplier( OSObject
* object
, void * arg
)
6565 IOPowerStateChangeNotification notify
;
6566 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6567 bool enableTracing
= context
->enableTracing
;
6569 if (context
->messageFilter
&&
6570 !context
->messageFilter(context
->us
, object
, context
, NULL
, NULL
)) {
6571 IOService::getPMRootDomain()->traceFilteredNotification(object
);
6575 notify
.powerRef
= (void *) NULL
;
6576 notify
.returnValue
= 0;
6577 notify
.stateNumber
= context
->stateNumber
;
6578 notify
.stateFlags
= context
->stateFlags
;
6580 if (enableTracing
) {
6581 IOService::getPMRootDomain()->traceNotification(object
, true);
6584 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6586 if (enableTracing
) {
6587 IOService::getPMRootDomain()->traceNotification(object
, false);
6592 copyClientIDForNotification(
6594 IOPMInterestContext
*context
)
6596 OSNumber
*clientID
= NULL
;
6597 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6602 logClientIDForNotification(
6604 IOPMInterestContext
*context
,
6605 const char *logString
)
6607 OSString
*logClientID
= NULL
;
6608 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6612 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6615 PM_LOG("%s %s %s, %s\n",
6616 context
->us
->getName(), logString
,
6617 IOService::getIOMessageString(context
->messageType
),
6618 logClientID
? logClientID
->getCStringNoCopy() : "");
6621 logClientID
->release();
6626 clientID
->release();
6633 tellAppClientApplier( OSObject
* object
, void * arg
)
6635 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6636 OSNumber
* clientID
= NULL
;
6638 boolean_t proc_suspended
= FALSE
;
6640 if (context
->us
== IOService::getPMRootDomain()) {
6641 if ((clientID
= copyClientIDForNotification(object
, context
))) {
6642 uint32_t clientPID
= clientID
->unsigned32BitValue();
6643 clientID
->release();
6644 proc
= proc_find(clientPID
);
6647 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6648 if (proc_suspended
) {
6649 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6650 } else if (IOService::getPMRootDomain()->isAOTMode() && get_task_suspended((task_t
) proc
->task
)) {
6651 proc_suspended
= true;
6652 context
->skippedInDark
++;
6655 if (proc_suspended
) {
6662 if (context
->messageFilter
&&
6663 !context
->messageFilter(context
->us
, object
, context
, NULL
, NULL
)) {
6664 if (kIOLogDebugPower
& gIOKitDebug
) {
6665 logClientIDForNotification(object
, context
, "DROP App");
6669 context
->notSkippedInDark
++;
6671 if (kIOLogDebugPower
& gIOKitDebug
) {
6672 logClientIDForNotification(object
, context
, "MESG App");
6675 context
->us
->messageClient(context
->messageType
, object
, NULL
);
6678 //*********************************************************************************
6679 // [private] checkForDone
6680 //*********************************************************************************
6683 IOService::checkForDone( void )
6688 if (fResponseArray
== NULL
) {
6693 theFlag
= fResponseArray
->getObject(i
);
6695 if (NULL
== theFlag
) {
6699 if (kOSBooleanTrue
!= theFlag
) {
6706 //*********************************************************************************
6707 // [public] responseValid
6708 //*********************************************************************************
6711 IOService::responseValid( uint32_t refcon
, int pid
)
6713 UInt16 serialComponent
;
6714 UInt16 ordinalComponent
;
6716 OSObject
*object
= NULL
;
6718 serialComponent
= (refcon
>> 16) & 0xFFFF;
6719 ordinalComponent
= (refcon
& 0xFFFF);
6721 if (serialComponent
!= fSerialNumber
) {
6725 if (fResponseArray
== NULL
) {
6729 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6731 if (theFlag
== NULL
) {
6735 if (fNotifyClientArray
) {
6736 object
= fNotifyClientArray
->getObject(ordinalComponent
);
6740 if ((num
= OSDynamicCast(OSNumber
, theFlag
))) {
6746 clock_get_uptime(&now
);
6747 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6748 SUB_ABSOLUTETIME(&now
, &start
);
6749 absolutetime_to_nanoseconds(now
, &nsec
);
6753 proc_name(pid
, name
, sizeof(name
));
6755 if (nsec
> LOG_APP_RESPONSE_TIMES
) {
6756 IOLog("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec
),
6761 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
) {
6762 // TODO: populate the messageType argument
6763 getPMRootDomain()->pmStatsRecordApplicationResponse(
6764 gIOPMStatsResponseSlow
,
6765 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6767 getPMRootDomain()->pmStatsRecordApplicationResponse(
6768 gIOPMStatsResponsePrompt
,
6769 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6772 getPMRootDomain()->traceNotificationAck(object
, NS_TO_MS(nsec
));
6775 if (kIOLogDebugPower
& gIOKitDebug
) {
6776 PM_LOG("Ack(%u) %u ms\n",
6777 (uint32_t) ordinalComponent
,
6780 theFlag
= kOSBooleanFalse
;
6781 } else if (object
) {
6782 getPMRootDomain()->pmStatsRecordApplicationResponse(
6783 gIOPMStatsResponsePrompt
,
6784 NULL
, 0, 0, pid
, object
);
6787 if (kOSBooleanFalse
== theFlag
) {
6788 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6794 //*********************************************************************************
6795 // [public] allowPowerChange
6797 // Our power state is about to lower, and we have notified applications
6798 // and kernel clients, and one of them has acknowledged. If this is the last to do
6799 // so, and all acknowledgements are positive, we continue with the power change.
6800 //*********************************************************************************
6803 IOService::allowPowerChange( unsigned long refcon
)
6805 IOPMRequest
* request
;
6809 return kIOReturnSuccess
;
6812 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6814 return kIOReturnNoMemory
;
6817 request
->fArg0
= (void *) refcon
;
6818 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6819 request
->fArg2
= (void *) NULL
;
6820 submitPMRequest( request
);
6822 return kIOReturnSuccess
;
6827 IOService::serializedAllowPowerChange2( unsigned long refcon
)
6829 // [deprecated] public
6830 return kIOReturnUnsupported
;
6832 #endif /* !__LP64__ */
6834 //*********************************************************************************
6835 // [public] cancelPowerChange
6837 // Our power state is about to lower, and we have notified applications
6838 // and kernel clients, and one of them has vetoed the change. If this is the last
6839 // client to respond, we abandon the power change.
6840 //*********************************************************************************
6843 IOService::cancelPowerChange( unsigned long refcon
)
6845 IOPMRequest
* request
;
6847 pid_t pid
= proc_selfpid();
6851 return kIOReturnSuccess
;
6855 proc_name(pid
, name
, sizeof(name
));
6856 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid
, name
);
6858 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6860 return kIOReturnNoMemory
;
6863 request
->fArg0
= (void *) refcon
;
6864 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6865 request
->fArg2
= (void *) OSString::withCString(name
);
6866 submitPMRequest( request
);
6868 return kIOReturnSuccess
;
6871 //*********************************************************************************
6872 // cancelIdlePowerDown
6874 // Internal method to trigger an idle cancel or revert
6875 //*********************************************************************************
6878 IOService::cancelIdlePowerDown( IOService
* service
)
6880 IOPMRequest
* request
;
6882 request
= acquirePMRequest(service
, kIOPMRequestTypeIdleCancel
);
6884 submitPMRequest(request
);
6890 IOService::serializedCancelPowerChange2( unsigned long refcon
)
6892 // [deprecated] public
6893 return kIOReturnUnsupported
;
6896 //*********************************************************************************
6897 // PM_Clamp_Timer_Expired
6899 // called when clamp timer expires...set power state to 0.
6900 //*********************************************************************************
6903 IOService::PM_Clamp_Timer_Expired( void )
6907 //*********************************************************************************
6910 // Set to highest available power state for a minimum of duration milliseconds
6911 //*********************************************************************************
6914 IOService::clampPowerOn( unsigned long duration
)
6917 #endif /* !__LP64__ */
6919 //*********************************************************************************
6920 // configurePowerStateReport
6922 // Configures the IOStateReport for kPMPowerStateChannel
6923 //*********************************************************************************
6925 IOService::configurePowerStatesReport( IOReportConfigureAction action
, void *result
)
6927 IOReturn rc
= kIOReturnSuccess
;
6933 return kIOReturnUnsupported
;
6936 if (!fNumberOfPowerStates
) {
6937 return kIOReturnSuccess
; // For drivers which are in power plane, but haven't called registerPowerDriver()
6940 if (fNumberOfPowerStates
> INT16_MAX
) {
6941 return kIOReturnOverrun
;
6946 case kIOReportEnable
:
6951 reportSize
= STATEREPORT_BUFSIZE(fNumberOfPowerStates
);
6952 fReportBuf
= IOMalloc(reportSize
);
6954 rc
= kIOReturnNoMemory
;
6957 memset(fReportBuf
, 0, reportSize
);
6959 STATEREPORT_INIT((uint16_t) fNumberOfPowerStates
, fReportBuf
, reportSize
,
6960 getRegistryEntryID(), kPMPowerStatesChID
, kIOReportCategoryPower
);
6962 for (i
= 0; i
< fNumberOfPowerStates
; i
++) {
6965 if (fPowerStates
[i
].capabilityFlags
& kIOPMPowerOn
) {
6966 bits
|= kPMReportPowerOn
;
6968 if (fPowerStates
[i
].capabilityFlags
& kIOPMDeviceUsable
) {
6969 bits
|= kPMReportDeviceUsable
;
6971 if (fPowerStates
[i
].capabilityFlags
& kIOPMLowPower
) {
6972 bits
|= kPMReportLowPower
;
6975 STATEREPORT_SETSTATEID(fReportBuf
, i
, ((bits
& 0xff) << 8) |
6976 ((StateOrder(fMaxPowerState
) & 0xf) << 4) | (StateOrder(i
) & 0xf));
6978 ts
= mach_absolute_time();
6979 STATEREPORT_SETSTATE(fReportBuf
, (uint16_t) fCurrentPowerState
, ts
);
6982 case kIOReportDisable
:
6983 if (fReportClientCnt
== 0) {
6984 rc
= kIOReturnBadArgument
;
6987 if (fReportClientCnt
== 1) {
6988 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
6994 case kIOReportGetDimensions
:
6996 STATEREPORT_UPDATERES(fReportBuf
, kIOReportGetDimensions
, result
);
7006 //*********************************************************************************
7007 // updatePowerStateReport
7009 // Updates the IOStateReport for kPMPowerStateChannel
7010 //*********************************************************************************
7012 IOService::updatePowerStatesReport( IOReportConfigureAction action
, void *result
, void *destination
)
7017 IOReturn rc
= kIOReturnSuccess
;
7018 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
7022 return kIOReturnUnsupported
;
7024 if (!fNumberOfPowerStates
) {
7025 return kIOReturnSuccess
;
7028 if (!result
|| !dest
) {
7029 return kIOReturnBadArgument
;
7034 case kIOReportCopyChannelData
:
7036 rc
= kIOReturnNotOpen
;
7040 ts
= mach_absolute_time();
7041 STATEREPORT_UPDATEPREP(fReportBuf
, ts
, data2cpy
, size2cpy
);
7042 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
7043 rc
= kIOReturnOverrun
;
7047 STATEREPORT_UPDATERES(fReportBuf
, kIOReportCopyChannelData
, result
);
7048 dest
->appendBytes(data2cpy
, size2cpy
);
7060 //*********************************************************************************
7061 // configureSimplePowerReport
7063 // Configures the IOSimpleReport for given channel id
7064 //*********************************************************************************
7066 IOService::configureSimplePowerReport(IOReportConfigureAction action
, void *result
)
7068 IOReturn rc
= kIOReturnSuccess
;
7071 return kIOReturnUnsupported
;
7074 if (!fNumberOfPowerStates
) {
7079 case kIOReportEnable
:
7080 case kIOReportDisable
:
7083 case kIOReportGetDimensions
:
7084 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
7092 //*********************************************************************************
7093 // updateSimplePowerReport
7095 // Updates the IOSimpleReport for the given chanel id
7096 //*********************************************************************************
7098 IOService::updateSimplePowerReport( IOReportConfigureAction action
, void *result
, void *destination
)
7102 uint64_t buf
[SIMPLEREPORT_BUFSIZE
/ sizeof(uint64_t) + 1]; // Force a 8-byte alignment
7103 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
7104 IOReturn rc
= kIOReturnSuccess
;
7109 return kIOReturnUnsupported
;
7111 if (!result
|| !dest
) {
7112 return kIOReturnBadArgument
;
7115 if (!fNumberOfPowerStates
) {
7121 case kIOReportCopyChannelData
:
7123 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), kPMCurrStateChID
, kIOReportCategoryPower
);
7125 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMPowerOn
) {
7126 bits
|= kPMReportPowerOn
;
7128 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMDeviceUsable
) {
7129 bits
|= kPMReportDeviceUsable
;
7131 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMLowPower
) {
7132 bits
|= kPMReportLowPower
;
7136 SIMPLEREPORT_SETVALUE(buf
, ((bits
& 0xff) << 8) | ((StateOrder(fMaxPowerState
) & 0xf) << 4) |
7137 (StateOrder(fCurrentPowerState
) & 0xf));
7139 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
7140 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
7141 rc
= kIOReturnOverrun
;
7145 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
7146 dest
->appendBytes(data2cpy
, size2cpy
);
7161 // MARK: Driver Overrides
7163 //*********************************************************************************
7164 // [public] setPowerState
7166 // Does nothing here. This should be implemented in a subclass driver.
7167 //*********************************************************************************
7170 IOService::setPowerState(
7171 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
7176 //*********************************************************************************
7177 // [public] maxCapabilityForDomainState
7179 // Finds the highest power state in the array whose input power requirement
7180 // is equal to the input parameter. Where a more intelligent decision is
7181 // possible, override this in the subclassed driver.
7182 //*********************************************************************************
7185 IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags
)
7187 IOPMPowerStateIndex stateIndex
;
7189 if (!fNumberOfPowerStates
) {
7190 return kPowerStateZero
;
7193 for (long order
= fNumberOfPowerStates
- 1; order
>= 0; order
--) {
7194 stateIndex
= fPowerStates
[order
].stateOrderToIndex
;
7196 if ((flags
& fPowerStates
[stateIndex
].inputPowerFlags
) ==
7197 fPowerStates
[stateIndex
].inputPowerFlags
) {
7201 return kPowerStateZero
;
7205 IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState
)
7207 return getPowerStateForDomainFlags(domainState
);
7210 //*********************************************************************************
7211 // [public] initialPowerStateForDomainState
7213 // Called to query the power state for the initial power transition.
7214 //*********************************************************************************
7217 IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState
)
7219 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
)) {
7220 // Return lowest power state for any root power domain changes
7221 return kPowerStateZero
;
7224 return getPowerStateForDomainFlags(domainState
);
7227 //*********************************************************************************
7228 // [public] powerStateForDomainState
7230 // This method is not called from PM.
7231 //*********************************************************************************
7234 IOService::powerStateForDomainState( IOPMPowerFlags domainState
)
7236 return getPowerStateForDomainFlags(domainState
);
7240 //*********************************************************************************
7241 // [deprecated] didYouWakeSystem
7243 // Does nothing here. This should be implemented in a subclass driver.
7244 //*********************************************************************************
7247 IOService::didYouWakeSystem( void )
7251 #endif /* !__LP64__ */
7253 //*********************************************************************************
7254 // [public] powerStateWillChangeTo
7256 // Does nothing here. This should be implemented in a subclass driver.
7257 //*********************************************************************************
7260 IOService::powerStateWillChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7262 return kIOPMAckImplied
;
7265 //*********************************************************************************
7266 // [public] powerStateDidChangeTo
7268 // Does nothing here. This should be implemented in a subclass driver.
7269 //*********************************************************************************
7272 IOService::powerStateDidChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7274 return kIOPMAckImplied
;
7277 //*********************************************************************************
7278 // [protected] powerChangeDone
7280 // Called from PM work loop thread.
7281 // Does nothing here. This should be implemented in a subclass policy-maker.
7282 //*********************************************************************************
7285 IOService::powerChangeDone( unsigned long )
7290 //*********************************************************************************
7291 // [deprecated] newTemperature
7293 // Does nothing here. This should be implemented in a subclass driver.
7294 //*********************************************************************************
7297 IOService::newTemperature( long currentTemp
, IOService
* whichZone
)
7301 #endif /* !__LP64__ */
7303 //*********************************************************************************
7304 // [public] systemWillShutdown
7306 // System shutdown and restart notification.
7307 //*********************************************************************************
7310 IOService::systemWillShutdown( IOOptionBits specifier
)
7312 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
7314 rootDomain
->acknowledgeSystemWillShutdown( this );
7319 // MARK: PM State Machine
7321 //*********************************************************************************
7322 // [private static] acquirePMRequest
7323 //*********************************************************************************
7326 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
7327 IOPMRequest
* active
)
7329 IOPMRequest
* request
;
7333 request
= IOPMRequest::create();
7335 request
->init( target
, requestType
);
7337 IOPMRequest
* root
= active
->getRootRequest();
7339 request
->attachRootRequest(root
);
7343 PM_ERROR("%s: No memory for PM request type 0x%x\n",
7344 target
->getName(), (uint32_t) requestType
);
7349 //*********************************************************************************
7350 // [private static] releasePMRequest
7351 //*********************************************************************************
7354 IOService::releasePMRequest( IOPMRequest
* request
)
7362 //*********************************************************************************
7363 // [private static] submitPMRequest
7364 //*********************************************************************************
7367 IOService::submitPMRequest( IOPMRequest
* request
)
7370 assert( gIOPMReplyQueue
);
7371 assert( gIOPMRequestQueue
);
7373 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7374 (long)request
->getType(), OBFUSCATE(request
),
7375 OBFUSCATE(request
->getTarget()), request
->getTarget()->getName(),
7376 OBFUSCATE(request
->fArg0
),
7377 OBFUSCATE(request
->fArg1
), OBFUSCATE(request
->fArg2
));
7379 if (request
->isReplyType()) {
7380 gIOPMReplyQueue
->queuePMRequest( request
);
7382 gIOPMRequestQueue
->queuePMRequest( request
);
7387 IOService::submitPMRequests( IOPMRequest
** requests
, IOItemCount count
)
7390 assert( count
> 0 );
7391 assert( gIOPMRequestQueue
);
7393 for (IOItemCount i
= 0; i
< count
; i
++) {
7394 IOPMRequest
* req
= requests
[i
];
7395 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7396 (long)req
->getType(), OBFUSCATE(req
),
7397 OBFUSCATE(req
->getTarget()), req
->getTarget()->getName(),
7398 OBFUSCATE(req
->fArg0
),
7399 OBFUSCATE(req
->fArg1
), OBFUSCATE(req
->fArg2
));
7402 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
7405 //*********************************************************************************
7406 // [private] actionPMRequestQueue
7408 // IOPMRequestQueue::checkForWork() passing a new request to the request target.
7409 //*********************************************************************************
7412 IOService::actionPMRequestQueue(
7413 IOPMRequest
* request
,
7414 IOPMRequestQueue
* queue
)
7419 // Work queue will immediately execute the request if the per-service
7420 // request queue is empty. Note pwrMgt is the target's IOServicePM.
7422 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
7424 // Calling PM without PMinit() is not allowed, fail the request.
7425 // Need to signal more when completing attached requests.
7427 PM_LOG("%s: PM not initialized\n", getName());
7428 PM_LOG1("[- %02x] %p [%p %s] !initialized\n",
7429 request
->getType(), OBFUSCATE(request
),
7430 OBFUSCATE(this), getName());
7432 more
= gIOPMCompletionQueue
->queuePMRequest(request
);
7434 gIOPMWorkQueue
->incrementProducerCount();
7441 //*********************************************************************************
7442 // [private] actionPMCompletionQueue
7444 // IOPMCompletionQueue::checkForWork() passing a completed request to the
7446 //*********************************************************************************
7449 IOService::actionPMCompletionQueue(
7450 IOPMRequest
* request
,
7451 IOPMCompletionQueue
* queue
)
7453 bool more
= (request
->getNextRequest() != NULL
);
7454 IOPMRequest
* root
= request
->getRootRequest();
7456 if (root
&& (root
!= request
)) {
7460 gIOPMWorkQueue
->incrementProducerCount();
7463 releasePMRequest( request
);
7467 //*********************************************************************************
7468 // [private] actionPMWorkQueueRetire
7470 // IOPMWorkQueue::checkForWork() passing a retired request to the request target.
7471 //*********************************************************************************
7474 IOService::actionPMWorkQueueRetire( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7476 assert(request
&& queue
);
7478 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7479 request
->getType(), OBFUSCATE(request
),
7480 OBFUSCATE(this), getName(),
7481 fMachineState
, gIOPMBusyRequestCount
);
7483 // Catch requests created by idleTimerExpired()
7484 if (request
->getType() == kIOPMRequestTypeActivityTickle
) {
7485 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
7487 if ((tickleFlags
& kTickleTypePowerDrop
) && fIdleTimerPeriod
) {
7489 } else if (tickleFlags
== (kTickleTypeActivity
| kTickleTypePowerRise
)) {
7490 // Invalidate any idle power drop that got queued while
7491 // processing this request.
7492 fIdleTimerGeneration
++;
7496 // When the completed request is linked, tell work queue there is
7497 // more work pending.
7499 return gIOPMCompletionQueue
->queuePMRequest( request
);
7502 //*********************************************************************************
7503 // [private] isPMBlocked
7505 // Check if machine state transition is blocked.
7506 //*********************************************************************************
7509 IOService::isPMBlocked( IOPMRequest
* request
, int count
)
7514 if (kIOPM_Finished
== fMachineState
) {
7518 if (kIOPM_DriverThreadCallDone
== fMachineState
) {
7519 // 5 = kDriverCallInformPreChange
7520 // 6 = kDriverCallInformPostChange
7521 // 7 = kDriverCallSetPowerState
7522 // 8 = kRootDomainInformPreChange
7523 if (fDriverCallBusy
) {
7524 reason
= 5 + fDriverCallReason
;
7529 // Waiting on driver's setPowerState() timeout.
7534 // Child or interested driver acks pending.
7535 if (fHeadNotePendingAcks
) {
7539 // Waiting on apps or priority power interest clients.
7540 if (fResponseArray
) {
7544 #if USE_SETTLE_TIMER
7545 // Waiting on settle timer expiration.
7546 if (fSettleTimeUS
) {
7552 fWaitReason
= reason
;
7556 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7557 request
->getType(), OBFUSCATE(request
),
7558 OBFUSCATE(this), getName(),
7559 fMachineState
, reason
);
7568 //*********************************************************************************
7569 // [private] actionPMWorkQueueInvoke
7571 // IOPMWorkQueue::checkForWork() passing a request to the
7572 // request target for execution.
7573 //*********************************************************************************
7576 IOService::actionPMWorkQueueInvoke( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7581 assert(request
&& queue
);
7583 while (isPMBlocked(request
, loop
++) == false) {
7584 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7585 request
->getType(), OBFUSCATE(request
),
7586 OBFUSCATE(this), getName(), fMachineState
);
7588 gIOPMRequest
= request
;
7589 gIOPMWorkInvokeCount
++;
7591 // Every PM machine states must be handled in one of the cases below.
7593 switch (fMachineState
) {
7594 case kIOPM_Finished
:
7595 start_watchdog_timer();
7597 executePMRequest( request
);
7600 case kIOPM_OurChangeTellClientsPowerDown
:
7601 // Root domain might self cancel due to assertions.
7602 if (IS_ROOT_DOMAIN
) {
7603 bool cancel
= (bool) fDoNotPowerDown
;
7604 getPMRootDomain()->askChangeDownDone(
7605 &fHeadNoteChangeFlags
, &cancel
);
7606 fDoNotPowerDown
= cancel
;
7609 // askChangeDown() done, was it vetoed?
7610 if (!fDoNotPowerDown
) {
7611 // no, we can continue
7612 OurChangeTellClientsPowerDown();
7614 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7615 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7616 if (IS_ROOT_DOMAIN
) {
7617 // RootDomain already sent "WillSleep" to its clients
7618 tellChangeUp(fCurrentPowerState
);
7620 tellNoChangeDown(fHeadNotePowerState
);
7622 // mark the change note un-actioned
7623 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7629 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
7630 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7631 if (fDoNotPowerDown
) {
7632 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7633 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7634 if (IS_ROOT_DOMAIN
) {
7635 // RootDomain already sent "WillSleep" to its clients
7636 tellChangeUp(fCurrentPowerState
);
7638 tellNoChangeDown(fHeadNotePowerState
);
7640 // mark the change note un-actioned
7641 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7645 OurChangeTellUserPMPolicyPowerDown();
7649 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
7650 // PMRD: LastCallBeforeSleep notify done
7651 // Non-PMRD: tellChangeDown/kNotifyApps done
7652 if (fDoNotPowerDown
) {
7653 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7654 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7655 // no, tell clients we're back in the old state
7656 tellChangeUp(fCurrentPowerState
);
7657 // mark the change note un-actioned
7658 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7662 // yes, we can continue
7663 OurChangeTellPriorityClientsPowerDown();
7667 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
7668 OurChangeNotifyInterestedDriversWillChange();
7671 case kIOPM_OurChangeSetPowerState
:
7672 OurChangeSetPowerState();
7675 case kIOPM_OurChangeWaitForPowerSettle
:
7676 OurChangeWaitForPowerSettle();
7679 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
7680 OurChangeNotifyInterestedDriversDidChange();
7683 case kIOPM_OurChangeTellCapabilityDidChange
:
7684 OurChangeTellCapabilityDidChange();
7687 case kIOPM_OurChangeFinish
:
7691 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
7692 ParentChangeTellPriorityClientsPowerDown();
7695 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
7696 ParentChangeNotifyInterestedDriversWillChange();
7699 case kIOPM_ParentChangeSetPowerState
:
7700 ParentChangeSetPowerState();
7703 case kIOPM_ParentChangeWaitForPowerSettle
:
7704 ParentChangeWaitForPowerSettle();
7707 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7708 ParentChangeNotifyInterestedDriversDidChange();
7711 case kIOPM_ParentChangeTellCapabilityDidChange
:
7712 ParentChangeTellCapabilityDidChange();
7715 case kIOPM_ParentChangeAcknowledgePowerChange
:
7716 ParentChangeAcknowledgePowerChange();
7719 case kIOPM_DriverThreadCallDone
:
7720 switch (fDriverCallReason
) {
7721 case kDriverCallInformPreChange
:
7722 case kDriverCallInformPostChange
:
7723 notifyInterestedDriversDone();
7725 case kDriverCallSetPowerState
:
7726 notifyControllingDriverDone();
7728 case kRootDomainInformPreChange
:
7729 notifyRootDomainDone();
7732 panic("%s: bad call reason %x",
7733 getName(), fDriverCallReason
);
7737 case kIOPM_NotifyChildrenOrdered
:
7738 notifyChildrenOrdered();
7741 case kIOPM_NotifyChildrenDelayed
:
7742 notifyChildrenDelayed();
7745 case kIOPM_NotifyChildrenStart
:
7746 // pop notifyAll() state saved by notifyInterestedDriversDone()
7751 case kIOPM_SyncTellClientsPowerDown
:
7752 // Root domain might self cancel due to assertions.
7753 if (IS_ROOT_DOMAIN
) {
7754 bool cancel
= (bool) fDoNotPowerDown
;
7755 getPMRootDomain()->askChangeDownDone(
7756 &fHeadNoteChangeFlags
, &cancel
);
7757 fDoNotPowerDown
= cancel
;
7759 if (!fDoNotPowerDown
) {
7760 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7761 fOutOfBandParameter
= kNotifyApps
;
7762 tellChangeDown(fHeadNotePowerState
);
7764 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7765 // askChangeDown/kNotifyApps
7766 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7767 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7768 tellNoChangeDown(fHeadNotePowerState
);
7769 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7774 case kIOPM_SyncTellPriorityClientsPowerDown
:
7775 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7776 if (!fDoNotPowerDown
) {
7777 fMachineState
= kIOPM_SyncNotifyWillChange
;
7778 fOutOfBandParameter
= kNotifyPriority
;
7779 tellChangeDown(fHeadNotePowerState
);
7781 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7782 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7783 tellChangeUp(fCurrentPowerState
);
7784 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7789 case kIOPM_SyncNotifyWillChange
:
7790 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
) {
7791 fMachineState
= kIOPM_SyncFinish
;
7794 fMachineState
= kIOPM_SyncNotifyDidChange
;
7795 fDriverCallReason
= kDriverCallInformPreChange
;
7799 case kIOPM_SyncNotifyDidChange
:
7800 fIsPreChange
= false;
7802 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
7803 fMachineState
= kIOPM_SyncFinish
;
7805 assert(IS_ROOT_DOMAIN
);
7806 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7809 fDriverCallReason
= kDriverCallInformPostChange
;
7813 case kIOPM_SyncTellCapabilityDidChange
:
7814 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7817 case kIOPM_SyncFinish
:
7818 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
7819 ParentChangeAcknowledgePowerChange();
7825 case kIOPM_TellCapabilityChangeDone
:
7827 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
) {
7828 MS_POP(); // MS passed to tellSystemCapabilityChange()
7831 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7833 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
) {
7834 MS_POP(); // MS passed to tellSystemCapabilityChange()
7837 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7839 tellClientsWithResponse( fOutOfBandMessage
);
7843 panic("PMWorkQueueInvoke: unknown machine state %x",
7847 gIOPMRequest
= NULL
;
7849 if (fMachineState
== kIOPM_Finished
) {
7850 stop_watchdog_timer();
7859 //*********************************************************************************
7860 // [private] executePMRequest
7861 //*********************************************************************************
7864 IOService::executePMRequest( IOPMRequest
* request
)
7866 assert( kIOPM_Finished
== fMachineState
);
7868 switch (request
->getType()) {
7869 case kIOPMRequestTypePMStop
:
7870 handlePMstop( request
);
7873 case kIOPMRequestTypeAddPowerChild1
:
7874 addPowerChild1( request
);
7877 case kIOPMRequestTypeAddPowerChild2
:
7878 addPowerChild2( request
);
7881 case kIOPMRequestTypeAddPowerChild3
:
7882 addPowerChild3( request
);
7885 case kIOPMRequestTypeRegisterPowerDriver
:
7886 handleRegisterPowerDriver( request
);
7889 case kIOPMRequestTypeAdjustPowerState
:
7890 fAdjustPowerScheduled
= false;
7894 case kIOPMRequestTypePowerDomainWillChange
:
7895 handlePowerDomainWillChangeTo( request
);
7898 case kIOPMRequestTypePowerDomainDidChange
:
7899 handlePowerDomainDidChangeTo( request
);
7902 case kIOPMRequestTypeRequestPowerState
:
7903 case kIOPMRequestTypeRequestPowerStateOverride
:
7904 handleRequestPowerState( request
);
7907 case kIOPMRequestTypePowerOverrideOnPriv
:
7908 case kIOPMRequestTypePowerOverrideOffPriv
:
7909 handlePowerOverrideChanged( request
);
7912 case kIOPMRequestTypeActivityTickle
:
7913 handleActivityTickle( request
);
7916 case kIOPMRequestTypeSynchronizePowerTree
:
7917 handleSynchronizePowerTree( request
);
7920 case kIOPMRequestTypeSetIdleTimerPeriod
:
7922 fIdleTimerPeriod
= (typeof(fIdleTimerPeriod
))(uintptr_t) request
->fArg0
;
7923 fNextIdleTimerPeriod
= fIdleTimerPeriod
;
7924 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0)) {
7930 case kIOPMRequestTypeIgnoreIdleTimer
:
7931 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7934 case kIOPMRequestTypeQuiescePowerTree
:
7935 gIOPMWorkQueue
->finishQuiesceRequest(request
);
7939 panic("executePMRequest: unknown request type %x", request
->getType());
7943 //*********************************************************************************
7944 // [private] actionPMReplyQueue
7946 // IOPMRequestQueue::checkForWork() passing a reply-type request to the
7948 //*********************************************************************************
7951 IOService::actionPMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7955 assert( request
&& queue
);
7956 assert( request
->isReplyType());
7958 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7959 request
->getType(), OBFUSCATE(request
),
7960 OBFUSCATE(this), getName(), fMachineState
);
7962 switch (request
->getType()) {
7963 case kIOPMRequestTypeAllowPowerChange
:
7964 case kIOPMRequestTypeCancelPowerChange
:
7965 // Check if we are expecting this response.
7966 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7967 (int)(uintptr_t) request
->fArg1
)) {
7968 if (kIOPMRequestTypeCancelPowerChange
== request
->getType()) {
7969 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7970 // flag is set. Only root domain will set this flag.
7971 // However, there is one exception to this rule. User-space PM
7972 // policy may choose to cancel sleep even after all clients have
7973 // been notified that we will lower power.
7975 if ((fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7976 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7977 || ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0)) {
7978 fDoNotPowerDown
= true;
7980 OSString
* name
= (OSString
*) request
->fArg2
;
7981 getPMRootDomain()->pmStatsRecordApplicationResponse(
7982 gIOPMStatsResponseCancel
,
7983 name
? name
->getCStringNoCopy() : "", 0,
7984 0, (int)(uintptr_t) request
->fArg1
, NULL
);
7988 if (checkForDone()) {
7990 cleanClientResponses(false);
7994 // OSString containing app name in Arg2 must be released.
7995 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
) {
7996 OSObject
* obj
= (OSObject
*) request
->fArg2
;
8003 case kIOPMRequestTypeAckPowerChange
:
8004 more
= handleAcknowledgePowerChange( request
);
8007 case kIOPMRequestTypeAckSetPowerState
:
8008 if (fDriverTimer
== -1) {
8009 // driver acked while setPowerState() call is in-flight.
8010 // take this ack, return value from setPowerState() is irrelevant.
8011 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
8012 (uintptr_t) this, fDriverTimer
);
8014 } else if (fDriverTimer
> 0) {
8015 // expected ack, stop the timer
8018 getPMRootDomain()->reset_watchdog_timer(this, 0);
8020 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
8021 if (nsec
> gIOPMSetPowerStateLogNS
) {
8022 getPMRootDomain()->pmStatsRecordApplicationResponse(
8023 gIOPMStatsDriverPSChangeSlow
,
8024 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
8025 NULL
, fHeadNotePowerState
, true);
8028 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
8033 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
8037 case kIOPMRequestTypeInterestChanged
:
8038 handleInterestChanged( request
);
8042 case kIOPMRequestTypeIdleCancel
:
8043 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
8044 || (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
8045 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
8046 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
8047 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
)) {
8048 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
8049 PM_LOG2("%s: cancel from machine state %d\n",
8050 getName(), fMachineState
);
8051 fDoNotPowerDown
= true;
8052 // Stop waiting for app replys.
8053 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
8054 (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
) ||
8055 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
) ||
8056 (fMachineState
== kIOPM_SyncTellClientsPowerDown
)) {
8057 cleanClientResponses(false);
8063 case kIOPMRequestTypeChildNotifyDelayCancel
:
8064 if (fMachineState
== kIOPM_NotifyChildrenDelayed
) {
8065 PM_LOG2("%s: delay notify cancelled\n", getName());
8066 notifyChildrenDelayed();
8071 panic("PMReplyQueue: unknown reply type %x", request
->getType());
8074 more
|= gIOPMCompletionQueue
->queuePMRequest(request
);
8076 gIOPMWorkQueue
->incrementProducerCount();
8082 //*********************************************************************************
8083 // [private] assertPMDriverCall / deassertPMDriverCall
8084 //*********************************************************************************
8087 IOService::assertPMDriverCall(
8088 IOPMDriverCallEntry
* entry
,
8089 IOOptionBits method
,
8090 const IOPMinformee
* inform
,
8091 IOOptionBits options
)
8093 IOService
* target
= NULL
;
8102 if (fLockedFlags
.PMStop
) {
8106 if (((options
& kIOPMDriverCallNoInactiveCheck
) == 0) && isInactive()) {
8111 if (!inform
->active
) {
8114 target
= inform
->whatObject
;
8115 if (target
->isInactive()) {
8120 // Record calling address for sleep failure diagnostics
8122 case kIOPMDriverCallMethodSetPowerState
:
8123 entry
->callMethod
= OSMemberFunctionCast(const void *, fControllingDriver
, &IOService::setPowerState
);
8125 case kIOPMDriverCallMethodWillChange
:
8126 entry
->callMethod
= OSMemberFunctionCast(const void *, target
, &IOService::powerStateWillChangeTo
);
8128 case kIOPMDriverCallMethodDidChange
:
8129 entry
->callMethod
= OSMemberFunctionCast(const void *, target
, &IOService::powerStateDidChangeTo
);
8131 case kIOPMDriverCallMethodUnknown
:
8132 case kIOPMDriverCallMethodSetAggressive
:
8134 entry
->callMethod
= NULL
;
8138 entry
->thread
= current_thread();
8139 entry
->target
= target
;
8140 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8150 IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
8152 bool wakeup
= false;
8156 assert( !queue_empty(&fPMDriverCallQueue
));
8157 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8158 if (fLockedFlags
.PMDriverCallWait
) {
8165 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
8170 IOService::getBlockingDriverCall(thread_t
*thread
, const void **callMethod
)
8172 const IOPMDriverCallEntry
* entry
= NULL
;
8173 bool blocked
= false;
8179 if (current_thread() != gIOPMWatchDogThread
) {
8180 // Meant to be accessed only from watchdog thread
8185 entry
= qe_queue_first(&fPMDriverCallQueue
, IOPMDriverCallEntry
, link
);
8187 *thread
= entry
->thread
;
8188 *callMethod
= entry
->callMethod
;
8198 IOService::waitForPMDriverCall( IOService
* target
)
8200 const IOPMDriverCallEntry
* entry
;
8201 thread_t thread
= current_thread();
8202 AbsoluteTime deadline
;
8209 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
8211 // Target of interested driver call
8212 if (target
&& (target
!= entry
->target
)) {
8216 if (entry
->thread
== thread
) {
8218 PM_LOG("%s: %s(%s) on PM thread\n",
8219 fName
, __FUNCTION__
, target
? target
->getName() : "");
8220 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
8221 fName
, __FUNCTION__
, target
? target
->getName() : "");
8232 fLockedFlags
.PMDriverCallWait
= true;
8233 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
8234 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
8235 fLockedFlags
.PMDriverCallWait
= false;
8236 if (THREAD_TIMED_OUT
== waitResult
) {
8237 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
8244 //*********************************************************************************
8245 // [private] Debug helpers
8246 //*********************************************************************************
8249 IOService::getIOMessageString( uint32_t msg
)
8251 #define MSG_ENTRY(x) {(int) x, #x}
8253 static const IONamedValue msgNames
[] = {
8254 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
8255 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
8256 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
8257 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
8258 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
8259 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
8260 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
8261 MSG_ENTRY( kIOMessageCanSystemSleep
),
8262 MSG_ENTRY( kIOMessageSystemWillSleep
),
8263 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
8264 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
8265 MSG_ENTRY( kIOMessageSystemWillRestart
),
8266 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
8267 MSG_ENTRY( kIOMessageSystemCapabilityChange
),
8268 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep
),
8269 MSG_ENTRY( kIOMessageSystemPagingOff
),
8273 return IOFindNameForValue(msg
, msgNames
);
8277 getNotificationPhaseString( uint32_t phase
)
8279 #define PHASE_ENTRY(x) {(int) x, #x}
8281 static const IONamedValue phaseNames
[] = {
8282 PHASE_ENTRY( kNotifyApps
),
8283 PHASE_ENTRY( kNotifyPriority
),
8284 PHASE_ENTRY( kNotifyCapabilityChangeApps
),
8285 PHASE_ENTRY( kNotifyCapabilityChangePriority
),
8289 return IOFindNameForValue(phase
, phaseNames
);
8293 // MARK: IOPMRequest
8295 //*********************************************************************************
8296 // IOPMRequest Class
8298 // Requests from PM clients, and also used for inter-object messaging within PM.
8299 //*********************************************************************************
8301 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
8304 IOPMRequest::create( void )
8306 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
8307 if (me
&& !me
->init(NULL
, kIOPMRequestTypeInvalid
)) {
8315 IOPMRequest::init( IOService
* target
, IOOptionBits type
)
8317 if (!IOCommand::init()) {
8321 fRequestType
= type
;
8328 // Root node and root domain requests does not prevent the power tree from
8329 // becoming quiescent.
8331 fIsQuiesceBlocker
= ((fTarget
!= gIOPMRootNode
) &&
8332 (fTarget
!= IOService::getPMRootDomain()));
8338 IOPMRequest::reset( void )
8340 assert( fWorkWaitCount
== 0 );
8341 assert( fFreeWaitCount
== 0 );
8343 detachNextRequest();
8344 detachRootRequest();
8346 if (fCompletionAction
&& (fRequestType
== kIOPMRequestTypeQuiescePowerTree
)) {
8347 // Call the completion on PM work loop context
8348 fCompletionAction(fCompletionTarget
, fCompletionParam
);
8349 fCompletionAction
= NULL
;
8352 fRequestType
= kIOPMRequestTypeInvalid
;
8361 IOPMRequest::attachNextRequest( IOPMRequest
* next
)
8365 if (!fRequestNext
) {
8366 // Postpone the execution of the next request after
8368 fRequestNext
= next
;
8369 fRequestNext
->fWorkWaitCount
++;
8370 #if LOG_REQUEST_ATTACH
8371 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8372 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8373 fRequestNext
->fRequestType
,
8374 (uint32_t) fRequestNext
->fWorkWaitCount
,
8375 fTarget
->getName());
8383 IOPMRequest::detachNextRequest( void )
8388 assert(fRequestNext
->fWorkWaitCount
);
8389 if (fRequestNext
->fWorkWaitCount
) {
8390 fRequestNext
->fWorkWaitCount
--;
8392 #if LOG_REQUEST_ATTACH
8393 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8394 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8395 fRequestNext
->fRequestType
,
8396 (uint32_t) fRequestNext
->fWorkWaitCount
,
8397 fTarget
->getName());
8399 fRequestNext
= NULL
;
8406 IOPMRequest::attachRootRequest( IOPMRequest
* root
)
8410 if (!fRequestRoot
) {
8411 // Delay the completion of the root request after
8413 fRequestRoot
= root
;
8414 fRequestRoot
->fFreeWaitCount
++;
8415 #if LOG_REQUEST_ATTACH
8416 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8417 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8418 (uint32_t) fRequestRoot
->fType
,
8419 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8420 fTarget
->getName());
8428 IOPMRequest::detachRootRequest( void )
8433 assert(fRequestRoot
->fFreeWaitCount
);
8434 if (fRequestRoot
->fFreeWaitCount
) {
8435 fRequestRoot
->fFreeWaitCount
--;
8437 #if LOG_REQUEST_ATTACH
8438 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8439 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8440 (uint32_t) fRequestRoot
->fType
,
8441 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8442 fTarget
->getName());
8444 fRequestRoot
= NULL
;
8451 // MARK: IOPMRequestQueue
8453 //*********************************************************************************
8454 // IOPMRequestQueue Class
8456 // Global queues. Queues are created once and never released.
8457 //*********************************************************************************
8459 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
8462 IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
8464 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
8465 if (me
&& !me
->init(inOwner
, inAction
)) {
8473 IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
8475 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
)) {
8479 queue_init(&fQueue
);
8480 fLock
= IOLockAlloc();
8481 return fLock
!= NULL
;
8485 IOPMRequestQueue::free( void )
8491 return IOEventSource::free();
8495 IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
8497 uint64_t now
= mach_continuous_time();
8500 request
->setTimestamp(now
);
8502 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8503 IOLockUnlock(fLock
);
8505 signalWorkAvailable();
8510 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
8513 uint64_t now
= mach_continuous_time();
8515 assert(requests
&& count
);
8519 next
->setTimestamp(now
);
8521 queue_enter(&fQueue
, next
, typeof(next
), fCommandChain
);
8523 IOLockUnlock(fLock
);
8525 signalWorkAvailable();
8530 IOPMRequestQueue::checkForWork( void )
8532 Action dqAction
= (Action
) action
;
8533 IOPMRequest
* request
;
8535 int dequeueCount
= 0;
8538 IOLockLock( fLock
);
8540 while (!queue_empty(&fQueue
)) {
8541 if (dequeueCount
++ >= kMaxDequeueCount
) {
8542 // Allow other queues a chance to work
8547 queue_remove_first(&fQueue
, request
, typeof(request
), fCommandChain
);
8548 IOLockUnlock(fLock
);
8549 target
= request
->getTarget();
8551 more
|= (*dqAction
)( target
, request
, this );
8552 IOLockLock( fLock
);
8555 IOLockUnlock( fLock
);
8560 // MARK: IOPMWorkQueue
8562 //*********************************************************************************
8563 // IOPMWorkQueue Class
8565 // Queue of IOServicePM objects, each with a queue of IOPMRequest sharing the
8567 //*********************************************************************************
8569 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
8572 IOPMWorkQueue::create( IOService
* inOwner
, Action invoke
, Action retire
)
8574 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
8575 if (me
&& !me
->init(inOwner
, invoke
, retire
)) {
8583 IOPMWorkQueue::init( IOService
* inOwner
, Action invoke
, Action retire
)
8585 if (!invoke
|| !retire
||
8586 !IOEventSource::init(inOwner
, (IOEventSourceAction
)NULL
)) {
8590 queue_init(&fWorkQueue
);
8592 fInvokeAction
= invoke
;
8593 fRetireAction
= retire
;
8594 fConsumerCount
= fProducerCount
= 0;
8600 IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
8602 queue_head_t
* requestQueue
;
8608 assert( onThread());
8609 assert( queue_next(&request
->fCommandChain
) ==
8610 queue_prev(&request
->fCommandChain
));
8612 gIOPMBusyRequestCount
++;
8614 if (request
->isQuiesceType()) {
8615 if ((request
->getTarget() == gIOPMRootNode
) && !fQuiesceStartTime
) {
8616 // Attach new quiesce request to all quiesce blockers in the queue
8617 fQuiesceStartTime
= mach_absolute_time();
8618 attachQuiesceRequest(request
);
8619 fQuiesceRequest
= request
;
8621 } else if (fQuiesceRequest
&& request
->isQuiesceBlocker()) {
8622 // Attach the new quiesce blocker to the blocked quiesce request
8623 request
->attachNextRequest(fQuiesceRequest
);
8626 // Add new request to the tail of the per-service request queue.
8627 // Then immediately check the request queue to minimize latency
8628 // if the queue was empty.
8630 requestQueue
= &pwrMgt
->RequestHead
;
8631 empty
= queue_empty(requestQueue
);
8632 queue_enter(requestQueue
, request
, typeof(request
), fCommandChain
);
8634 more
= checkRequestQueue(requestQueue
, &empty
);
8636 // Request just added is blocked, add its target IOServicePM
8637 // to the work queue.
8638 assert( queue_next(&pwrMgt
->WorkChain
) ==
8639 queue_prev(&pwrMgt
->WorkChain
));
8641 queue_enter(&fWorkQueue
, pwrMgt
, typeof(pwrMgt
), WorkChain
);
8643 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8644 fQueueLength
, pwrMgt
->Name
, OBFUSCATE(pwrMgt
));
8652 IOPMWorkQueue::checkRequestQueue( queue_head_t
* requestQueue
, bool * empty
)
8654 IOPMRequest
* request
;
8659 assert(!queue_empty(requestQueue
));
8661 request
= (typeof(request
))queue_first(requestQueue
);
8662 if (request
->isWorkBlocked()) {
8663 break; // request dispatch blocked on attached request
8665 target
= request
->getTarget();
8666 if (fInvokeAction
) {
8667 done
= (*fInvokeAction
)( target
, request
, this );
8669 PM_LOG("PM request 0x%x dropped\n", request
->getType());
8673 break; // PM state machine blocked
8675 assert(gIOPMBusyRequestCount
> 0);
8676 if (gIOPMBusyRequestCount
) {
8677 gIOPMBusyRequestCount
--;
8680 if (request
== fQuiesceRequest
) {
8681 fQuiesceRequest
= NULL
;
8684 queue_remove_first(requestQueue
, request
, typeof(request
), fCommandChain
);
8685 more
|= (*fRetireAction
)( target
, request
, this );
8686 done
= queue_empty(requestQueue
);
8692 // Retired a request that may unblock a previously visited request
8693 // that is still waiting on the work queue. Must trigger another
8702 IOPMWorkQueue::checkForWork( void )
8704 IOServicePM
* entry
;
8709 #if WORK_QUEUE_STATS
8710 fStatCheckForWork
++;
8713 // Iterate over all IOServicePM entries in the work queue,
8714 // and check each entry's request queue.
8716 while (fConsumerCount
!= fProducerCount
) {
8717 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8718 fProducerCount
, fConsumerCount
);
8720 fConsumerCount
= fProducerCount
;
8722 #if WORK_QUEUE_STATS
8723 if (queue_empty(&fWorkQueue
)) {
8728 uint32_t cachedWorkCount
= gIOPMWorkInvokeCount
;
8731 __IGNORE_WCASTALIGN(entry
= (typeof(entry
))queue_first(&fWorkQueue
));
8732 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
)) {
8733 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
8735 // Get next entry, points to head if current entry is last.
8736 __IGNORE_WCASTALIGN(next
= (typeof(next
))queue_next(&entry
->WorkChain
));
8738 // if request queue is empty, remove IOServicePM from work queue.
8740 assert(fQueueLength
);
8744 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8745 fQueueLength
, entry
->Name
, OBFUSCATE(entry
));
8746 queue_remove(&fWorkQueue
, entry
, typeof(entry
), WorkChain
);
8751 #if WORK_QUEUE_STATS
8752 if (cachedWorkCount
== gIOPMWorkInvokeCount
) {
8762 IOPMWorkQueue::signalWorkAvailable( void )
8765 IOEventSource::signalWorkAvailable();
8769 IOPMWorkQueue::incrementProducerCount( void )
8775 IOPMWorkQueue::attachQuiesceRequest( IOPMRequest
* quiesceRequest
)
8777 IOServicePM
* entry
;
8778 IOPMRequest
* request
;
8780 if (queue_empty(&fWorkQueue
)) {
8784 queue_iterate(&fWorkQueue
, entry
, typeof(entry
), WorkChain
)
8786 queue_iterate(&entry
->RequestHead
, request
, typeof(request
), fCommandChain
)
8788 // Attach the quiesce request to any request in the queue that
8789 // is not linked to a next request. These requests will block
8790 // the quiesce request.
8792 if (request
->isQuiesceBlocker()) {
8793 request
->attachNextRequest(quiesceRequest
);
8800 IOPMWorkQueue::finishQuiesceRequest( IOPMRequest
* quiesceRequest
)
8802 if (fQuiesceRequest
&& (quiesceRequest
== fQuiesceRequest
) &&
8803 (fQuiesceStartTime
!= 0)) {
8804 fInvokeAction
= NULL
;
8805 fQuiesceFinishTime
= mach_absolute_time();
8810 // MARK: IOPMCompletionQueue
8812 //*********************************************************************************
8813 // IOPMCompletionQueue Class
8814 //*********************************************************************************
8816 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
8818 IOPMCompletionQueue
*
8819 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
8821 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
8822 if (me
&& !me
->init(inOwner
, inAction
)) {
8830 IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
8832 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
)) {
8836 queue_init(&fQueue
);
8841 IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
8846 // unblock dependent request
8847 more
= request
->detachNextRequest();
8848 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8853 IOPMCompletionQueue::checkForWork( void )
8855 Action dqAction
= (Action
) action
;
8856 IOPMRequest
* request
;
8861 request
= (typeof(request
))queue_first(&fQueue
);
8862 while (!queue_end(&fQueue
, (queue_entry_t
) request
)) {
8863 next
= (typeof(next
))queue_next(&request
->fCommandChain
);
8864 if (!request
->isFreeBlocked()) {
8865 queue_remove(&fQueue
, request
, typeof(request
), fCommandChain
);
8866 target
= request
->getTarget();
8868 more
|= (*dqAction
)( target
, request
, this );
8877 // MARK: IOServicePM
8879 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8881 //*********************************************************************************
8884 // Serialize IOServicePM for debugging.
8885 //*********************************************************************************
8888 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8890 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8892 dict
->setObject(key
, num
);
8898 IOServicePM::gatedSerialize( OSSerialize
* s
) const
8900 OSDictionary
* dict
;
8902 int powerClamp
= -1;
8905 if (IdleTimerPeriod
) {
8909 if (PMActions
.state
& kPMActionsStatePowerClamped
) {
8912 if (PMActions
.flags
&
8913 (kPMActionsFlagIsDisplayWrangler
| kPMActionsFlagIsGraphicsDriver
)) {
8918 #if WORK_QUEUE_STATS
8919 if (gIOPMRootNode
== ControllingDriver
) {
8925 dict
= OSDictionary::withDictionary(
8926 PowerClients
, PowerClients
->getCount() + dictSize
);
8928 dict
= OSDictionary::withCapacity(dictSize
);
8932 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8933 setPMProperty(dict
, "CapabilityFlags", CurrentCapabilityFlags
);
8934 if (NumberOfPowerStates
) {
8935 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
- 1);
8937 if (DesiredPowerState
!= CurrentPowerState
) {
8938 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8940 if (kIOPM_Finished
!= MachineState
) {
8941 setPMProperty(dict
, "MachineState", MachineState
);
8943 if (DeviceOverrideEnabled
) {
8944 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8946 if (powerClamp
>= 0) {
8947 setPMProperty(dict
, "PowerClamp", powerClamp
);
8950 if (IdleTimerPeriod
) {
8955 clock_get_uptime(&now
);
8957 // The idle timer period in milliseconds
8958 setPMProperty(dict
, "IdleTimerPeriod", NextIdleTimerPeriod
* 1000ULL);
8960 // Number of tickles since the last idle timer expiration
8961 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8963 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
)) {
8964 // Milliseconds since the last activity tickle
8966 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8967 absolutetime_to_nanoseconds(delta
, &nsecs
);
8968 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
8971 if (!IdleTimerStopped
&& AbsoluteTime_to_scalar(&IdleTimerStartTime
)) {
8972 // Idle timer elapsed time in milliseconds
8974 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
8975 absolutetime_to_nanoseconds(delta
, &nsecs
);
8976 setPMProperty(dict
, "IdleTimerElapsedTime", NS_TO_MS(nsecs
));
8980 #if WORK_QUEUE_STATS
8981 if (gIOPMRootNode
== Owner
) {
8982 setPMProperty(dict
, "WQ-CheckForWork",
8983 gIOPMWorkQueue
->fStatCheckForWork
);
8984 setPMProperty(dict
, "WQ-ScanEntries",
8985 gIOPMWorkQueue
->fStatScanEntries
);
8986 setPMProperty(dict
, "WQ-QueueEmpty",
8987 gIOPMWorkQueue
->fStatQueueEmpty
);
8988 setPMProperty(dict
, "WQ-NoWorkDone",
8989 gIOPMWorkQueue
->fStatNoWorkDone
);
8993 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
) {
8994 // Don't report advisory tickle when it has no influence
8995 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
8998 ok
= dict
->serialize(s
);
9002 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;
9006 IOServicePM::serialize( OSSerialize
* s
) const
9008 IOReturn ret
= kIOReturnNotReady
;
9010 if (gIOPMWatchDogThread
== current_thread()) {
9011 // Calling without lock as this data is collected for debug purpose, before reboot.
9012 // The workloop is probably already hung in state machine.
9013 ret
= gatedSerialize(s
);
9014 } else if (gIOPMWorkLoop
) {
9015 ret
= gIOPMWorkLoop
->runAction(
9016 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
9017 (OSObject
*) this, (void *) s
);
9020 return kIOReturnSuccess
== ret
;
9024 IOServicePM::pmPrint(
9027 uintptr_t param2
) const
9029 gPlatform
->PMLog(Name
, event
, param1
, param2
);
9033 IOServicePM::pmTrace(
9037 uintptr_t param2
) const
9039 uintptr_t nameAsArg
= 0;
9041 assert(event
< KDBG_CODE_MAX
);
9042 assert((eventFunc
& ~KDBG_FUNC_MASK
) == 0);
9044 // Copy the first characters of the name into an uintptr_t.
9045 // NULL termination is not required.
9046 strncpy((char*)&nameAsArg
, Name
, sizeof(nameAsArg
));
9048 #if defined(XNU_TARGET_OS_OSX)
9049 KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE
, IODBG_POWER(event
) | eventFunc
, nameAsArg
,
9050 (uintptr_t)Owner
->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1
)),
9051 (uintptr_t)(OBFUSCATE(param2
)), 0);
9053 IOTimeStampConstant(IODBG_POWER(event
) | eventFunc
, nameAsArg
, (uintptr_t)Owner
->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1
)), (uintptr_t)(OBFUSCATE(param2
)));