2 * Copyright (c) 1998-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/assert.h>
30 #include <IOKit/IOKitDebug.h>
31 #include <IOKit/IOLib.h>
32 #include <IOKit/IOMessage.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IOEventSource.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/IOCommand.h>
38 #include <IOKit/IOTimeStamp.h>
39 #include <IOKit/IOReportMacros.h>
40 #include <IOKit/IODeviceTreeSupport.h>
42 #include <IOKit/pwr_mgt/IOPMlog.h>
43 #include <IOKit/pwr_mgt/IOPMinformee.h>
44 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
45 #include <IOKit/pwr_mgt/IOPowerConnection.h>
46 #include <IOKit/pwr_mgt/RootDomain.h>
47 #include <IOKit/pwr_mgt/IOPMPrivate.h>
50 #include <sys/proc_internal.h>
51 #include <sys/sysctl.h>
52 #include <libkern/OSDebug.h>
53 #include <kern/thread.h>
55 // Required for notification instrumentation
56 #include "IOServicePrivate.h"
57 #include "IOServicePMPrivate.h"
58 #include "IOKitKernelInternal.h"
61 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
62 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
63 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
64 static void tellAppClientApplier(OSObject
* object
, void * arg
);
67 computeTimeDeltaNS( const AbsoluteTime
* start
)
72 clock_get_uptime(&now
);
73 SUB_ABSOLUTETIME(&now
, start
);
74 absolutetime_to_nanoseconds(now
, &nsec
);
79 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
82 //******************************************************************************
84 //******************************************************************************
86 static bool gIOPMInitialized
= false;
87 static uint32_t gIOPMBusyRequestCount
= 0;
88 static uint32_t gIOPMWorkInvokeCount
= 0;
89 static uint32_t gIOPMTickleGeneration
= 0;
90 static IOWorkLoop
* gIOPMWorkLoop
= NULL
;
91 static IOPMRequestQueue
* gIOPMRequestQueue
= NULL
;
92 static IOPMRequestQueue
* gIOPMReplyQueue
= NULL
;
93 static IOPMWorkQueue
* gIOPMWorkQueue
= NULL
;
94 static IOPMCompletionQueue
* gIOPMCompletionQueue
= NULL
;
95 static IOPMRequest
* gIOPMRequest
= NULL
;
96 static IOService
* gIOPMRootNode
= NULL
;
97 static IOPlatformExpert
* gPlatform
= NULL
;
100 const OSSymbol
* gIOPMPowerClientDevice
= NULL
;
101 const OSSymbol
* gIOPMPowerClientDriver
= NULL
;
102 const OSSymbol
* gIOPMPowerClientChildProxy
= NULL
;
103 const OSSymbol
* gIOPMPowerClientChildren
= NULL
;
104 const OSSymbol
* gIOPMPowerClientRootDomain
= NULL
;
106 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= NULL
;
107 static bool gIOPMAdvisoryTickleEnabled
= true;
108 static thread_t gIOPMWatchDogThread
= NULL
;
109 uint32_t gCanSleepTimeout
= 0;
112 getPMRequestType( void )
114 uint32_t type
= kIOPMRequestTypeInvalid
;
116 type
= gIOPMRequest
->getType();
121 static IOPMRequestTag
122 getPMRequestTag( void )
124 IOPMRequestTag tag
= 0;
126 (gIOPMRequest
->getType() == kIOPMRequestTypeRequestPowerStateOverride
)) {
127 tag
= gIOPMRequest
->fRequestTag
;
132 SYSCTL_UINT(_kern
, OID_AUTO
, pmtimeout
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &gCanSleepTimeout
, 0, "Power Management Timeout");
134 //******************************************************************************
136 //******************************************************************************
138 #define PM_ERROR(x...) do { kprintf(x);IOLog(x); \
140 #define PM_LOG(x...) do { kprintf(x); } while (false)
142 #define PM_LOG1(x...) do { \
143 if (kIOLogDebugPower & gIOKitDebug) \
144 kprintf(x); } while (false)
146 #define PM_LOG2(x...) do { \
147 if (kIOLogDebugPower & gIOKitDebug) \
148 kprintf(x); } while (false)
151 #define PM_LOG3(x...) do { kprintf(x); } while (false)
153 #define PM_LOG3(x...)
156 #define RD_LOG(x...) do { \
157 if ((kIOLogPMRootDomain & gIOKitDebug) && \
158 (getPMRootDomain() == this)) { \
159 kprintf("PMRD: " x); \
161 #define PM_ASSERT_IN_GATE(x) \
163 assert(gIOPMWorkLoop->inGate()); \
166 #define PM_LOCK() IOLockLock(fPMLock)
167 #define PM_UNLOCK() IOLockUnlock(fPMLock)
168 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
169 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
171 #define us_per_s 1000000
172 #define ns_per_us 1000
173 #define k30Seconds (30*us_per_s)
174 #define k5Seconds ( 5*us_per_s)
176 #define kCanSleepMaxTimeReq k5Seconds
178 #define kCanSleepMaxTimeReq k30Seconds
180 #define kMaxTimeRequested k30Seconds
181 #define kMinAckTimeoutTicks (10*1000000)
182 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
183 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
184 #define kPwrMgtKey "IOPowerManagement"
186 #define OUR_PMLog(t, a, b) do { \
188 if (gIOKitDebug & kIOLogPower) \
189 pwrMgt->pmPrint(t, a, b); \
190 if (gIOKitTrace & kIOTracePowerMgmt) \
191 pwrMgt->pmTrace(t, DBG_FUNC_NONE, a, b); \
195 #define OUR_PMLogFuncStart(t, a, b) do { \
197 if (gIOKitDebug & kIOLogPower) \
198 pwrMgt->pmPrint(t, a, b); \
199 if (gIOKitTrace & kIOTracePowerMgmt) \
200 pwrMgt->pmTrace(t, DBG_FUNC_START, a, b); \
204 #define OUR_PMLogFuncEnd(t, a, b) do { \
206 if (gIOKitDebug & kIOLogPower) \
207 pwrMgt->pmPrint(-t, a, b); \
208 if (gIOKitTrace & kIOTracePowerMgmt) \
209 pwrMgt->pmTrace(t, DBG_FUNC_END, a, b); \
213 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
214 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
216 #define SUPPORT_IDLE_CANCEL 1
218 #define kIOPMPowerStateMax 0xFFFFFFFF
219 #define kInvalidTicklePowerState kIOPMPowerStateMax
221 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
223 #define IS_PM_ROOT (this == gIOPMRootNode)
224 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
225 #define IS_POWER_DROP (StateOrder(fHeadNotePowerState) < StateOrder(fCurrentPowerState))
226 #define IS_POWER_RISE (StateOrder(fHeadNotePowerState) > StateOrder(fCurrentPowerState))
228 // log setPowerStates longer than (ns):
229 #if defined(__i386__) || defined(__x86_64__)
230 #define LOG_SETPOWER_TIMES (300ULL * 1000ULL * 1000ULL)
232 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
234 // log app responses longer than (ns):
235 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
236 // use message tracer to log messages longer than (ns):
237 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
239 // log kext responses longer than (ns):
240 #define LOG_KEXT_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
243 kReserveDomainPower
= 1
247 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
248 assert(kIOPM_BadMachineState != n); \
249 fSavedMachineState = n; } while (false)
252 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
253 fMachineState = fSavedMachineState; \
254 fSavedMachineState = kIOPM_BadMachineState; } while (false)
256 #define PM_ACTION_0(a) \
257 do { if (fPMActions.a) { \
258 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
261 #define PM_ACTION_2(a, x, y) \
262 do { if (fPMActions.a) { \
263 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, \
264 getPMRequestTag()); } \
267 #define PM_ACTION_3(a, x, y, z) \
268 do { if (fPMActions.a) { \
269 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, z); } \
272 static OSNumber
* copyClientIDForNotification(
274 IOPMInterestContext
*context
);
276 static void logClientIDForNotification(
278 IOPMInterestContext
*context
,
279 const char *logString
);
281 //*********************************************************************************
284 // Check kgmacros after modifying machine states.
285 //*********************************************************************************
290 kIOPM_OurChangeTellClientsPowerDown
= 1,
291 kIOPM_OurChangeTellUserPMPolicyPowerDown
= 2,
292 kIOPM_OurChangeTellPriorityClientsPowerDown
= 3,
293 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 4,
294 kIOPM_OurChangeSetPowerState
= 5,
295 kIOPM_OurChangeWaitForPowerSettle
= 6,
296 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 7,
297 kIOPM_OurChangeTellCapabilityDidChange
= 8,
298 kIOPM_OurChangeFinish
= 9,
300 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
301 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
302 kIOPM_ParentChangeSetPowerState
= 12,
303 kIOPM_ParentChangeWaitForPowerSettle
= 13,
304 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
305 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
306 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
308 kIOPM_NotifyChildrenStart
= 17,
309 kIOPM_NotifyChildrenOrdered
= 18,
310 kIOPM_NotifyChildrenDelayed
= 19,
311 kIOPM_SyncTellClientsPowerDown
= 20,
312 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
313 kIOPM_SyncNotifyWillChange
= 22,
314 kIOPM_SyncNotifyDidChange
= 23,
315 kIOPM_SyncTellCapabilityDidChange
= 24,
316 kIOPM_SyncFinish
= 25,
317 kIOPM_TellCapabilityChangeDone
= 26,
318 kIOPM_DriverThreadCallDone
= 27,
320 kIOPM_BadMachineState
= 0xFFFFFFFF
323 //*********************************************************************************
326 // Initialize power management.
327 //*********************************************************************************
330 IOService::PMinit( void )
333 if (!gIOPMInitialized
) {
334 gPlatform
= getPlatform();
335 gIOPMWorkLoop
= IOWorkLoop::workLoop();
337 gIOPMRequestQueue
= IOPMRequestQueue::create(
338 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
339 this, &IOService::actionPMRequestQueue
));
341 gIOPMReplyQueue
= IOPMRequestQueue::create(
342 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
343 this, &IOService::actionPMReplyQueue
));
345 gIOPMWorkQueue
= IOPMWorkQueue::create(this,
346 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
347 &IOService::actionPMWorkQueueInvoke
),
348 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
349 &IOService::actionPMWorkQueueRetire
));
351 gIOPMCompletionQueue
= IOPMCompletionQueue::create(
352 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
353 this, &IOService::actionPMCompletionQueue
));
355 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
357 gIOPMRequestQueue
->release();
358 gIOPMRequestQueue
= NULL
;
361 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
363 gIOPMReplyQueue
->release();
364 gIOPMReplyQueue
= NULL
;
367 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
369 gIOPMWorkQueue
->release();
370 gIOPMWorkQueue
= NULL
;
373 // Must be added after the work queue, which pushes request
374 // to the completion queue without signaling the work loop.
375 if (gIOPMWorkLoop
->addEventSource(gIOPMCompletionQueue
) !=
377 gIOPMCompletionQueue
->release();
378 gIOPMCompletionQueue
= NULL
;
381 gIOPMPowerClientDevice
=
382 OSSymbol::withCStringNoCopy( "DevicePowerState" );
384 gIOPMPowerClientDriver
=
385 OSSymbol::withCStringNoCopy( "DriverPowerState" );
387 gIOPMPowerClientChildProxy
=
388 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
390 gIOPMPowerClientChildren
=
391 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
393 gIOPMPowerClientAdvisoryTickle
=
394 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
396 gIOPMPowerClientRootDomain
=
397 OSSymbol::withCStringNoCopy( "RootDomainPower" );
400 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMCompletionQueue
) {
401 gIOPMInitialized
= true;
404 if (!gIOPMInitialized
) {
408 pwrMgt
= new IOServicePM
;
410 setProperty(kPwrMgtKey
, pwrMgt
);
412 queue_init(&pwrMgt
->WorkChain
);
413 queue_init(&pwrMgt
->RequestHead
);
414 queue_init(&pwrMgt
->PMDriverCallQueue
);
417 fPMLock
= IOLockAlloc();
418 fInterestedDrivers
= new IOPMinformeeList
;
419 fInterestedDrivers
->initialize();
420 fDesiredPowerState
= kPowerStateZero
;
421 fDeviceDesire
= kPowerStateZero
;
422 fInitialPowerChange
= true;
423 fInitialSetPowerState
= true;
424 fPreviousRequestPowerFlags
= 0;
425 fDeviceOverrideEnabled
= false;
426 fMachineState
= kIOPM_Finished
;
427 fSavedMachineState
= kIOPM_BadMachineState
;
428 fIdleTimerMinPowerState
= kPowerStateZero
;
429 fActivityLock
= IOLockAlloc();
430 fStrictTreeOrder
= false;
431 fActivityTicklePowerState
= kInvalidTicklePowerState
;
432 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
433 fControllingDriver
= NULL
;
435 fNumberOfPowerStates
= 0;
436 fCurrentPowerState
= kPowerStateZero
;
437 fParentsCurrentPowerFlags
= 0;
438 fMaxPowerState
= kPowerStateZero
;
440 fParentsKnowState
= false;
442 fResponseArray
= NULL
;
443 fNotifyClientArray
= NULL
;
444 fCurrentPowerConsumption
= kIOPMUnknown
;
445 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
447 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot())) {
448 gIOPMRootNode
= this;
449 fParentsKnowState
= true;
450 } else if (getProperty(kIOPMResetPowerStateOnWakeKey
) == kOSBooleanTrue
) {
451 fResetPowerStateOnWake
= true;
454 if (IS_ROOT_DOMAIN
) {
455 fWatchdogTimer
= thread_call_allocate(
456 &IOService::watchdog_timer_expired
, (thread_call_param_t
)this);
457 fWatchdogLock
= IOLockAlloc();
459 fBlockedArray
= OSArray::withCapacity(4);
462 fAckTimer
= thread_call_allocate(
463 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
464 fSettleTimer
= thread_call_allocate(
465 &settle_timer_expired
, (thread_call_param_t
)this);
466 fIdleTimer
= thread_call_allocate(
467 &idle_timer_expired
, (thread_call_param_t
)this);
468 fDriverCallEntry
= thread_call_allocate(
469 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
470 assert(fDriverCallEntry
);
472 // Check for powerChangeDone override.
473 if (OSMemberFunctionCast(void (*)(void),
474 getResourceService(), &IOService::powerChangeDone
) !=
475 OSMemberFunctionCast(void (*)(void),
476 this, &IOService::powerChangeDone
)) {
477 fPCDFunctionOverride
= true;
481 IOPMprot
* prot
= new IOPMprot
;
484 prot
->ourName
= fName
;
485 prot
->thePlatform
= gPlatform
;
490 pm_vars
= (void *) (uintptr_t) true;
497 //*********************************************************************************
500 // Free the data created by PMinit. Only called from IOService::free().
501 //*********************************************************************************
504 IOService::PMfree( void )
510 assert(fMachineState
== kIOPM_Finished
);
511 assert(fInsertInterestSet
== NULL
);
512 assert(fRemoveInterestSet
== NULL
);
513 assert(fNotifyChildArray
== NULL
);
514 assert(queue_empty(&pwrMgt
->RequestHead
));
515 assert(queue_empty(&fPMDriverCallQueue
));
517 if (fWatchdogTimer
) {
518 thread_call_cancel(fWatchdogTimer
);
519 thread_call_free(fWatchdogTimer
);
520 fWatchdogTimer
= NULL
;
524 IOLockFree(fWatchdogLock
);
525 fWatchdogLock
= NULL
;
529 fBlockedArray
->release();
530 fBlockedArray
= NULL
;
534 thread_call_cancel(fSettleTimer
);
535 thread_call_free(fSettleTimer
);
539 thread_call_cancel(fAckTimer
);
540 thread_call_free(fAckTimer
);
544 thread_call_cancel(fIdleTimer
);
545 thread_call_free(fIdleTimer
);
548 if (fDriverCallEntry
) {
549 thread_call_free(fDriverCallEntry
);
550 fDriverCallEntry
= NULL
;
557 IOLockFree(fActivityLock
);
558 fActivityLock
= NULL
;
560 if (fInterestedDrivers
) {
561 fInterestedDrivers
->release();
562 fInterestedDrivers
= NULL
;
564 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
565 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
566 fDriverCallParamPtr
= NULL
;
567 fDriverCallParamSlots
= 0;
569 if (fResponseArray
) {
570 fResponseArray
->release();
571 fResponseArray
= NULL
;
573 if (fNotifyClientArray
) {
574 fNotifyClientArray
->release();
575 fNotifyClientArray
= NULL
;
577 if (fPowerStates
&& fNumberOfPowerStates
) {
578 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
579 fNumberOfPowerStates
= 0;
583 fPowerClients
->release();
584 fPowerClients
= NULL
;
600 IOService::PMDebug( uint32_t event
, uintptr_t param1
, uintptr_t param2
)
602 OUR_PMLog(event
, param1
, param2
);
605 //*********************************************************************************
606 // [public] joinPMtree
608 // A policy-maker calls its nub here when initializing, to be attached into
609 // the power management hierarchy. The default function is to call the
610 // platform expert, which knows how to do it. This method is overridden
611 // by a nub subclass which may either know how to do it, or may need to
612 // take other action.
614 // This may be the only "power management" method used in a nub,
615 // meaning it may not be initialized for power management.
616 //*********************************************************************************
619 IOService::joinPMtree( IOService
* driver
)
621 IOPlatformExpert
* platform
;
623 platform
= getPlatform();
624 assert(platform
!= NULL
);
625 platform
->PMRegisterDevice(this, driver
);
629 //*********************************************************************************
630 // [deprecated] youAreRoot
632 // Power Managment is informing us that we are the root power domain.
633 //*********************************************************************************
636 IOService::youAreRoot( void )
640 #endif /* !__LP64__ */
642 //*********************************************************************************
645 // Immediately stop driver callouts. Schedule an async stop request to detach
647 //*********************************************************************************
650 IOService::PMstop( void )
652 IOPMRequest
* request
;
660 if (fLockedFlags
.PMStop
) {
661 PM_LOG2("%s: PMstop() already stopped\n", fName
);
666 // Inhibit future driver calls.
667 fLockedFlags
.PMStop
= true;
669 // Wait for all prior driver calls to finish.
670 waitForPMDriverCall();
674 // The rest of the work is performed async.
675 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
677 PM_LOG2("%s: %p PMstop\n", getName(), OBFUSCATE(this));
678 submitPMRequest( request
);
682 //*********************************************************************************
683 // [private] handlePMstop
685 // Disconnect the node from all parents and children in the power plane.
686 //*********************************************************************************
689 IOService::handlePMstop( IOPMRequest
* request
)
693 IOPowerConnection
* connection
;
694 IOService
* theChild
;
695 IOService
* theParent
;
698 PM_LOG2("%s: %p %s start\n", getName(), OBFUSCATE(this), __FUNCTION__
);
700 // remove driver from prevent system sleep lists
701 getPMRootDomain()->updatePreventIdleSleepList(this, false);
702 getPMRootDomain()->updatePreventSystemSleepList(this, false);
704 // remove the property
705 removeProperty(kPwrMgtKey
);
708 iter
= getParentIterator(gIOPowerPlane
);
710 while ((next
= iter
->getNextObject())) {
711 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
712 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
714 theParent
->removePowerChild(connection
);
715 theParent
->release();
722 // detach IOConnections
723 detachAbove( gIOPowerPlane
);
725 // no more power state changes
726 fParentsKnowState
= false;
729 iter
= getChildIterator(gIOPowerPlane
);
731 while ((next
= iter
->getNextObject())) {
732 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
733 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
735 // detach nub from child
736 connection
->detachFromChild(theChild
, gIOPowerPlane
);
739 // detach us from nub
740 detachFromChild(connection
, gIOPowerPlane
);
746 // Remove all interested drivers from the list, including the power
747 // controlling driver.
749 // Usually, the controlling driver and the policy-maker functionality
750 // are implemented by the same object, and without the deregistration,
751 // the object will be holding an extra retain on itself, and cannot
754 if (fInterestedDrivers
) {
755 IOPMinformeeList
* list
= fInterestedDrivers
;
759 while ((item
= list
->firstInList())) {
760 list
->removeFromList(item
->whatObject
);
765 // Clear idle period to prevent idleTimerExpired() from servicing
766 // idle timer expirations.
768 fIdleTimerPeriod
= 0;
769 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
)) {
773 PM_LOG2("%s: %p %s done\n", getName(), OBFUSCATE(this), __FUNCTION__
);
776 //*********************************************************************************
777 // [public] addPowerChild
779 // Power Management is informing us who our children are.
780 //*********************************************************************************
783 IOService::addPowerChild( IOService
* child
)
785 IOPowerConnection
* connection
= NULL
;
786 IOPMRequest
* requests
[3] = {NULL
, NULL
, NULL
};
791 return kIOReturnBadArgument
;
794 if (!initialized
|| !child
->initialized
) {
795 return IOPMNotYetInitialized
;
798 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
801 // Is this child already one of our children?
803 iter
= child
->getParentIterator( gIOPowerPlane
);
805 IORegistryEntry
* entry
;
808 while ((next
= iter
->getNextObject())) {
809 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
810 isChild(entry
, gIOPowerPlane
)) {
818 PM_LOG2("%s: %s (%p) is already a child\n",
819 getName(), child
->getName(), OBFUSCATE(child
));
823 // Add the child to the power plane immediately, but the
824 // joining connection is marked as not ready.
825 // We want the child to appear in the power plane before
826 // returning to the caller, but don't want the caller to
827 // block on the PM work loop.
829 connection
= new IOPowerConnection
;
834 // Create a chain of PM requests to perform the bottom-half
835 // work from the PM work loop.
837 requests
[0] = acquirePMRequest(
839 /* type */ kIOPMRequestTypeAddPowerChild1
);
841 requests
[1] = acquirePMRequest(
843 /* type */ kIOPMRequestTypeAddPowerChild2
);
845 requests
[2] = acquirePMRequest(
847 /* type */ kIOPMRequestTypeAddPowerChild3
);
849 if (!requests
[0] || !requests
[1] || !requests
[2]) {
853 requests
[0]->attachNextRequest( requests
[1] );
854 requests
[1]->attachNextRequest( requests
[2] );
857 connection
->start(this);
858 connection
->setAwaitingAck(false);
859 connection
->setReadyFlag(false);
861 attachToChild( connection
, gIOPowerPlane
);
862 connection
->attachToChild( child
, gIOPowerPlane
);
864 // connection needs to be released
865 requests
[0]->fArg0
= connection
;
866 requests
[1]->fArg0
= connection
;
867 requests
[2]->fArg0
= connection
;
869 submitPMRequests( requests
, 3 );
870 return kIOReturnSuccess
;
874 connection
->release();
877 releasePMRequest(requests
[0]);
880 releasePMRequest(requests
[1]);
883 releasePMRequest(requests
[2]);
886 // Silent failure, to prevent platform drivers from adding the child
887 // to the root domain.
889 return kIOReturnSuccess
;
892 //*********************************************************************************
893 // [private] addPowerChild1
895 // Step 1/3 of adding a power child. Called on the power parent.
896 //*********************************************************************************
899 IOService::addPowerChild1( IOPMRequest
* request
)
901 IOPMPowerStateIndex tempDesire
= kPowerStateZero
;
903 // Make us temporary usable before adding the child.
906 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
908 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
) {
909 tempDesire
= fHighestPowerState
;
912 if ((tempDesire
!= kPowerStateZero
) &&
913 (IS_PM_ROOT
|| (StateOrder(fMaxPowerState
) >= StateOrder(tempDesire
)))) {
914 adjustPowerState(tempDesire
);
918 //*********************************************************************************
919 // [private] addPowerChild2
921 // Step 2/3 of adding a power child. Called on the joining child.
922 // Execution blocked behind addPowerChild1.
923 //*********************************************************************************
926 IOService::addPowerChild2( IOPMRequest
* request
)
928 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
930 IOPMPowerFlags powerFlags
;
932 unsigned long powerState
;
933 unsigned long tempDesire
;
936 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
938 if (!parent
|| !inPlane(gIOPowerPlane
)) {
939 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
943 // Parent will be waiting for us to complete this stage.
944 // It is safe to directly access parent's vars.
946 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
947 powerState
= parent
->fCurrentPowerState
;
950 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
955 // Set our power parent.
957 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
959 setParentInfo( powerFlags
, connection
, knowsState
);
961 connection
->setReadyFlag(true);
963 if (fControllingDriver
&& fParentsKnowState
) {
964 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
965 // initially change into the state we are already in
966 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
967 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
968 adjustPowerState(tempDesire
);
971 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
974 //*********************************************************************************
975 // [private] addPowerChild3
977 // Step 3/3 of adding a power child. Called on the parent.
978 // Execution blocked behind addPowerChild2.
979 //*********************************************************************************
982 IOService::addPowerChild3( IOPMRequest
* request
)
984 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
986 IOPMrootDomain
* rootDomain
= getPMRootDomain();
989 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
991 if (child
&& inPlane(gIOPowerPlane
)) {
992 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder")) {
993 PM_LOG1("%s: strict PM order enforced\n", getName());
994 fStrictTreeOrder
= true;
998 rootDomain
->joinAggressiveness( child
);
1001 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1004 connection
->release();
1008 //*********************************************************************************
1009 // [deprecated] setPowerParent
1011 // Power Management is informing us who our parent is.
1012 // If we have a controlling driver, find out, given our newly-informed
1013 // power domain state, what state it would be in, and then tell it
1014 // to assume that state.
1015 //*********************************************************************************
1018 IOService::setPowerParent(
1019 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
1021 return kIOReturnUnsupported
;
1023 #endif /* !__LP64__ */
1025 //*********************************************************************************
1026 // [public] removePowerChild
1028 // Called on a parent whose child is being removed by PMstop().
1029 //*********************************************************************************
1032 IOService::removePowerChild( IOPowerConnection
* theNub
)
1034 IORegistryEntry
* theChild
;
1036 PM_ASSERT_IN_GATE();
1037 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1041 // detach nub from child
1042 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1044 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1045 theChild
->release();
1047 // detach from the nub
1048 detachFromChild(theNub
, gIOPowerPlane
);
1050 // Are we awaiting an ack from this child?
1051 if (theNub
->getAwaitingAck()) {
1052 // yes, pretend we got one
1053 theNub
->setAwaitingAck(false);
1054 if (fHeadNotePendingAcks
!= 0) {
1055 // that's one fewer ack to worry about
1056 fHeadNotePendingAcks
--;
1058 // is that the last?
1059 if (fHeadNotePendingAcks
== 0) {
1061 getPMRootDomain()->reset_watchdog_timer(this, 0);
1063 // This parent may have a request in the work queue that is
1064 // blocked on fHeadNotePendingAcks=0. And removePowerChild()
1065 // is called while executing the child's PMstop request so they
1066 // can occur simultaneously. IOPMWorkQueue::checkForWork() must
1067 // restart and check all request queues again.
1069 gIOPMWorkQueue
->incrementProducerCount();
1076 // A child has gone away, re-scan children desires and clamp bits.
1077 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1079 if (!fAdjustPowerScheduled
) {
1080 IOPMRequest
* request
;
1081 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1083 submitPMRequest( request
);
1084 fAdjustPowerScheduled
= true;
1091 //*********************************************************************************
1092 // [public] registerPowerDriver
1094 // A driver has called us volunteering to control power to our device.
1095 //*********************************************************************************
1098 IOService::registerPowerDriver(
1099 IOService
* powerDriver
,
1100 IOPMPowerState
* powerStates
,
1101 unsigned long numberOfStates
)
1103 IOPMRequest
* request
;
1104 IOPMPSEntry
* powerStatesCopy
= NULL
;
1105 IOPMPowerStateIndex stateOrder
;
1106 IOReturn error
= kIOReturnSuccess
;
1109 return IOPMNotYetInitialized
;
1112 if (!powerStates
|| (numberOfStates
< 2)) {
1113 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1114 return kIOReturnBadArgument
;
1117 if (!powerDriver
|| !powerDriver
->initialized
) {
1118 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1119 return kIOReturnBadArgument
;
1122 if (powerStates
[0].version
> kIOPMPowerStateVersion2
) {
1123 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1124 return kIOReturnBadArgument
;
1128 // Make a copy of the supplied power state array.
1129 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1130 if (!powerStatesCopy
) {
1131 error
= kIOReturnNoMemory
;
1135 // Initialize to bogus values
1136 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++) {
1137 powerStatesCopy
[i
].stateOrderToIndex
= kIOPMPowerStateMax
;
1140 for (uint32_t i
= 0; i
< numberOfStates
; i
++) {
1141 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1142 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1143 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1144 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1145 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1146 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1147 if (powerStates
[i
].version
>= kIOPMPowerStateVersion2
) {
1148 stateOrder
= powerStates
[i
].stateOrder
;
1153 if (stateOrder
< numberOfStates
) {
1154 powerStatesCopy
[i
].stateOrder
= stateOrder
;
1155 powerStatesCopy
[stateOrder
].stateOrderToIndex
= i
;
1159 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++) {
1160 if (powerStatesCopy
[i
].stateOrderToIndex
== kIOPMPowerStateMax
) {
1161 // power state order missing
1162 error
= kIOReturnBadArgument
;
1166 if (kIOReturnSuccess
!= error
) {
1170 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1172 error
= kIOReturnNoMemory
;
1176 powerDriver
->retain();
1177 request
->fArg0
= (void *) powerDriver
;
1178 request
->fArg1
= (void *) powerStatesCopy
;
1179 request
->fArg2
= (void *) numberOfStates
;
1181 submitPMRequest( request
);
1182 return kIOReturnSuccess
;
1185 if (powerStatesCopy
) {
1186 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1192 //*********************************************************************************
1193 // [private] handleRegisterPowerDriver
1194 //*********************************************************************************
1197 IOService::handleRegisterPowerDriver( IOPMRequest
* request
)
1199 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1200 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1201 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1202 unsigned long i
, stateIndex
;
1203 unsigned long lowestPowerState
;
1207 PM_ASSERT_IN_GATE();
1208 assert(powerStates
);
1209 assert(powerDriver
);
1210 assert(numberOfStates
> 1);
1212 if (!fNumberOfPowerStates
) {
1213 OUR_PMLog(kPMLogControllingDriver
,
1214 (unsigned long) numberOfStates
,
1215 (unsigned long) kIOPMPowerStateVersion1
);
1217 fPowerStates
= powerStates
;
1218 fNumberOfPowerStates
= numberOfStates
;
1219 fControllingDriver
= powerDriver
;
1220 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1222 lowestPowerState
= fPowerStates
[0].stateOrderToIndex
;
1223 fHighestPowerState
= fPowerStates
[numberOfStates
- 1].stateOrderToIndex
;
1225 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
1228 IOService
* service
;
1232 // Disallow kIOPMAOTPower states unless device tree enabled
1236 while (service
&& !service
->inPlane(gIODTPlane
)) {
1237 service
= service
->getProvider();
1240 object
= service
->copyProperty(kIOPMAOTPowerKey
, gIODTPlane
);
1241 data
= OSDynamicCast(OSData
, object
);
1242 if (data
&& (data
->getLength() >= sizeof(uint32_t))) {
1243 aotFlags
= ((uint32_t *)data
->getBytesNoCopy())[0];
1245 OSSafeReleaseNULL(object
);
1248 for (i
= 0; i
< numberOfStates
; i
++) {
1249 if (kIOPMAOTPower
& fPowerStates
[i
].inputPowerFlags
) {
1250 fPowerStates
[i
].inputPowerFlags
= 0xFFFFFFFF;
1251 fPowerStates
[i
].capabilityFlags
= 0;
1252 fPowerStates
[i
].outputPowerFlags
= 0;
1257 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
1259 // OR'in all the output power flags
1260 fMergedOutputPowerFlags
= 0;
1261 fDeviceUsablePowerState
= lowestPowerState
;
1262 for (i
= 0; i
< numberOfStates
; i
++) {
1263 fMergedOutputPowerFlags
|= fPowerStates
[i
].outputPowerFlags
;
1265 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
1266 assert(stateIndex
< numberOfStates
);
1267 if ((fDeviceUsablePowerState
== lowestPowerState
) &&
1268 (fPowerStates
[stateIndex
].capabilityFlags
& IOPMDeviceUsable
)) {
1269 // The minimum power state that the device is usable
1270 fDeviceUsablePowerState
= stateIndex
;
1274 // Register powerDriver as interested, unless already done.
1275 // We don't want to register the default implementation since
1276 // it does nothing. One ramification of not always registering
1277 // is the one fewer retain count held.
1279 root
= getPlatform()->getProvider();
1282 ((OSMemberFunctionCast(void (*)(void),
1283 root
, &IOService::powerStateDidChangeTo
)) !=
1284 ((OSMemberFunctionCast(void (*)(void),
1285 this, &IOService::powerStateDidChangeTo
)))) ||
1286 ((OSMemberFunctionCast(void (*)(void),
1287 root
, &IOService::powerStateWillChangeTo
)) !=
1288 ((OSMemberFunctionCast(void (*)(void),
1289 this, &IOService::powerStateWillChangeTo
))))) {
1290 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
) {
1292 fInterestedDrivers
->appendNewInformee(powerDriver
);
1297 // Examine all existing power clients and perform limit check.
1299 if (fPowerClients
&&
1300 (iter
= OSCollectionIterator::withCollection(fPowerClients
))) {
1301 const OSSymbol
* client
;
1302 while ((client
= (const OSSymbol
*) iter
->getNextObject())) {
1303 IOPMPowerStateIndex powerState
= getPowerStateForClient(client
);
1304 if (powerState
>= numberOfStates
) {
1305 updatePowerClient(client
, fHighestPowerState
);
1311 if (inPlane(gIOPowerPlane
) && fParentsKnowState
) {
1312 IOPMPowerStateIndex tempDesire
;
1313 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1314 // initially change into the state we are already in
1315 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1316 adjustPowerState(tempDesire
);
1319 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1320 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1323 powerDriver
->release();
1326 //*********************************************************************************
1327 // [public] registerInterestedDriver
1329 // Add the caller to our list of interested drivers and return our current
1330 // power state. If we don't have a power-controlling driver yet, we will
1331 // call this interested driver again later when we do get a driver and find
1332 // out what the current power state of the device is.
1333 //*********************************************************************************
1336 IOService::registerInterestedDriver( IOService
* driver
)
1338 IOPMRequest
* request
;
1341 if (!driver
|| !initialized
|| !fInterestedDrivers
) {
1346 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1347 if (fInsertInterestSet
== NULL
) {
1348 fInsertInterestSet
= OSSet::withCapacity(4);
1350 if (fInsertInterestSet
) {
1351 fInsertInterestSet
->setObject(driver
);
1352 if (fRemoveInterestSet
) {
1353 fRemoveInterestSet
->removeObject(driver
);
1359 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1361 submitPMRequest( request
);
1365 // This return value cannot be trusted, but return a value
1366 // for those clients that care.
1368 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1369 return kIOPMDeviceUsable
;
1372 //*********************************************************************************
1373 // [public] deRegisterInterestedDriver
1374 //*********************************************************************************
1377 IOService::deRegisterInterestedDriver( IOService
* driver
)
1379 IOPMinformee
* item
;
1380 IOPMRequest
* request
;
1384 return kIOReturnBadArgument
;
1386 if (!initialized
|| !fInterestedDrivers
) {
1387 return IOPMNotPowerManaged
;
1391 if (fInsertInterestSet
) {
1392 fInsertInterestSet
->removeObject(driver
);
1395 item
= fInterestedDrivers
->findItem(driver
);
1398 return kIOReturnNotFound
;
1401 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1402 if (fRemoveInterestSet
== NULL
) {
1403 fRemoveInterestSet
= OSSet::withCapacity(4);
1405 if (fRemoveInterestSet
) {
1406 fRemoveInterestSet
->setObject(driver
);
1408 item
->active
= false;
1409 waitForPMDriverCall( driver
);
1415 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1417 submitPMRequest( request
);
1424 //*********************************************************************************
1425 // [private] handleInterestChanged
1427 // Handle interest added or removed.
1428 //*********************************************************************************
1431 IOService::handleInterestChanged( IOPMRequest
* request
)
1434 IOPMinformee
* informee
;
1435 IOPMinformeeList
* list
= fInterestedDrivers
;
1439 if (fInsertInterestSet
) {
1440 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject())) {
1441 if (list
->findItem(driver
) == NULL
) {
1442 informee
= list
->appendNewInformee(driver
);
1444 fInsertInterestSet
->removeObject(driver
);
1446 fInsertInterestSet
->release();
1447 fInsertInterestSet
= NULL
;
1450 if (fRemoveInterestSet
) {
1451 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject())) {
1452 informee
= list
->findItem(driver
);
1454 // Clean-up async interest acknowledgement
1455 if (fHeadNotePendingAcks
&& informee
->timer
) {
1456 informee
->timer
= 0;
1457 fHeadNotePendingAcks
--;
1459 list
->removeFromList(driver
);
1461 fRemoveInterestSet
->removeObject(driver
);
1463 fRemoveInterestSet
->release();
1464 fRemoveInterestSet
= NULL
;
1470 //*********************************************************************************
1471 // [public] acknowledgePowerChange
1473 // After we notified one of the interested drivers or a power-domain child
1474 // of an impending change in power, it has called to say it is now
1475 // prepared for the change. If this object is the last to
1476 // acknowledge this change, we take whatever action we have been waiting
1478 // That may include acknowledging to our parent. In this case, we do it
1479 // last of all to insure that this doesn't cause the parent to call us some-
1480 // where else and alter data we are relying on here (like the very existance
1481 // of a "current change note".)
1482 //*********************************************************************************
1485 IOService::acknowledgePowerChange( IOService
* whichObject
)
1487 IOPMRequest
* request
;
1490 return IOPMNotYetInitialized
;
1493 return kIOReturnBadArgument
;
1496 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1498 return kIOReturnNoMemory
;
1501 whichObject
->retain();
1502 request
->fArg0
= whichObject
;
1504 submitPMRequest( request
);
1508 //*********************************************************************************
1509 // [private] handleAcknowledgePowerChange
1510 //*********************************************************************************
1513 IOService::handleAcknowledgePowerChange( IOPMRequest
* request
)
1515 IOPMinformee
* informee
;
1516 unsigned long childPower
= kIOPMUnknown
;
1517 IOService
* theChild
;
1518 IOService
* whichObject
;
1519 bool all_acked
= false;
1521 PM_ASSERT_IN_GATE();
1522 whichObject
= (IOService
*) request
->fArg0
;
1523 assert(whichObject
);
1525 // one of our interested drivers?
1526 informee
= fInterestedDrivers
->findItem( whichObject
);
1527 if (informee
== NULL
) {
1528 if (!isChild(whichObject
, gIOPowerPlane
)) {
1529 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1532 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1535 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1538 if (fHeadNotePendingAcks
!= 0) {
1539 assert(fPowerStates
!= NULL
);
1541 // yes, make sure we're expecting acks
1542 if (informee
!= NULL
) {
1543 // it's an interested driver
1544 // make sure we're expecting this ack
1545 if (informee
->timer
!= 0) {
1546 if (informee
->timer
> 0) {
1547 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1548 if (nsec
> LOG_SETPOWER_TIMES
) {
1549 getPMRootDomain()->pmStatsRecordApplicationResponse(
1550 gIOPMStatsDriverPSChangeSlow
, informee
->whatObject
->getName(),
1551 fDriverCallReason
, NS_TO_MS(nsec
), informee
->whatObject
->getRegistryEntryID(),
1552 NULL
, fHeadNotePowerState
);
1557 informee
->timer
= 0;
1558 // that's one fewer to worry about
1559 fHeadNotePendingAcks
--;
1561 // this driver has already acked
1562 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1566 // make sure we're expecting this ack
1567 if (((IOPowerConnection
*)whichObject
)->getAwaitingAck()) {
1568 // that's one fewer to worry about
1569 fHeadNotePendingAcks
--;
1570 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1571 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1573 childPower
= theChild
->currentPowerConsumption();
1574 theChild
->release();
1576 if (childPower
== kIOPMUnknown
) {
1577 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1579 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
) {
1580 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1586 if (fHeadNotePendingAcks
== 0) {
1587 // yes, stop the timer
1589 // and now we can continue
1591 getPMRootDomain()->reset_watchdog_timer(this, 0);
1594 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1599 whichObject
->release();
1605 //*********************************************************************************
1606 // [public] acknowledgeSetPowerState
1608 // After we instructed our controlling driver to change power states,
1609 // it has called to say it has finished doing so.
1610 // We continue to process the power state change.
1611 //*********************************************************************************
1614 IOService::acknowledgeSetPowerState( void )
1616 IOPMRequest
* request
;
1619 return IOPMNotYetInitialized
;
1622 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1624 return kIOReturnNoMemory
;
1627 submitPMRequest( request
);
1628 return kIOReturnSuccess
;
1631 //*********************************************************************************
1632 // [private] adjustPowerState
1633 //*********************************************************************************
1636 IOService::adjustPowerState( uint32_t clamp
)
1638 PM_ASSERT_IN_GATE();
1639 computeDesiredState(clamp
, false);
1640 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
)) {
1641 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1643 // Indicate that children desires must be ignored, and do not ask
1644 // apps for permission to drop power. This is used by root domain
1645 // for demand sleep.
1647 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
) {
1648 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1652 /* flags */ changeFlags
,
1653 /* power state */ fDesiredPowerState
,
1654 /* domain flags */ 0,
1655 /* connection */ NULL
,
1656 /* parent flags */ 0);
1660 //*********************************************************************************
1661 // [public] synchronizePowerTree
1662 //*********************************************************************************
1665 IOService::synchronizePowerTree(
1666 IOOptionBits options
,
1667 IOService
* notifyRoot
)
1669 IOPMRequest
* request_c
= NULL
;
1670 IOPMRequest
* request_s
;
1672 if (this != getPMRootDomain()) {
1673 return kIOReturnBadArgument
;
1676 return kIOPMNotYetInitialized
;
1679 OUR_PMLog(kPMLogCSynchronizePowerTree
, options
, (notifyRoot
!= NULL
));
1684 // Cancels don't need to be synchronized.
1685 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1687 submitPMRequest(nr
);
1689 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1691 submitPMRequest(nr
);
1695 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1697 goto error_no_memory
;
1700 if (options
& kIOPMSyncCancelPowerDown
) {
1701 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1704 request_c
->attachNextRequest( request_s
);
1705 submitPMRequest(request_c
);
1708 request_s
->fArg0
= (void *)(uintptr_t) options
;
1709 submitPMRequest(request_s
);
1711 return kIOReturnSuccess
;
1715 releasePMRequest(request_c
);
1718 releasePMRequest(request_s
);
1720 return kIOReturnNoMemory
;
1723 //*********************************************************************************
1724 // [private] handleSynchronizePowerTree
1725 //*********************************************************************************
1728 IOService::handleSynchronizePowerTree( IOPMRequest
* request
)
1730 PM_ASSERT_IN_GATE();
1731 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1732 (fCurrentPowerState
== fHighestPowerState
)) {
1733 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1736 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1737 (options
& kIOPMSyncNoChildNotify
),
1738 /* power state */ fCurrentPowerState
,
1739 /* domain flags */ 0,
1740 /* connection */ NULL
,
1741 /* parent flags */ 0);
1746 //*********************************************************************************
1747 // [deprecated] powerDomainWillChangeTo
1749 // Called by the power-hierarchy parent notifying of a new power state
1750 // in the power domain.
1751 // We enqueue a parent power-change to our queue of power changes.
1752 // This may or may not cause us to change power, depending on what
1753 // kind of change is occuring in the domain.
1754 //*********************************************************************************
1757 IOService::powerDomainWillChangeTo(
1758 IOPMPowerFlags newPowerFlags
,
1759 IOPowerConnection
* whichParent
)
1762 return kIOReturnUnsupported
;
1764 #endif /* !__LP64__ */
1766 //*********************************************************************************
1767 // [private] handlePowerDomainWillChangeTo
1768 //*********************************************************************************
1771 IOService::handlePowerDomainWillChangeTo( IOPMRequest
* request
)
1773 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1774 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1775 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1776 IOPMPowerChangeFlags myChangeFlags
;
1779 IOPowerConnection
* connection
;
1780 IOPMPowerStateIndex maxPowerState
;
1781 IOPMPowerFlags combinedPowerFlags
;
1782 bool savedParentsKnowState
;
1783 IOReturn result
= IOPMAckImplied
;
1785 PM_ASSERT_IN_GATE();
1786 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1788 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck()) {
1789 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1793 savedParentsKnowState
= fParentsKnowState
;
1795 // Combine parents' output power flags.
1797 combinedPowerFlags
= 0;
1799 iter
= getParentIterator(gIOPowerPlane
);
1801 while ((next
= iter
->getNextObject())) {
1802 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
1803 if (connection
== whichParent
) {
1804 combinedPowerFlags
|= parentPowerFlags
;
1806 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1813 // If our initial change has yet to occur, then defer the power change
1814 // until after the power domain has completed its power transition.
1816 if (fControllingDriver
&& !fInitialPowerChange
) {
1817 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1818 combinedPowerFlags
);
1820 if (parentChangeFlags
& kIOPMDomainPowerDrop
) {
1821 // fMaxPowerState set a limit on self-initiated power changes.
1822 // Update it before a parent power drop.
1823 fMaxPowerState
= maxPowerState
;
1826 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1827 // to avoid propagating the root change flags if any service must
1828 // change power state due to root's will-change notification.
1829 // Root does not change power state for kIOPMSynchronize.
1831 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1832 (parentChangeFlags
& kIOPMSynchronize
);
1834 result
= startPowerChange(
1835 /* flags */ myChangeFlags
,
1836 /* power state */ maxPowerState
,
1837 /* domain flags */ combinedPowerFlags
,
1838 /* connection */ whichParent
,
1839 /* parent flags */ parentPowerFlags
);
1842 // If parent is dropping power, immediately update the parent's
1843 // capability flags. Any future merging of parent(s) combined
1844 // power flags should account for this power drop.
1846 if (parentChangeFlags
& kIOPMDomainPowerDrop
) {
1847 setParentInfo(parentPowerFlags
, whichParent
, true);
1850 // Parent is expecting an ACK from us. If we did not embark on a state
1851 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1852 // still required to issue an ACK to our parent.
1854 if (IOPMAckImplied
== result
) {
1856 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1859 parent
->acknowledgePowerChange( whichParent
);
1865 // Drop the retain from notifyChild().
1867 whichParent
->release();
1872 //*********************************************************************************
1873 // [deprecated] powerDomainDidChangeTo
1875 // Called by the power-hierarchy parent after the power state of the power domain
1876 // has settled at a new level.
1877 // We enqueue a parent power-change to our queue of power changes.
1878 // This may or may not cause us to change power, depending on what
1879 // kind of change is occuring in the domain.
1880 //*********************************************************************************
1883 IOService::powerDomainDidChangeTo(
1884 IOPMPowerFlags newPowerFlags
,
1885 IOPowerConnection
* whichParent
)
1888 return kIOReturnUnsupported
;
1890 #endif /* !__LP64__ */
1892 //*********************************************************************************
1893 // [private] handlePowerDomainDidChangeTo
1894 //*********************************************************************************
1897 IOService::handlePowerDomainDidChangeTo( IOPMRequest
* request
)
1899 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1900 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1901 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1902 IOPMPowerChangeFlags myChangeFlags
;
1903 IOPMPowerStateIndex maxPowerState
;
1904 IOPMPowerStateIndex initialDesire
= kPowerStateZero
;
1905 bool computeDesire
= false;
1906 bool desireChanged
= false;
1907 bool savedParentsKnowState
;
1908 IOReturn result
= IOPMAckImplied
;
1910 PM_ASSERT_IN_GATE();
1911 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1913 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck()) {
1914 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1918 savedParentsKnowState
= fParentsKnowState
;
1920 setParentInfo(parentPowerFlags
, whichParent
, true);
1922 if (fControllingDriver
) {
1923 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1924 fParentsCurrentPowerFlags
);
1926 if ((parentChangeFlags
& kIOPMDomainPowerDrop
) == 0) {
1927 // fMaxPowerState set a limit on self-initiated power changes.
1928 // Update it after a parent power rise.
1929 fMaxPowerState
= maxPowerState
;
1932 if (fInitialPowerChange
) {
1933 computeDesire
= true;
1934 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1935 fParentsCurrentPowerFlags
);
1936 } else if (parentChangeFlags
& kIOPMRootChangeUp
) {
1937 if (fAdvisoryTickleUsed
) {
1938 // On system wake, re-compute the desired power state since
1939 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1940 // which is an input to computeDesiredState(). This is not
1941 // necessary for a dark wake because powerChangeDone() will
1942 // handle the dark to full wake case, but it does no harm.
1944 desireChanged
= true;
1947 if (fResetPowerStateOnWake
) {
1948 // Query the driver for the desired power state on system wake.
1949 // Default implementation returns the lowest power state.
1951 IOPMPowerStateIndex wakePowerState
=
1952 fControllingDriver
->initialPowerStateForDomainState(
1953 kIOPMRootDomainState
| kIOPMPowerOn
);
1955 // fDesiredPowerState was adjusted before going to sleep
1956 // with fDeviceDesire at min.
1958 if (StateOrder(wakePowerState
) > StateOrder(fDesiredPowerState
)) {
1959 // Must schedule a power adjustment if we changed the
1960 // device desire. That will update the desired domain
1961 // power on the parent power connection and ping the
1962 // power parent if necessary.
1964 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1965 desireChanged
= true;
1970 if (computeDesire
|| desireChanged
) {
1971 computeDesiredState(initialDesire
, false);
1974 // Absorb and propagate parent's broadcast flags
1975 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1976 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1978 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
1979 if (kIOPMAOTPower
& fPowerStates
[maxPowerState
].inputPowerFlags
) {
1980 IOLog("aotPS %s0x%qx[%ld]\n", getName(), getRegistryEntryID(), maxPowerState
);
1982 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
1984 result
= startPowerChange(
1985 /* flags */ myChangeFlags
,
1986 /* power state */ maxPowerState
,
1987 /* domain flags */ fParentsCurrentPowerFlags
,
1988 /* connection */ whichParent
,
1989 /* parent flags */ 0);
1992 // Parent is expecting an ACK from us. If we did not embark on a state
1993 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1994 // still required to issue an ACK to our parent.
1996 if (IOPMAckImplied
== result
) {
1998 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
2001 parent
->acknowledgePowerChange( whichParent
);
2006 // If the parent registers its power driver late, then this is the
2007 // first opportunity to tell our parent about our desire. Or if the
2008 // child's desire changed during a parent change notify.
2010 if (fControllingDriver
&&
2011 ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
)) {
2012 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
2013 getName(), fParentsKnowState
);
2014 requestDomainPower( fDesiredPowerState
);
2018 // Drop the retain from notifyChild().
2020 whichParent
->release();
2024 //*********************************************************************************
2025 // [private] setParentInfo
2027 // Set our connection data for one specific parent, and then combine all the parent
2029 //*********************************************************************************
2032 IOService::setParentInfo(
2033 IOPMPowerFlags newPowerFlags
,
2034 IOPowerConnection
* whichParent
,
2039 IOPowerConnection
* conn
;
2041 PM_ASSERT_IN_GATE();
2043 // set our connection data
2044 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
2045 whichParent
->setParentKnowsState(knowsState
);
2047 // recompute our parent info
2048 fParentsCurrentPowerFlags
= 0;
2049 fParentsKnowState
= true;
2051 iter
= getParentIterator(gIOPowerPlane
);
2053 while ((next
= iter
->getNextObject())) {
2054 if ((conn
= OSDynamicCast(IOPowerConnection
, next
))) {
2055 fParentsKnowState
&= conn
->parentKnowsState();
2056 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
2063 //******************************************************************************
2064 // [private] trackSystemSleepPreventers
2065 //******************************************************************************
2068 IOService::trackSystemSleepPreventers(
2069 IOPMPowerStateIndex oldPowerState
,
2070 IOPMPowerStateIndex newPowerState
,
2071 IOPMPowerChangeFlags changeFlags __unused
)
2073 IOPMPowerFlags oldCapability
, newCapability
;
2075 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2076 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2077 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2078 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2080 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
) {
2083 if (oldCapability
== newCapability
) {
2087 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
) {
2088 bool enablePrevention
= ((oldCapability
& kIOPMPreventIdleSleep
) == 0);
2089 bool idleCancelAllowed
= getPMRootDomain()->updatePreventIdleSleepList(
2090 this, enablePrevention
);
2091 #if SUPPORT_IDLE_CANCEL
2092 if (idleCancelAllowed
&& enablePrevention
) {
2093 IOPMRequest
* cancelRequest
;
2095 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2096 if (cancelRequest
) {
2097 submitPMRequest( cancelRequest
);
2103 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
) {
2104 getPMRootDomain()->updatePreventSystemSleepList(this,
2105 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2109 //*********************************************************************************
2110 // [public] requestPowerDomainState
2112 // Called on a power parent when a child's power requirement changes.
2113 //*********************************************************************************
2116 IOService::requestPowerDomainState(
2117 IOPMPowerFlags childRequestPowerFlags
,
2118 IOPowerConnection
* childConnection
,
2119 unsigned long specification
)
2121 IOPMPowerStateIndex order
, powerState
;
2122 IOPMPowerFlags outputPowerFlags
;
2124 IOPMRequest
* subRequest
;
2125 bool adjustPower
= false;
2128 return IOPMNotYetInitialized
;
2131 if (gIOPMWorkLoop
->onThread() == false) {
2132 PM_LOG("%s::requestPowerDomainState\n", getName());
2133 return kIOReturnSuccess
;
2136 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2138 if (!isChild(childConnection
, gIOPowerPlane
)) {
2139 return kIOReturnNotAttached
;
2142 if (!fControllingDriver
|| !fNumberOfPowerStates
) {
2143 return kIOReturnNotReady
;
2146 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2149 // Remove flags from child request which we can't possibly supply
2150 childRequestPowerFlags
&= fMergedOutputPowerFlags
;
2152 // Merge in the power flags contributed by this power parent
2153 // at its current or impending power state.
2155 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2156 if (fMachineState
!= kIOPM_Finished
) {
2157 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
) {
2158 // Use the lower power state when dropping power.
2159 // Must be careful since a power drop can be cancelled
2160 // from the following states:
2161 // - kIOPM_OurChangeTellClientsPowerDown
2162 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2164 // The child must not wait for this parent to raise power
2165 // if the power drop was cancelled. The solution is to cancel
2166 // the power drop if possible, then schedule an adjustment to
2167 // re-evaluate the parent's power state.
2169 // Root domain is excluded to avoid idle sleep issues. And allow
2170 // root domain children to pop up when system is going to sleep.
2172 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2173 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)) {
2174 fDoNotPowerDown
= true; // cancel power drop
2175 adjustPower
= true;// schedule an adjustment
2176 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2177 getName(), fMachineState
, child
->getName());
2179 // Beyond cancellation point, report the impending state.
2181 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2183 } else if (IS_POWER_RISE
) {
2184 // When raising power, must report the output power flags from
2185 // child's perspective. A child power request may arrive while
2186 // parent is transitioning upwards. If a request arrives after
2187 // setParentInfo() has already recorded the output power flags
2188 // for the next power state, then using the power supplied by
2189 // fCurrentPowerState is incorrect, and might cause the child
2190 // to wait when it should not.
2192 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2195 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2197 // Map child's requested power flags to one of our power state.
2199 for (order
= 0; order
< fNumberOfPowerStates
; order
++) {
2200 powerState
= fPowerStates
[order
].stateOrderToIndex
;
2201 if ((fPowerStates
[powerState
].outputPowerFlags
& childRequestPowerFlags
)
2202 == childRequestPowerFlags
) {
2206 if (order
>= fNumberOfPowerStates
) {
2207 powerState
= kPowerStateZero
;
2210 // Conditions that warrants a power adjustment on this parent.
2211 // Adjust power will also propagate any changes to the child's
2212 // prevent idle/sleep flags towards the root domain.
2214 if (!childConnection
->childHasRequestedPower() ||
2215 (powerState
!= childConnection
->getDesiredDomainState())) {
2219 #if ENABLE_DEBUG_LOGS
2221 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2222 getName(), child
->getName(),
2223 !childConnection
->childHasRequestedPower(),
2224 (uint32_t) childConnection
->getDesiredDomainState(),
2225 (uint32_t) powerState
);
2229 // Record the child's desires on the connection.
2230 childConnection
->setChildHasRequestedPower();
2231 childConnection
->setDesiredDomainState( powerState
);
2233 // Schedule a request to re-evaluate all children desires and
2234 // adjust power state. Submit a request if one wasn't pending,
2235 // or if the current request is part of a call tree.
2237 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2238 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest())) {
2239 subRequest
= acquirePMRequest(
2240 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2242 submitPMRequest( subRequest
);
2243 fAdjustPowerScheduled
= true;
2247 return kIOReturnSuccess
;
2250 //*********************************************************************************
2251 // [public] temporaryPowerClampOn
2253 // A power domain wants to clamp its power on till it has children which
2254 // will thendetermine the power domain state.
2256 // We enter the highest state until addPowerChild is called.
2257 //*********************************************************************************
2260 IOService::temporaryPowerClampOn( void )
2262 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2265 //*********************************************************************************
2266 // [public] makeUsable
2268 // Some client of our device is asking that we become usable. Although
2269 // this has not come from a subclassed device object, treat it exactly
2270 // as if it had. In this way, subsequent requests for lower power from
2271 // a subclassed device object will pre-empt this request.
2273 // We treat this as a subclass object request to switch to the
2274 // highest power state.
2275 //*********************************************************************************
2278 IOService::makeUsable( void )
2280 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2281 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2284 //*********************************************************************************
2285 // [public] currentCapability
2286 //*********************************************************************************
2289 IOService::currentCapability( void )
2292 return IOPMNotPowerManaged
;
2295 return fCurrentCapabilityFlags
;
2298 //*********************************************************************************
2299 // [public] changePowerStateTo
2301 // Called by our power-controlling driver to change power state. The new desired
2302 // power state is computed and compared against the current power state. If those
2303 // power states differ, then a power state change is initiated.
2304 //*********************************************************************************
2307 IOService::changePowerStateTo( unsigned long ordinal
)
2309 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2310 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2313 //*********************************************************************************
2314 // [protected] changePowerStateToPriv
2316 // Called by our driver subclass to change power state. The new desired power
2317 // state is computed and compared against the current power state. If those
2318 // power states differ, then a power state change is initiated.
2319 //*********************************************************************************
2322 IOService::changePowerStateToPriv( unsigned long ordinal
)
2324 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2325 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2328 //*********************************************************************************
2329 // [public] changePowerStateWithOverrideTo
2331 // Called by our driver subclass to change power state. The new desired power
2332 // state is computed and compared against the current power state. If those
2333 // power states differ, then a power state change is initiated.
2334 // Override enforced - Children and Driver desires are ignored.
2335 //*********************************************************************************
2338 IOService::changePowerStateWithOverrideTo( IOPMPowerStateIndex ordinal
,
2339 IOPMRequestTag tag
)
2341 IOPMRequest
* request
;
2344 return kIOPMNotYetInitialized
;
2347 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2349 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2351 return kIOReturnNoMemory
;
2354 gIOPMPowerClientDevice
->retain();
2355 request
->fRequestTag
= tag
;
2356 request
->fArg0
= (void *) ordinal
;
2357 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2358 request
->fArg2
= NULL
;
2361 request
->installCompletionAction( action
, target
, param
);
2365 // Prevent needless downwards power transitions by clamping power
2366 // until the scheduled request is executed.
2368 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
)) {
2369 fTempClampPowerState
= StateMax(fTempClampPowerState
, ordinal
);
2371 fOverrideMaxPowerState
= ordinal
;
2372 request
->fArg2
= (void *) (uintptr_t) true;
2375 submitPMRequest( request
);
2379 //*********************************************************************************
2380 // [public] changePowerStateForRootDomain
2382 // Adjust the root domain's power desire on the target
2383 //*********************************************************************************
2386 IOService::changePowerStateForRootDomain( IOPMPowerStateIndex ordinal
)
2388 OUR_PMLog(kPMLogChangeStateForRootDomain
, ordinal
, 0);
2389 return requestPowerState( gIOPMPowerClientRootDomain
, ordinal
);
2392 //*********************************************************************************
2393 // [public for PMRD] quiescePowerTree
2395 // For root domain to issue a request to quiesce the power tree.
2396 // Supplied callback invoked upon completion.
2397 //*********************************************************************************
2400 IOService::quiescePowerTree(
2401 void * target
, IOPMCompletionAction action
, void * param
)
2403 IOPMRequest
* request
;
2406 return kIOPMNotYetInitialized
;
2408 if (!target
|| !action
) {
2409 return kIOReturnBadArgument
;
2412 OUR_PMLog(kPMLogQuiescePowerTree
, 0, 0);
2414 // Target the root node instead of root domain. This is to avoid blocking
2415 // the quiesce request behind an existing root domain request in the work
2416 // queue. Root parent and root domain requests in the work queue must not
2417 // block the completion of the quiesce request.
2419 request
= acquirePMRequest(gIOPMRootNode
, kIOPMRequestTypeQuiescePowerTree
);
2421 return kIOReturnNoMemory
;
2424 request
->installCompletionAction(target
, action
, param
);
2426 // Submit through the normal request flow. This will make sure any request
2427 // already in the request queue will get pushed over to the work queue for
2428 // execution. Any request submitted after this request may not be serviced.
2430 submitPMRequest( request
);
2431 return kIOReturnSuccess
;
2434 //*********************************************************************************
2435 // [private] requestPowerState
2436 //*********************************************************************************
2439 IOService::requestPowerState(
2440 const OSSymbol
* client
,
2443 IOPMRequest
* request
;
2446 return kIOReturnBadArgument
;
2449 return kIOPMNotYetInitialized
;
2452 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2454 return kIOReturnNoMemory
;
2458 request
->fArg0
= (void *)(uintptr_t) state
;
2459 request
->fArg1
= (void *) client
;
2460 request
->fArg2
= NULL
;
2463 request
->installCompletionAction( action
, target
, param
);
2467 // Prevent needless downwards power transitions by clamping power
2468 // until the scheduled request is executed.
2470 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
)) {
2471 fTempClampPowerState
= StateMax(fTempClampPowerState
, state
);
2473 request
->fArg2
= (void *) (uintptr_t) true;
2476 submitPMRequest( request
);
2480 //*********************************************************************************
2481 // [private] handleRequestPowerState
2482 //*********************************************************************************
2485 IOService::handleRequestPowerState( IOPMRequest
* request
)
2487 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2488 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2490 PM_ASSERT_IN_GATE();
2491 if (request
->fArg2
) {
2492 assert(fTempClampCount
!= 0);
2493 if (fTempClampCount
) {
2496 if (!fTempClampCount
) {
2497 fTempClampPowerState
= kPowerStateZero
;
2501 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
)) {
2502 state
= fHighestPowerState
;
2505 // The power suppression due to changePowerStateWithOverrideTo() expires
2506 // upon the next "device" power request - changePowerStateToPriv().
2508 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2509 (client
== gIOPMPowerClientDevice
)) {
2510 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2513 if ((state
== kPowerStateZero
) &&
2514 (client
!= gIOPMPowerClientDevice
) &&
2515 (client
!= gIOPMPowerClientDriver
) &&
2516 (client
!= gIOPMPowerClientChildProxy
)) {
2517 removePowerClient(client
);
2519 updatePowerClient(client
, state
);
2526 //*********************************************************************************
2527 // [private] Helper functions to update/remove power clients.
2528 //*********************************************************************************
2531 IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2533 IOPMPowerStateIndex oldPowerState
= kPowerStateZero
;
2535 if (!fPowerClients
) {
2536 fPowerClients
= OSDictionary::withCapacity(4);
2538 if (fPowerClients
&& client
) {
2539 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2541 oldPowerState
= num
->unsigned32BitValue();
2542 num
->setValue(powerState
);
2544 num
= OSNumber::withNumber(powerState
, 32);
2546 fPowerClients
->setObject(client
, num
);
2551 PM_ACTION_3(actionUpdatePowerClient
, client
, oldPowerState
, powerState
);
2556 IOService::removePowerClient( const OSSymbol
* client
)
2558 if (fPowerClients
&& client
) {
2559 fPowerClients
->removeObject(client
);
2564 IOService::getPowerStateForClient( const OSSymbol
* client
)
2566 uint32_t powerState
= kPowerStateZero
;
2568 if (fPowerClients
&& client
) {
2569 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2571 powerState
= num
->unsigned32BitValue();
2577 //*********************************************************************************
2578 // [protected] powerOverrideOnPriv
2579 //*********************************************************************************
2582 IOService::powerOverrideOnPriv( void )
2584 IOPMRequest
* request
;
2587 return IOPMNotYetInitialized
;
2590 if (gIOPMWorkLoop
->inGate()) {
2591 fDeviceOverrideEnabled
= true;
2595 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2597 return kIOReturnNoMemory
;
2600 submitPMRequest( request
);
2604 //*********************************************************************************
2605 // [protected] powerOverrideOffPriv
2606 //*********************************************************************************
2609 IOService::powerOverrideOffPriv( void )
2611 IOPMRequest
* request
;
2614 return IOPMNotYetInitialized
;
2617 if (gIOPMWorkLoop
->inGate()) {
2618 fDeviceOverrideEnabled
= false;
2622 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2624 return kIOReturnNoMemory
;
2627 submitPMRequest( request
);
2631 //*********************************************************************************
2632 // [private] handlePowerOverrideChanged
2633 //*********************************************************************************
2636 IOService::handlePowerOverrideChanged( IOPMRequest
* request
)
2638 PM_ASSERT_IN_GATE();
2639 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
) {
2640 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2641 fDeviceOverrideEnabled
= true;
2643 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2644 fDeviceOverrideEnabled
= false;
2650 //*********************************************************************************
2651 // [private] computeDesiredState
2652 //*********************************************************************************
2655 IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2659 IOPowerConnection
* connection
;
2660 uint32_t desiredState
= kPowerStateZero
;
2661 uint32_t newPowerState
= kPowerStateZero
;
2662 bool hasChildren
= false;
2664 // Desired power state is always 0 without a controlling driver.
2666 if (!fNumberOfPowerStates
) {
2667 fDesiredPowerState
= kPowerStateZero
;
2671 // Examine the children's desired power state.
2673 iter
= getChildIterator(gIOPowerPlane
);
2675 while ((next
= iter
->getNextObject())) {
2676 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
2677 if (connection
->getReadyFlag() == false) {
2678 PM_LOG3("[%s] %s: connection not ready\n",
2679 getName(), __FUNCTION__
);
2682 if (connection
->childHasRequestedPower()) {
2685 desiredState
= StateMax(connection
->getDesiredDomainState(), desiredState
);
2691 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2693 removePowerClient(gIOPMPowerClientChildren
);
2696 // Iterate through all power clients to determine the min power state.
2698 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2700 const OSSymbol
* client
;
2701 while ((client
= (const OSSymbol
*) iter
->getNextObject())) {
2702 // Ignore child and driver when override is in effect.
2703 if ((fDeviceOverrideEnabled
||
2704 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2705 ((client
== gIOPMPowerClientChildren
) ||
2706 (client
== gIOPMPowerClientDriver
))) {
2710 // Ignore child proxy when children are present.
2711 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
)) {
2715 // Advisory tickles are irrelevant unless system is in full wake
2716 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2717 !gIOPMAdvisoryTickleEnabled
) {
2721 desiredState
= getPowerStateForClient(client
);
2722 assert(desiredState
< fNumberOfPowerStates
);
2724 desiredState
, client
->getCStringNoCopy());
2726 newPowerState
= StateMax(newPowerState
, desiredState
);
2728 if (client
== gIOPMPowerClientDevice
) {
2729 fDeviceDesire
= desiredState
;
2735 // Factor in the temporary power desires.
2737 newPowerState
= StateMax(newPowerState
, localClamp
);
2738 newPowerState
= StateMax(newPowerState
, fTempClampPowerState
);
2740 // Limit check against max power override.
2742 newPowerState
= StateMin(newPowerState
, fOverrideMaxPowerState
);
2744 // Limit check against number of power states.
2746 if (newPowerState
>= fNumberOfPowerStates
) {
2747 newPowerState
= fHighestPowerState
;
2750 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
2751 if (getPMRootDomain()->isAOTMode()) {
2752 if ((kIOPMPreventIdleSleep
& fPowerStates
[newPowerState
].capabilityFlags
)
2753 && !(kIOPMPreventIdleSleep
& fPowerStates
[fDesiredPowerState
].capabilityFlags
)) {
2754 getPMRootDomain()->claimSystemWakeEvent(this, kIOPMWakeEventAOTExit
, getName(), NULL
);
2757 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
2759 fDesiredPowerState
= newPowerState
;
2761 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2762 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2763 (uint32_t) fCurrentPowerState
, newPowerState
);
2766 // Restart idle timer if possible when device desire has increased.
2767 // Or if an advisory desire exists.
2769 if (fIdleTimerPeriod
&& fIdleTimerStopped
) {
2773 // Invalidate cached tickle power state when desires change, and not
2774 // due to a tickle request. In case the driver has requested a lower
2775 // power state, but the tickle is caching a higher power state which
2776 // will drop future tickles until the cached value is lowered or in-
2777 // validated. The invalidation must occur before the power transition
2778 // to avoid dropping a necessary tickle.
2780 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2781 (fActivityTicklePowerState
!= kInvalidTicklePowerState
)) {
2782 IOLockLock(fActivityLock
);
2783 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2784 IOLockUnlock(fActivityLock
);
2789 //*********************************************************************************
2790 // [public] currentPowerConsumption
2792 //*********************************************************************************
2795 IOService::currentPowerConsumption( void )
2798 return kIOPMUnknown
;
2801 return fCurrentPowerConsumption
;
2804 //*********************************************************************************
2805 // [deprecated] getPMworkloop
2806 //*********************************************************************************
2810 IOService::getPMworkloop( void )
2812 return gIOPMWorkLoop
;
2818 //*********************************************************************************
2819 // Power Parent/Children Applier
2820 //*********************************************************************************
2823 applyToPowerChildren(
2824 IOService
* service
,
2825 IOServiceApplierFunction applier
,
2827 IOOptionBits options
)
2829 PM_ASSERT_IN_GATE();
2831 IORegistryEntry
* entry
;
2832 IORegistryIterator
* iter
;
2833 IOPowerConnection
* connection
;
2836 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2838 while ((entry
= iter
->getNextObject())) {
2839 // Get child of IOPowerConnection objects
2840 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
))) {
2841 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2843 (*applier
)(child
, context
);
2854 IOService
* service
,
2855 IOServiceApplierFunction applier
,
2857 IOOptionBits options
)
2859 PM_ASSERT_IN_GATE();
2861 IORegistryEntry
* entry
;
2862 IORegistryIterator
* iter
;
2863 IOPowerConnection
* connection
;
2866 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2867 options
| kIORegistryIterateParents
);
2869 while ((entry
= iter
->getNextObject())) {
2870 // Get child of IOPowerConnection objects
2871 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
))) {
2872 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2874 (*applier
)(parent
, context
);
2883 #endif /* NOT_YET */
2886 // MARK: Activity Tickle & Idle Timer
2889 IOService::setAdvisoryTickleEnable( bool enable
)
2891 gIOPMAdvisoryTickleEnabled
= enable
;
2894 //*********************************************************************************
2895 // [public] activityTickle
2897 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2898 // flag to be set, and the device state checked. If the device has been
2899 // powered down, it is powered up again.
2900 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2901 // should be intercepted by a subclass.
2902 //*********************************************************************************
2905 IOService::activityTickle( unsigned long type
, unsigned long stateNumber
)
2907 IOPMRequest
* request
;
2908 bool noPowerChange
= true;
2909 uint32_t tickleFlags
;
2912 return true; // no power change
2914 if ((type
== kIOPMSuperclassPolicy1
) && StateOrder(stateNumber
)) {
2915 IOLockLock(fActivityLock
);
2917 // Record device activity for the idle timer handler.
2919 fDeviceWasActive
= true;
2920 fActivityTickleCount
++;
2921 clock_get_uptime(&fDeviceActiveTimestamp
);
2923 PM_ACTION_0(actionActivityTickle
);
2925 // Record the last tickle power state.
2926 // This helps to filter out redundant tickles as
2927 // this function may be called from the data path.
2929 if ((fActivityTicklePowerState
== kInvalidTicklePowerState
)
2930 || StateOrder(fActivityTicklePowerState
) < StateOrder(stateNumber
)) {
2931 fActivityTicklePowerState
= stateNumber
;
2932 noPowerChange
= false;
2934 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2935 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2937 request
->fArg0
= (void *) stateNumber
;
2938 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2939 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2940 submitPMRequest(request
);
2944 IOLockUnlock(fActivityLock
);
2945 } else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2946 ((stateNumber
= fDeviceUsablePowerState
) != kPowerStateZero
)) {
2947 IOLockLock(fActivityLock
);
2949 fAdvisoryTickled
= true;
2951 if (fAdvisoryTicklePowerState
!= stateNumber
) {
2952 fAdvisoryTicklePowerState
= stateNumber
;
2953 noPowerChange
= false;
2955 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2956 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2958 request
->fArg0
= (void *) stateNumber
;
2959 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2960 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2961 submitPMRequest(request
);
2965 IOLockUnlock(fActivityLock
);
2968 // Returns false if the activityTickle might cause a transition to a
2969 // higher powered state, true otherwise.
2971 return noPowerChange
;
2974 //*********************************************************************************
2975 // [private] handleActivityTickle
2976 //*********************************************************************************
2979 IOService::handleActivityTickle( IOPMRequest
* request
)
2981 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2982 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
2983 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
2984 bool adjustPower
= false;
2986 PM_ASSERT_IN_GATE();
2987 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
)) {
2988 // Drivers that don't want power restored on wake will drop any
2989 // tickles that pre-dates the current system wake. The model is
2990 // that each wake is a fresh start, with power state depressed
2991 // until a new tickle or an explicit power up request from the
2992 // driver. It is possible for the PM work loop to enter the
2993 // system sleep path with tickle requests queued.
2998 if (tickleFlags
& kTickleTypeActivity
) {
2999 IOPMPowerStateIndex deviceDesireOrder
= StateOrder(fDeviceDesire
);
3000 uint32_t idleTimerGeneration
= ticklePowerState
; // kTickleTypePowerDrop
3002 if (tickleFlags
& kTickleTypePowerRise
) {
3003 if ((StateOrder(ticklePowerState
) > deviceDesireOrder
) &&
3004 (ticklePowerState
< fNumberOfPowerStates
)) {
3005 fIdleTimerMinPowerState
= ticklePowerState
;
3006 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
3009 } else if ((deviceDesireOrder
> StateOrder(fIdleTimerMinPowerState
)) &&
3010 (idleTimerGeneration
== fIdleTimerGeneration
)) {
3011 // Power drop due to idle timer expiration.
3012 // Do not allow idle timer to reduce power below tickle power.
3013 // This prevents the idle timer from decreasing the device desire
3014 // to zero and cancelling the effect of a pre-sleep tickle when
3015 // system wakes up to doze state, while the device is unable to
3016 // raise its power state to satisfy the tickle.
3018 deviceDesireOrder
--;
3019 if (deviceDesireOrder
< fNumberOfPowerStates
) {
3020 ticklePowerState
= fPowerStates
[deviceDesireOrder
].stateOrderToIndex
;
3021 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
3025 } else { // advisory tickle
3026 if (tickleFlags
& kTickleTypePowerRise
) {
3027 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
3028 (ticklePowerState
< fNumberOfPowerStates
)) {
3029 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
3030 fHasAdvisoryDesire
= true;
3031 fAdvisoryTickleUsed
= true;
3034 IOLockLock(fActivityLock
);
3035 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3036 IOLockUnlock(fActivityLock
);
3038 } else if (fHasAdvisoryDesire
) {
3039 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
3040 fHasAdvisoryDesire
= false;
3050 //******************************************************************************
3051 // [public] setIdleTimerPeriod
3053 // A subclass policy-maker is using our standard idleness detection service.
3054 // Start the idle timer. Period is in seconds.
3055 //******************************************************************************
3058 IOService::setIdleTimerPeriod( unsigned long period
)
3061 return IOPMNotYetInitialized
;
3064 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
3066 IOPMRequest
* request
=
3067 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
3069 return kIOReturnNoMemory
;
3072 request
->fArg0
= (void *) period
;
3073 submitPMRequest( request
);
3075 return kIOReturnSuccess
;
3079 IOService::setIgnoreIdleTimer( bool ignore
)
3082 return IOPMNotYetInitialized
;
3085 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
3087 IOPMRequest
* request
=
3088 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
3090 return kIOReturnNoMemory
;
3093 request
->fArg0
= (void *) ignore
;
3094 submitPMRequest( request
);
3096 return kIOReturnSuccess
;
3099 //******************************************************************************
3100 // [public] nextIdleTimeout
3102 // Returns how many "seconds from now" the device should idle into its
3103 // next lowest power state.
3104 //******************************************************************************
3107 IOService::nextIdleTimeout(
3108 AbsoluteTime currentTime
,
3109 AbsoluteTime lastActivity
,
3110 unsigned int powerState
)
3117 // Calculate time difference using funky macro from clock.h.
3118 delta
= currentTime
;
3119 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
3121 // Figure it in seconds.
3122 absolutetime_to_nanoseconds(delta
, &delta_ns
);
3123 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
3125 // Be paranoid about delta somehow exceeding timer period.
3126 if (delta_secs
< (int) fIdleTimerPeriod
) {
3127 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3129 delay_secs
= (int) fIdleTimerPeriod
;
3132 return (SInt32
)delay_secs
;
3135 //*********************************************************************************
3136 // [public] start_PM_idle_timer
3137 //*********************************************************************************
3140 IOService::start_PM_idle_timer( void )
3142 static const int maxTimeout
= 100000;
3143 static const int minTimeout
= 1;
3144 AbsoluteTime uptime
, deadline
;
3148 if (!initialized
|| !fIdleTimerPeriod
) {
3152 IOLockLock(fActivityLock
);
3154 clock_get_uptime(&uptime
);
3156 // Subclasses may modify idle sleep algorithm
3157 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3159 // Check for out-of range responses
3160 if (idle_in
> maxTimeout
) {
3161 // use standard implementation
3162 idle_in
= IOService::nextIdleTimeout(uptime
,
3163 fDeviceActiveTimestamp
,
3164 fCurrentPowerState
);
3165 } else if (idle_in
< minTimeout
) {
3166 idle_in
= fIdleTimerPeriod
;
3169 IOLockUnlock(fActivityLock
);
3171 fNextIdleTimerPeriod
= idle_in
;
3172 fIdleTimerStartTime
= uptime
;
3175 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3176 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3177 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3183 //*********************************************************************************
3184 // [private] restartIdleTimer
3185 //*********************************************************************************
3188 IOService::restartIdleTimer( void )
3190 if (fDeviceDesire
!= kPowerStateZero
) {
3191 fIdleTimerStopped
= false;
3192 fActivityTickleCount
= 0;
3193 start_PM_idle_timer();
3194 } else if (fHasAdvisoryDesire
) {
3195 fIdleTimerStopped
= false;
3196 start_PM_idle_timer();
3198 fIdleTimerStopped
= true;
3202 //*********************************************************************************
3203 // idle_timer_expired
3204 //*********************************************************************************
3208 thread_call_param_t arg0
, thread_call_param_t arg1
)
3210 IOService
* me
= (IOService
*) arg0
;
3212 if (gIOPMWorkLoop
) {
3213 gIOPMWorkLoop
->runAction(
3214 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3215 &IOService::idleTimerExpired
),
3222 //*********************************************************************************
3223 // [private] idleTimerExpired
3225 // The idle timer has expired. If there has been activity since the last
3226 // expiration, just restart the timer and return. If there has not been
3227 // activity, switch to the next lower power state and restart the timer.
3228 //*********************************************************************************
3231 IOService::idleTimerExpired( void )
3233 IOPMRequest
* request
;
3234 bool restartTimer
= true;
3235 uint32_t tickleFlags
;
3237 if (!initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3238 fLockedFlags
.PMStop
) {
3242 fIdleTimerStartTime
= 0;
3244 IOLockLock(fActivityLock
);
3246 // Check for device activity (tickles) over last timer period.
3248 if (fDeviceWasActive
) {
3249 // Device was active - do not drop power, restart timer.
3250 fDeviceWasActive
= false;
3251 } else if (!fIdleTimerIgnored
) {
3252 // No device activity - drop power state by one level.
3253 // Decrement the cached tickle power state when possible.
3254 // This value may be kInvalidTicklePowerState before activityTickle()
3255 // is called, but the power drop request must be issued regardless.
3257 if ((fActivityTicklePowerState
!= kInvalidTicklePowerState
) &&
3258 (fActivityTicklePowerState
!= kPowerStateZero
)) {
3259 fActivityTicklePowerState
--;
3262 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3263 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3265 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3266 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3267 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3268 submitPMRequest( request
);
3270 // Do not restart timer until after the tickle request has been
3273 restartTimer
= false;
3277 if (fAdvisoryTickled
) {
3278 fAdvisoryTickled
= false;
3279 } else if (fHasAdvisoryDesire
) {
3280 // Want new tickles to turn into pm request after we drop the lock
3281 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3283 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3284 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3286 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3287 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3288 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3289 submitPMRequest( request
);
3291 // Do not restart timer until after the tickle request has been
3294 restartTimer
= false;
3298 IOLockUnlock(fActivityLock
);
3301 start_PM_idle_timer();
3306 //*********************************************************************************
3307 // [deprecated] PM_idle_timer_expiration
3308 //*********************************************************************************
3311 IOService::PM_idle_timer_expiration( void )
3315 //*********************************************************************************
3316 // [deprecated] command_received
3317 //*********************************************************************************
3320 IOService::command_received( void *statePtr
, void *, void *, void * )
3323 #endif /* !__LP64__ */
3325 //*********************************************************************************
3326 // [public] setAggressiveness
3328 // Pass on the input parameters to all power domain children. All those which are
3329 // power domains will pass it on to their children, etc.
3330 //*********************************************************************************
3333 IOService::setAggressiveness( unsigned long type
, unsigned long newLevel
)
3335 return kIOReturnSuccess
;
3338 //*********************************************************************************
3339 // [public] getAggressiveness
3341 // Called by the user client.
3342 //*********************************************************************************
3345 IOService::getAggressiveness( unsigned long type
, unsigned long * currentLevel
)
3347 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3350 return kIOReturnNotReady
;
3353 return rootDomain
->getAggressiveness( type
, currentLevel
);
3356 //*********************************************************************************
3357 // [public] getPowerState
3359 //*********************************************************************************
3362 IOService::getPowerState( void )
3365 return kPowerStateZero
;
3368 return fCurrentPowerState
;
3372 //*********************************************************************************
3373 // [deprecated] systemWake
3375 // Pass this to all power domain children. All those which are
3376 // power domains will pass it on to their children, etc.
3377 //*********************************************************************************
3380 IOService::systemWake( void )
3384 IOPowerConnection
* connection
;
3385 IOService
* theChild
;
3387 iter
= getChildIterator(gIOPowerPlane
);
3389 while ((next
= iter
->getNextObject())) {
3390 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
3391 if (connection
->getReadyFlag() == false) {
3392 PM_LOG3("[%s] %s: connection not ready\n",
3393 getName(), __FUNCTION__
);
3397 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3399 theChild
->systemWake();
3400 theChild
->release();
3407 if (fControllingDriver
!= NULL
) {
3408 if (fControllingDriver
->didYouWakeSystem()) {
3416 //*********************************************************************************
3417 // [deprecated] temperatureCriticalForZone
3418 //*********************************************************************************
3421 IOService::temperatureCriticalForZone( IOService
* whichZone
)
3423 IOService
* theParent
;
3426 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3428 if (inPlane(gIOPowerPlane
) && !IS_PM_ROOT
) {
3429 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3431 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3434 theParent
->temperatureCriticalForZone(whichZone
);
3435 theParent
->release();
3441 #endif /* !__LP64__ */
3444 // MARK: Power Change (Common)
3446 //*********************************************************************************
3447 // [private] startPowerChange
3449 // All power state changes starts here.
3450 //*********************************************************************************
3453 IOService::startPowerChange(
3454 IOPMPowerChangeFlags changeFlags
,
3455 IOPMPowerStateIndex powerState
,
3456 IOPMPowerFlags domainFlags
,
3457 IOPowerConnection
* parentConnection
,
3458 IOPMPowerFlags parentFlags
)
3460 uint32_t savedPMActionsParam
;
3462 PM_ASSERT_IN_GATE();
3463 assert( fMachineState
== kIOPM_Finished
);
3464 assert( powerState
< fNumberOfPowerStates
);
3466 if (powerState
>= fNumberOfPowerStates
) {
3467 return IOPMAckImplied
;
3470 fIsPreChange
= true;
3471 savedPMActionsParam
= fPMActions
.parameter
;
3472 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3474 // rdar://problem/55040032
3475 // Schedule a power adjustment after removing the power clamp
3476 // to inform our power parent(s) about our latest desired domain
3477 // power state. For a self-initiated change, let OurChangeStart()
3478 // automatically request parent power when necessary.
3479 if (!fAdjustPowerScheduled
&&
3480 ((changeFlags
& kIOPMSelfInitiated
) == 0) &&
3481 ((fPMActions
.parameter
& kPMActionsFlagLimitPower
) == 0) &&
3482 ((savedPMActionsParam
& kPMActionsFlagLimitPower
) != 0)) {
3483 IOPMRequest
* request
= acquirePMRequest(this, kIOPMRequestTypeAdjustPowerState
);
3485 submitPMRequest(request
);
3486 fAdjustPowerScheduled
= true;
3490 if (changeFlags
& kIOPMExpireIdleTimer
) {
3491 // Root domain requested removal of tickle influence
3492 if (StateOrder(fDeviceDesire
) > StateOrder(powerState
)) {
3493 // Reset device desire down to the clamped power state
3494 updatePowerClient(gIOPMPowerClientDevice
, powerState
);
3495 computeDesiredState(kPowerStateZero
, true);
3497 // Invalidate tickle cache so the next tickle will issue a request
3498 IOLockLock(fActivityLock
);
3499 fDeviceWasActive
= false;
3500 fActivityTicklePowerState
= kInvalidTicklePowerState
;
3501 IOLockUnlock(fActivityLock
);
3503 fIdleTimerMinPowerState
= kPowerStateZero
;
3507 // Root domain's override handler may cancel the power change by
3508 // setting the kIOPMNotDone flag.
3510 if (changeFlags
& kIOPMNotDone
) {
3511 return IOPMAckImplied
;
3514 // Forks to either Driver or Parent initiated power change paths.
3516 fHeadNoteChangeFlags
= changeFlags
;
3517 fHeadNotePowerState
= powerState
;
3518 fHeadNotePowerArrayEntry
= &fPowerStates
[powerState
];
3519 fHeadNoteParentConnection
= NULL
;
3521 if (changeFlags
& kIOPMSelfInitiated
) {
3522 if (changeFlags
& kIOPMSynchronize
) {
3529 assert(changeFlags
& kIOPMParentInitiated
);
3530 fHeadNoteDomainFlags
= domainFlags
;
3531 fHeadNoteParentFlags
= parentFlags
;
3532 fHeadNoteParentConnection
= parentConnection
;
3533 return ParentChangeStart();
3537 //*********************************************************************************
3538 // [private] notifyInterestedDrivers
3539 //*********************************************************************************
3542 IOService::notifyInterestedDrivers( void )
3544 IOPMinformee
* informee
;
3545 IOPMinformeeList
* list
= fInterestedDrivers
;
3546 DriverCallParam
* param
;
3548 IOItemCount skipCnt
= 0;
3550 PM_ASSERT_IN_GATE();
3551 assert( fDriverCallParamCount
== 0 );
3552 assert( fHeadNotePendingAcks
== 0 );
3554 fHeadNotePendingAcks
= 0;
3556 count
= list
->numberOfItems();
3558 goto done
; // no interested drivers
3560 // Allocate an array of interested drivers and their return values
3561 // for the callout thread. Everything else is still "owned" by the
3562 // PM work loop, which can run to process acknowledgePowerChange()
3565 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3566 if (count
> fDriverCallParamSlots
) {
3567 if (fDriverCallParamSlots
) {
3568 assert(fDriverCallParamPtr
);
3569 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3570 fDriverCallParamPtr
= NULL
;
3571 fDriverCallParamSlots
= 0;
3574 param
= IONew(DriverCallParam
, count
);
3576 goto done
; // no memory
3578 fDriverCallParamPtr
= (void *) param
;
3579 fDriverCallParamSlots
= count
;
3582 informee
= list
->firstInList();
3584 for (IOItemCount i
= 0; i
< count
; i
++) {
3585 if (fInitialSetPowerState
|| (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)) {
3586 // Skip notifying self, if 'kIOPMInitialDeviceState' is set and
3587 // this is the initial power state change
3588 if ((this == informee
->whatObject
) &&
3589 (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)) {
3594 informee
->timer
= -1;
3595 param
[i
].Target
= informee
;
3597 informee
= list
->nextInList( informee
);
3604 fDriverCallParamCount
= count
;
3605 fHeadNotePendingAcks
= count
;
3607 // Block state machine and wait for callout completion.
3608 assert(!fDriverCallBusy
);
3609 fDriverCallBusy
= true;
3610 thread_call_enter( fDriverCallEntry
);
3614 // Return false if there are no interested drivers or could not schedule
3615 // callout thread due to error.
3619 //*********************************************************************************
3620 // [private] notifyInterestedDriversDone
3621 //*********************************************************************************
3624 IOService::notifyInterestedDriversDone( void )
3626 IOPMinformee
* informee
;
3628 DriverCallParam
* param
;
3632 PM_ASSERT_IN_GATE();
3633 assert( fDriverCallBusy
== false );
3634 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3636 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3637 count
= fDriverCallParamCount
;
3639 if (param
&& count
) {
3640 for (IOItemCount i
= 0; i
< count
; i
++, param
++) {
3641 informee
= (IOPMinformee
*) param
->Target
;
3642 result
= param
->Result
;
3644 if ((result
== IOPMAckImplied
) || (result
< 0)) {
3645 // Interested driver return IOPMAckImplied.
3646 // If informee timer is zero, it must have de-registered
3647 // interest during the thread callout. That also drops
3648 // the pending ack count.
3650 if (fHeadNotePendingAcks
&& informee
->timer
) {
3651 fHeadNotePendingAcks
--;
3654 informee
->timer
= 0;
3655 } else if (informee
->timer
) {
3656 assert(informee
->timer
== -1);
3658 // Driver has not acked, and has returned a positive result.
3659 // Enforce a minimum permissible timeout value.
3660 // Make the min value large enough so timeout is less likely
3661 // to occur if a driver misinterpreted that the return value
3662 // should be in microsecond units. And make it large enough
3663 // to be noticeable if a driver neglects to ack.
3665 if (result
< kMinAckTimeoutTicks
) {
3666 result
= kMinAckTimeoutTicks
;
3669 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3670 if (result
> maxTimeout
) {
3671 maxTimeout
= result
;
3674 // else, child has already acked or driver has removed interest,
3675 // and head_note_pendingAcks decremented.
3676 // informee may have been removed from the interested drivers list,
3677 // thus the informee must be retained across the callout.
3679 informee
->release();
3682 fDriverCallParamCount
= 0;
3684 if (fHeadNotePendingAcks
) {
3685 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3687 getPMRootDomain()->reset_watchdog_timer(this, maxTimeout
/ USEC_PER_SEC
+ 1);
3691 MS_POP(); // pop the machine state passed to notifyAll()
3693 // If interest acks are outstanding, block the state machine until
3694 // fHeadNotePendingAcks drops to zero before notifying root domain.
3695 // Otherwise notify root domain directly.
3697 if (!fHeadNotePendingAcks
) {
3700 MS_PUSH(fMachineState
);
3701 fMachineState
= kIOPM_NotifyChildrenStart
;
3705 //*********************************************************************************
3706 // [private] notifyRootDomain
3707 //*********************************************************************************
3710 IOService::notifyRootDomain( void )
3712 assert( fDriverCallBusy
== false );
3714 // Only for root domain in the will-change phase
3715 if (!IS_ROOT_DOMAIN
|| (fMachineState
!= kIOPM_OurChangeSetPowerState
)) {
3720 MS_PUSH(fMachineState
); // push notifyAll() machine state
3721 fMachineState
= kIOPM_DriverThreadCallDone
;
3723 // Call IOPMrootDomain::willNotifyPowerChildren() on a thread call
3724 // to avoid a deadlock.
3725 fDriverCallReason
= kRootDomainInformPreChange
;
3726 fDriverCallBusy
= true;
3727 thread_call_enter( fDriverCallEntry
);
3731 IOService::notifyRootDomainDone( void )
3733 assert( fDriverCallBusy
== false );
3734 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3736 MS_POP(); // pop notifyAll() machine state
3740 //*********************************************************************************
3741 // [private] notifyChildren
3742 //*********************************************************************************
3745 IOService::notifyChildren( void )
3749 IOPowerConnection
* connection
;
3750 OSArray
* children
= NULL
;
3751 IOPMrootDomain
* rootDomain
;
3752 bool delayNotify
= false;
3754 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3755 (IS_POWER_DROP
== fIsPreChange
) &&
3756 ((rootDomain
= getPMRootDomain()) == this)) {
3757 rootDomain
->tracePoint( IS_POWER_DROP
?
3758 kIOPMTracePointSleepPowerPlaneDrivers
:
3759 kIOPMTracePointWakePowerPlaneDrivers
);
3762 if (fStrictTreeOrder
) {
3763 children
= OSArray::withCapacity(8);
3766 // Sum child power consumption in notifyChild()
3767 fHeadNotePowerArrayEntry
->staticPower
= 0;
3769 iter
= getChildIterator(gIOPowerPlane
);
3771 while ((next
= iter
->getNextObject())) {
3772 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
3773 if (connection
->getReadyFlag() == false) {
3774 PM_LOG3("[%s] %s: connection not ready\n",
3775 getName(), __FUNCTION__
);
3779 // Mechanism to postpone the did-change notification to
3780 // certain power children to order those children last.
3781 // Cannot be used together with strict tree ordering.
3783 if (!fIsPreChange
&&
3784 connection
->delayChildNotification
&&
3785 getPMRootDomain()->shouldDelayChildNotification(this)) {
3787 children
= OSArray::withCapacity(8);
3793 children
->setObject( connection
);
3798 if (!delayNotify
&& children
) {
3799 children
->setObject( connection
);
3801 notifyChild( connection
);
3808 if (children
&& (children
->getCount() == 0)) {
3809 children
->release();
3813 assert(fNotifyChildArray
== NULL
);
3814 fNotifyChildArray
= children
;
3815 MS_PUSH(fMachineState
);
3818 // Block until all non-delayed children have acked their
3819 // notification. Then notify the remaining delayed child
3820 // in the array. This is used to hold off graphics child
3821 // notification while the rest of the system powers up.
3822 // If a hid tickle arrives during this time, the delayed
3823 // children are immediately notified and root domain will
3824 // not clamp power for dark wake.
3826 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3827 PM_LOG2("%s: %d children in delayed array\n",
3828 getName(), children
->getCount());
3830 // Child array created to support strict notification order.
3831 // Notify children in the array one at a time.
3833 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3838 //*********************************************************************************
3839 // [private] notifyChildrenOrdered
3840 //*********************************************************************************
3843 IOService::notifyChildrenOrdered( void )
3845 PM_ASSERT_IN_GATE();
3846 assert(fNotifyChildArray
);
3847 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3849 // Notify one child, wait for it to ack, then repeat for next child.
3850 // This is a workaround for some drivers with multiple instances at
3851 // the same branch in the power tree, but the driver is slow to power
3852 // up unless the tree ordering is observed. Problem observed only on
3853 // system wake, not on system sleep.
3855 // We have the ability to power off in reverse child index order.
3856 // That works nicely on some machines, but not on all HW configs.
3858 if (fNotifyChildArray
->getCount()) {
3859 IOPowerConnection
* connection
;
3860 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3861 notifyChild( connection
);
3862 fNotifyChildArray
->removeObject(0);
3864 fNotifyChildArray
->release();
3865 fNotifyChildArray
= NULL
;
3867 MS_POP(); // pushed by notifyChildren()
3871 //*********************************************************************************
3872 // [private] notifyChildrenDelayed
3873 //*********************************************************************************
3876 IOService::notifyChildrenDelayed( void )
3878 IOPowerConnection
* connection
;
3880 PM_ASSERT_IN_GATE();
3881 assert(fNotifyChildArray
);
3882 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3884 // Wait after all non-delayed children and interested drivers have ack'ed,
3885 // then notify all delayed children. If notify delay is canceled, child
3886 // acks may be outstanding with PM blocked on fHeadNotePendingAcks != 0.
3887 // But the handling for either case is identical.
3889 for (int i
= 0;; i
++) {
3890 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3895 notifyChild( connection
);
3898 PM_LOG2("%s: notified delayed children\n", getName());
3899 fNotifyChildArray
->release();
3900 fNotifyChildArray
= NULL
;
3902 MS_POP(); // pushed by notifyChildren()
3905 //*********************************************************************************
3906 // [private] notifyAll
3907 //*********************************************************************************
3910 IOService::notifyAll( uint32_t nextMS
)
3912 // Save the machine state to be restored by notifyInterestedDriversDone()
3914 PM_ASSERT_IN_GATE();
3916 fMachineState
= kIOPM_DriverThreadCallDone
;
3917 fDriverCallReason
= fIsPreChange
?
3918 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3920 if (!notifyInterestedDrivers()) {
3921 notifyInterestedDriversDone();
3924 return IOPMWillAckLater
;
3927 //*********************************************************************************
3928 // [private, static] pmDriverCallout
3930 // Thread call context
3931 //*********************************************************************************
3934 IOService::actionDriverCalloutDone(
3936 void * arg0
, void * arg1
,
3937 void * arg2
, void * arg3
)
3939 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3941 assert( fDriverCallBusy
);
3942 fDriverCallBusy
= false;
3944 assert(gIOPMWorkQueue
);
3945 gIOPMWorkQueue
->signalWorkAvailable();
3947 return kIOReturnSuccess
;
3951 IOService::pmDriverCallout( IOService
* from
)
3954 switch (from
->fDriverCallReason
) {
3955 case kDriverCallSetPowerState
:
3956 from
->driverSetPowerState();
3959 case kDriverCallInformPreChange
:
3960 case kDriverCallInformPostChange
:
3961 from
->driverInformPowerChange();
3964 case kRootDomainInformPreChange
:
3965 getPMRootDomain()->willNotifyPowerChildren(from
->fHeadNotePowerState
);
3969 panic("IOService::pmDriverCallout bad machine state %x",
3970 from
->fDriverCallReason
);
3973 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3975 /* arg0 */ (void *) from
->pwrMgt
);
3978 //*********************************************************************************
3979 // [private] driverSetPowerState
3981 // Thread call context
3982 //*********************************************************************************
3985 IOService::driverSetPowerState( void )
3987 IOPMPowerStateIndex powerState
;
3988 DriverCallParam
* param
;
3989 IOPMDriverCallEntry callEntry
;
3992 uint32_t oldPowerState
= getPowerState();
3994 assert( fDriverCallBusy
);
3995 assert( fDriverCallParamPtr
);
3996 assert( fDriverCallParamCount
== 1 );
3998 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3999 powerState
= fHeadNotePowerState
;
4001 if (assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodSetPowerState
)) {
4002 OUR_PMLogFuncStart(kPMLogProgramHardware
, (uintptr_t) this, powerState
);
4003 clock_get_uptime(&fDriverCallStartTime
);
4004 result
= fControllingDriver
->setPowerState( powerState
, this );
4005 clock_get_uptime(&end
);
4006 OUR_PMLogFuncEnd(kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
4008 deassertPMDriverCall(&callEntry
);
4010 // Record the most recent max power state residency timings.
4011 // Use with DeviceActiveTimestamp to diagnose tickle issues.
4012 if (powerState
== fHighestPowerState
) {
4013 fMaxPowerStateEntryTime
= end
;
4014 } else if (oldPowerState
== fHighestPowerState
) {
4015 fMaxPowerStateExitTime
= end
;
4019 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
4020 fName
, OBFUSCATE(this), fCurrentPowerState
, powerState
, result
);
4024 if ((result
== IOPMAckImplied
) || (result
< 0)) {
4027 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
4028 absolutetime_to_nanoseconds(end
, &nsec
);
4029 if (nsec
> LOG_SETPOWER_TIMES
) {
4030 getPMRootDomain()->pmStatsRecordApplicationResponse(
4031 gIOPMStatsDriverPSChangeSlow
,
4032 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
4037 result
= kIOPMAckImplied
;
4040 param
->Result
= result
;
4043 //*********************************************************************************
4044 // [private] driverInformPowerChange
4046 // Thread call context
4047 //*********************************************************************************
4050 IOService::driverInformPowerChange( void )
4052 IOPMinformee
* informee
;
4054 DriverCallParam
* param
;
4055 IOPMDriverCallEntry callEntry
;
4056 IOPMPowerFlags powerFlags
;
4057 IOPMPowerStateIndex powerState
;
4061 IOOptionBits callMethod
= (fDriverCallReason
== kDriverCallInformPreChange
) ?
4062 kIOPMDriverCallMethodWillChange
: kIOPMDriverCallMethodDidChange
;
4064 assert( fDriverCallBusy
);
4065 assert( fDriverCallParamPtr
);
4066 assert( fDriverCallParamCount
);
4068 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4069 count
= fDriverCallParamCount
;
4071 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4072 powerState
= fHeadNotePowerState
;
4074 for (IOItemCount i
= 0; i
< count
; i
++) {
4075 informee
= (IOPMinformee
*) param
->Target
;
4076 driver
= informee
->whatObject
;
4078 if (assertPMDriverCall(&callEntry
, callMethod
, informee
)) {
4079 if (fDriverCallReason
== kDriverCallInformPreChange
) {
4080 OUR_PMLogFuncStart(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
4081 clock_get_uptime(&informee
->startTime
);
4082 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
4083 clock_get_uptime(&end
);
4084 OUR_PMLogFuncEnd(kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
4086 OUR_PMLogFuncStart(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
4087 clock_get_uptime(&informee
->startTime
);
4088 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
4089 clock_get_uptime(&end
);
4090 OUR_PMLogFuncEnd(kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
4093 deassertPMDriverCall(&callEntry
);
4096 if ((result
== IOPMAckImplied
) || (result
< 0)) {
4099 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
4100 absolutetime_to_nanoseconds(end
, &nsec
);
4101 if (nsec
> LOG_SETPOWER_TIMES
) {
4102 getPMRootDomain()->pmStatsRecordApplicationResponse(
4103 gIOPMStatsDriverPSChangeSlow
, driver
->getName(),
4104 fDriverCallReason
, NS_TO_MS(nsec
), driver
->getRegistryEntryID(),
4109 result
= kIOPMAckImplied
;
4112 param
->Result
= result
;
4117 //*********************************************************************************
4118 // [private] notifyChild
4120 // Notify a power domain child of an upcoming power change.
4121 // If the object acknowledges the current change, we return TRUE.
4122 //*********************************************************************************
4125 IOService::notifyChild( IOPowerConnection
* theNub
)
4127 IOReturn ret
= IOPMAckImplied
;
4128 unsigned long childPower
;
4129 IOService
* theChild
;
4130 IOPMRequest
* childRequest
;
4131 IOPMPowerChangeFlags requestArg2
;
4134 PM_ASSERT_IN_GATE();
4135 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
4140 // Unless the child handles the notification immediately and returns
4141 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4142 fHeadNotePendingAcks
++;
4143 theNub
->setAwaitingAck(true);
4145 requestArg2
= fHeadNoteChangeFlags
;
4146 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
)) {
4147 requestArg2
|= kIOPMDomainPowerDrop
;
4150 requestType
= fIsPreChange
?
4151 kIOPMRequestTypePowerDomainWillChange
:
4152 kIOPMRequestTypePowerDomainDidChange
;
4154 childRequest
= acquirePMRequest( theChild
, requestType
);
4157 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4158 childRequest
->fArg1
= (void *) theNub
;
4159 childRequest
->fArg2
= (void *)(uintptr_t) requestArg2
;
4160 theChild
->submitPMRequest( childRequest
);
4161 ret
= IOPMWillAckLater
;
4163 ret
= IOPMAckImplied
;
4164 fHeadNotePendingAcks
--;
4165 theNub
->setAwaitingAck(false);
4166 childPower
= theChild
->currentPowerConsumption();
4167 if (childPower
== kIOPMUnknown
) {
4168 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4170 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
) {
4171 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4176 theChild
->release();
4177 return IOPMAckImplied
== ret
;
4180 //*********************************************************************************
4181 // [private] notifyControllingDriver
4182 //*********************************************************************************
4185 IOService::notifyControllingDriver( void )
4187 DriverCallParam
* param
;
4189 PM_ASSERT_IN_GATE();
4190 assert( fDriverCallParamCount
== 0 );
4191 assert( fControllingDriver
);
4193 if (fInitialSetPowerState
) {
4194 fInitialSetPowerState
= false;
4195 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4197 // Driver specified flag to skip the inital setPowerState()
4198 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
) {
4203 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4205 param
= IONew(DriverCallParam
, 1);
4207 return false; // no memory
4209 fDriverCallParamPtr
= (void *) param
;
4210 fDriverCallParamSlots
= 1;
4213 param
->Target
= fControllingDriver
;
4214 fDriverCallParamCount
= 1;
4217 // Block state machine and wait for callout completion.
4218 assert(!fDriverCallBusy
);
4219 fDriverCallBusy
= true;
4220 thread_call_enter( fDriverCallEntry
);
4225 //*********************************************************************************
4226 // [private] notifyControllingDriverDone
4227 //*********************************************************************************
4230 IOService::notifyControllingDriverDone( void )
4232 DriverCallParam
* param
;
4235 PM_ASSERT_IN_GATE();
4236 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4238 assert( fDriverCallBusy
== false );
4239 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4241 if (param
&& fDriverCallParamCount
) {
4242 assert(fDriverCallParamCount
== 1);
4244 // the return value from setPowerState()
4245 result
= param
->Result
;
4247 if ((result
== IOPMAckImplied
) || (result
< 0)) {
4249 } else if (fDriverTimer
) {
4250 assert(fDriverTimer
== -1);
4252 // Driver has not acked, and has returned a positive result.
4253 // Enforce a minimum permissible timeout value.
4254 // Make the min value large enough so timeout is less likely
4255 // to occur if a driver misinterpreted that the return value
4256 // should be in microsecond units. And make it large enough
4257 // to be noticeable if a driver neglects to ack.
4259 if (result
< kMinAckTimeoutTicks
) {
4260 result
= kMinAckTimeoutTicks
;
4263 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4265 // else, child has already acked and driver_timer reset to 0.
4267 fDriverCallParamCount
= 0;
4270 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4272 getPMRootDomain()->reset_watchdog_timer(this, result
/ USEC_PER_SEC
+ 1);
4276 MS_POP(); // pushed by OurChangeSetPowerState()
4277 fIsPreChange
= false;
4280 //*********************************************************************************
4281 // [private] all_done
4283 // A power change is done.
4284 //*********************************************************************************
4287 IOService::all_done( void )
4289 IOPMPowerStateIndex prevPowerState
;
4290 const IOPMPSEntry
* powerStatePtr
;
4291 IOPMDriverCallEntry callEntry
;
4292 uint32_t prevMachineState
= fMachineState
;
4293 bool actionCalled
= false;
4296 fMachineState
= kIOPM_Finished
;
4298 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4299 ((prevMachineState
== kIOPM_Finished
) ||
4300 (prevMachineState
== kIOPM_SyncFinish
))) {
4301 // Sync operation and no power change occurred.
4302 // Do not inform driver and clients about this request completion,
4303 // except for the originator (root domain).
4305 PM_ACTION_2(actionPowerChangeDone
,
4306 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4308 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
) {
4309 powerChangeDone(fCurrentPowerState
);
4310 } else if (fAdvisoryTickleUsed
) {
4311 // Not root domain and advisory tickle target.
4312 // Re-adjust power after power tree sync at the 'did' pass
4313 // to recompute desire and adjust power state between dark
4314 // and full wake transitions. Root domain is responsible
4315 // for calling setAdvisoryTickleEnable() before starting
4316 // the kIOPMSynchronize power change.
4318 if (!fAdjustPowerScheduled
&&
4319 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
)) {
4320 IOPMRequest
* request
;
4321 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4323 submitPMRequest( request
);
4324 fAdjustPowerScheduled
= true;
4333 if (fHeadNoteChangeFlags
& kIOPMSelfInitiated
) {
4334 // power state changed
4335 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0) {
4336 trackSystemSleepPreventers(
4337 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4339 // we changed, tell our parent
4340 requestDomainPower(fHeadNotePowerState
);
4342 // yes, did power raise?
4343 if (StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
)) {
4344 // yes, inform clients and apps
4345 tellChangeUp(fHeadNotePowerState
);
4347 prevPowerState
= fCurrentPowerState
;
4349 fCurrentPowerState
= fHeadNotePowerState
;
4352 ts
= mach_absolute_time();
4353 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4357 fPMVars
->myCurrentState
= fCurrentPowerState
;
4359 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4360 PM_ACTION_2(actionPowerChangeDone
,
4361 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4362 actionCalled
= true;
4364 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4365 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4366 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
) {
4367 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4370 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
) {
4371 // Bump tickle generation count once the entire tree is down
4372 gIOPMTickleGeneration
++;
4375 // inform subclass policy-maker
4376 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4377 assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodChangeDone
, NULL
, kIOPMDriverCallNoInactiveCheck
)) {
4378 powerChangeDone(prevPowerState
);
4379 deassertPMDriverCall(&callEntry
);
4381 } else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
) {
4382 // changePowerStateWithOverrideTo() was cancelled
4383 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4387 // parent-initiated power change
4388 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
4389 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
) {
4390 ParentChangeRootChangeDown();
4393 // power state changed
4394 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0) {
4395 trackSystemSleepPreventers(
4396 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4399 if (StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
)) {
4400 // yes, inform clients and apps
4401 tellChangeUp(fHeadNotePowerState
);
4404 prevPowerState
= fCurrentPowerState
;
4405 fCurrentPowerState
= fHeadNotePowerState
;
4408 ts
= mach_absolute_time();
4409 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4413 fPMVars
->myCurrentState
= fCurrentPowerState
;
4416 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4417 PM_ACTION_2(actionPowerChangeDone
,
4418 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4419 actionCalled
= true;
4421 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4422 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4423 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
) {
4424 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4427 // inform subclass policy-maker
4428 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4429 assertPMDriverCall(&callEntry
, kIOPMDriverCallMethodChangeDone
, NULL
, kIOPMDriverCallNoInactiveCheck
)) {
4430 powerChangeDone(prevPowerState
);
4431 deassertPMDriverCall(&callEntry
);
4436 // When power rises enough to satisfy the tickle's desire for more power,
4437 // the condition preventing idle-timer from dropping power is removed.
4439 if (StateOrder(fCurrentPowerState
) >= StateOrder(fIdleTimerMinPowerState
)) {
4440 fIdleTimerMinPowerState
= kPowerStateZero
;
4443 if (!actionCalled
) {
4444 PM_ACTION_2(actionPowerChangeDone
,
4445 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4450 // MARK: Power Change Initiated by Driver
4452 //*********************************************************************************
4453 // [private] OurChangeStart
4455 // Begin the processing of a power change initiated by us.
4456 //*********************************************************************************
4459 IOService::OurChangeStart( void )
4461 PM_ASSERT_IN_GATE();
4462 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4464 // fMaxPowerState is our maximum possible power state based on the current
4465 // power state of our parents. If we are trying to raise power beyond the
4466 // maximum, send an async request for more power to all parents.
4468 if (!IS_PM_ROOT
&& (StateOrder(fMaxPowerState
) < StateOrder(fHeadNotePowerState
))) {
4469 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4470 requestDomainPower(fHeadNotePowerState
);
4475 // Redundant power changes skips to the end of the state machine.
4477 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
)) {
4481 fInitialPowerChange
= false;
4483 // Change started, but may not complete...
4484 // Can be canceled (power drop) or deferred (power rise).
4486 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4488 // Two separate paths, depending if power is being raised or lowered.
4489 // Lowering power is subject to approval by clients of this service.
4491 if (IS_POWER_DROP
) {
4492 fDoNotPowerDown
= false;
4494 // Ask for persmission to drop power state
4495 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4496 fOutOfBandParameter
= kNotifyApps
;
4497 askChangeDown(fHeadNotePowerState
);
4499 // This service is raising power and parents are able to support the
4500 // new power state. However a parent may have already committed to
4501 // drop power, which might force this object to temporarily drop power.
4502 // This results in "oscillations" before the state machines converge
4503 // to a steady state.
4505 // To prevent this, a child must make a power reservation against all
4506 // parents before raising power. If the reservation fails, indicating
4507 // that the child will be unable to sustain the higher power state,
4508 // then the child will signal the parent to adjust power, and the child
4509 // will defer its power change.
4513 // Reserve parent power necessary to achieve fHeadNotePowerState.
4514 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4515 if (ret
!= kIOReturnSuccess
) {
4516 // Reservation failed, defer power rise.
4517 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4522 OurChangeTellCapabilityWillChange();
4526 //*********************************************************************************
4527 // [private] requestDomainPowerApplier
4529 // Call requestPowerDomainState() on all power parents.
4530 //*********************************************************************************
4532 struct IOPMRequestDomainPowerContext
{
4533 IOService
* child
; // the requesting child
4534 IOPMPowerFlags requestPowerFlags
;// power flags requested by child
4538 requestDomainPowerApplier(
4539 IORegistryEntry
* entry
,
4542 IOPowerConnection
* connection
;
4544 IOPMRequestDomainPowerContext
* context
;
4546 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == NULL
) {
4549 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4555 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4557 if (connection
->parentKnowsState() && connection
->getReadyFlag()) {
4558 parent
->requestPowerDomainState(
4559 context
->requestPowerFlags
,
4567 //*********************************************************************************
4568 // [private] requestDomainPower
4570 // Called by a power child to broadcast its desired power state to all parents.
4571 // If the child self-initiates a power change, it must call this function to
4572 // allow its parents to adjust power state.
4573 //*********************************************************************************
4576 IOService::requestDomainPower(
4577 IOPMPowerStateIndex ourPowerState
,
4578 IOOptionBits options
)
4580 IOPMPowerFlags requestPowerFlags
;
4581 IOPMPowerStateIndex maxPowerState
;
4582 IOPMRequestDomainPowerContext context
;
4584 PM_ASSERT_IN_GATE();
4585 assert(ourPowerState
< fNumberOfPowerStates
);
4586 if (ourPowerState
>= fNumberOfPowerStates
) {
4587 return kIOReturnBadArgument
;
4590 return kIOReturnSuccess
;
4593 // Fetch our input power flags for the requested power state.
4594 // Parent request is stated in terms of required power flags.
4596 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4598 // Disregard the "previous request" for power reservation.
4600 if (((options
& kReserveDomainPower
) == 0) &&
4601 (fPreviousRequestPowerFlags
== requestPowerFlags
)) {
4602 // skip if domain already knows our requirements
4605 fPreviousRequestPowerFlags
= requestPowerFlags
;
4607 // The results will be collected by fHeadNoteDomainTargetFlags
4608 context
.child
= this;
4609 context
.requestPowerFlags
= requestPowerFlags
;
4610 fHeadNoteDomainTargetFlags
= 0;
4611 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4613 if (options
& kReserveDomainPower
) {
4614 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4615 fHeadNoteDomainTargetFlags
);
4617 if (StateOrder(maxPowerState
) < StateOrder(ourPowerState
)) {
4618 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4620 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4621 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4622 return kIOReturnNoPower
;
4627 return kIOReturnSuccess
;
4630 //*********************************************************************************
4631 // [private] OurSyncStart
4632 //*********************************************************************************
4635 IOService::OurSyncStart( void )
4637 PM_ASSERT_IN_GATE();
4639 if (fInitialPowerChange
) {
4643 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4645 if (fHeadNoteChangeFlags
& kIOPMNotDone
) {
4650 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
) {
4651 fDoNotPowerDown
= false;
4653 // Ask for permission to drop power state
4654 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4655 fOutOfBandParameter
= kNotifyApps
;
4656 askChangeDown(fHeadNotePowerState
);
4658 // Only inform capability app and clients.
4659 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4663 //*********************************************************************************
4664 // [private] OurChangeTellClientsPowerDown
4666 // All applications and kernel clients have acknowledged our permission to drop
4667 // power. Here we notify them that we will lower the power and wait for acks.
4668 //*********************************************************************************
4671 IOService::OurChangeTellClientsPowerDown( void )
4673 if (!IS_ROOT_DOMAIN
) {
4674 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4676 fMachineState
= kIOPM_OurChangeTellUserPMPolicyPowerDown
;
4678 tellChangeDown1(fHeadNotePowerState
);
4681 //*********************************************************************************
4682 // [private] OurChangeTellUserPMPolicyPowerDown
4684 // All applications and kernel clients have acknowledged our permission to drop
4685 // power. Here we notify power management policy in user-space and wait for acks
4686 // one last time before we lower power
4687 //*********************************************************************************
4689 IOService::OurChangeTellUserPMPolicyPowerDown( void )
4691 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4692 fOutOfBandParameter
= kNotifyApps
;
4694 tellClientsWithResponse(kIOPMMessageLastCallBeforeSleep
);
4697 //*********************************************************************************
4698 // [private] OurChangeTellPriorityClientsPowerDown
4700 // All applications and kernel clients have acknowledged our intention to drop
4701 // power. Here we notify "priority" clients that we are lowering power.
4702 //*********************************************************************************
4705 IOService::OurChangeTellPriorityClientsPowerDown( void )
4707 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4708 tellChangeDown2(fHeadNotePowerState
);
4711 //*********************************************************************************
4712 // [private] OurChangeTellCapabilityWillChange
4714 // Extra stage for root domain to notify apps and drivers about the
4715 // system capability change when raising power state.
4716 //*********************************************************************************
4719 IOService::OurChangeTellCapabilityWillChange( void )
4721 if (!IS_ROOT_DOMAIN
) {
4722 return OurChangeNotifyInterestedDriversWillChange();
4725 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4728 //*********************************************************************************
4729 // [private] OurChangeNotifyInterestedDriversWillChange
4731 // All applications and kernel clients have acknowledged our power state change.
4732 // Here we notify interested drivers pre-change.
4733 //*********************************************************************************
4736 IOService::OurChangeNotifyInterestedDriversWillChange( void )
4738 IOPMrootDomain
* rootDomain
;
4739 if ((rootDomain
= getPMRootDomain()) == this) {
4740 if (IS_POWER_DROP
) {
4741 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4743 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4747 notifyAll( kIOPM_OurChangeSetPowerState
);
4750 //*********************************************************************************
4751 // [private] OurChangeSetPowerState
4753 // Instruct our controlling driver to program the hardware for the power state
4754 // change. Wait for async completions.
4755 //*********************************************************************************
4758 IOService::OurChangeSetPowerState( void )
4760 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4761 fMachineState
= kIOPM_DriverThreadCallDone
;
4762 fDriverCallReason
= kDriverCallSetPowerState
;
4764 if (notifyControllingDriver() == false) {
4765 notifyControllingDriverDone();
4769 //*********************************************************************************
4770 // [private] OurChangeWaitForPowerSettle
4772 // Our controlling driver has completed the power state change we initiated.
4773 // Wait for the driver specified settle time to expire.
4774 //*********************************************************************************
4777 IOService::OurChangeWaitForPowerSettle( void )
4779 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4783 //*********************************************************************************
4784 // [private] OurChangeNotifyInterestedDriversDidChange
4786 // Power has settled on a power change we initiated. Here we notify
4787 // all our interested drivers post-change.
4788 //*********************************************************************************
4791 IOService::OurChangeNotifyInterestedDriversDidChange( void )
4793 IOPMrootDomain
* rootDomain
;
4794 if ((rootDomain
= getPMRootDomain()) == this) {
4795 rootDomain
->tracePoint( IS_POWER_DROP
?
4796 kIOPMTracePointSleepDidChangeInterests
:
4797 kIOPMTracePointWakeDidChangeInterests
);
4800 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4803 //*********************************************************************************
4804 // [private] OurChangeTellCapabilityDidChange
4806 // For root domain to notify capability power-change.
4807 //*********************************************************************************
4810 IOService::OurChangeTellCapabilityDidChange( void )
4812 if (!IS_ROOT_DOMAIN
) {
4813 return OurChangeFinish();
4816 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4817 kIOPMTracePointSleepCapabilityClients
:
4818 kIOPMTracePointWakeCapabilityClients
);
4820 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4823 //*********************************************************************************
4824 // [private] OurChangeFinish
4826 // Done with this self-induced power state change.
4827 //*********************************************************************************
4830 IOService::OurChangeFinish( void )
4836 // MARK: Power Change Initiated by Parent
4838 //*********************************************************************************
4839 // [private] ParentChangeStart
4841 // Here we begin the processing of a power change initiated by our parent.
4842 //*********************************************************************************
4845 IOService::ParentChangeStart( void )
4847 PM_ASSERT_IN_GATE();
4848 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4850 // Root power domain has transitioned to its max power state
4851 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4852 (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) {
4853 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4854 if (fIdleTimerPeriod
&& fIdleTimerStopped
) {
4859 // Power domain is forcing us to lower power
4860 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
)) {
4861 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4863 // Tell apps and kernel clients
4864 fInitialPowerChange
= false;
4865 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4866 tellChangeDown1(fHeadNotePowerState
);
4867 return IOPMWillAckLater
;
4870 // Power domain is allowing us to raise power up to fHeadNotePowerState
4871 if (StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
)) {
4872 if (StateOrder(fDesiredPowerState
) > StateOrder(fCurrentPowerState
)) {
4873 if (StateOrder(fDesiredPowerState
) < StateOrder(fHeadNotePowerState
)) {
4874 // We power up, but not all the way
4875 fHeadNotePowerState
= fDesiredPowerState
;
4876 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4877 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4880 // We don't need to change
4881 fHeadNotePowerState
= fCurrentPowerState
;
4882 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4883 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4887 if (fHeadNoteChangeFlags
& kIOPMDomainDidChange
) {
4888 if (StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
)) {
4889 PM_ACTION_2(actionPowerChangeStart
,
4890 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4892 // Parent did change up - start our change up
4893 fInitialPowerChange
= false;
4894 ParentChangeTellCapabilityWillChange();
4895 return IOPMWillAckLater
;
4896 } else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
) {
4897 // No need to change power state, but broadcast change
4899 fMachineState
= kIOPM_SyncNotifyDidChange
;
4900 fDriverCallReason
= kDriverCallInformPreChange
;
4901 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4903 return IOPMWillAckLater
;
4907 // No power state change necessary
4908 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4911 return IOPMAckImplied
;
4914 //******************************************************************************
4915 // [private] ParentChangeRootChangeDown
4917 // Root domain has finished the transition to the system sleep state. And all
4918 // drivers in the power plane should have powered down. Cancel the idle timer,
4919 // and also reset the device desire for those drivers that don't want power
4920 // automatically restored on wake.
4921 //******************************************************************************
4924 IOService::ParentChangeRootChangeDown( void )
4926 // Always stop the idle timer before root power down
4927 if (fIdleTimerPeriod
&& !fIdleTimerStopped
) {
4928 fIdleTimerStopped
= true;
4929 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
)) {
4934 if (fResetPowerStateOnWake
) {
4935 // Reset device desire down to the lowest power state.
4936 // Advisory tickle desire is intentionally untouched since
4937 // it has no effect until system is promoted to full wake.
4939 if (fDeviceDesire
!= kPowerStateZero
) {
4940 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4941 computeDesiredState(kPowerStateZero
, true);
4942 requestDomainPower( fDesiredPowerState
);
4943 PM_LOG1("%s: tickle desire removed\n", fName
);
4946 // Invalidate tickle cache so the next tickle will issue a request
4947 IOLockLock(fActivityLock
);
4948 fDeviceWasActive
= false;
4949 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4950 IOLockUnlock(fActivityLock
);
4952 fIdleTimerMinPowerState
= kPowerStateZero
;
4953 } else if (fAdvisoryTickleUsed
) {
4954 // Less aggressive mechanism to accelerate idle timer expiration
4955 // before system sleep. May not always allow the driver to wake
4956 // up from system sleep in the min power state.
4960 bool dropTickleDesire
= false;
4962 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
4963 (fIdleTimerMinPowerState
== kPowerStateZero
) &&
4964 (fDeviceDesire
!= kPowerStateZero
)) {
4965 IOLockLock(fActivityLock
);
4967 if (!fDeviceWasActive
) {
4968 // No tickles since the last idle timer expiration.
4969 // Safe to drop the device desire to zero.
4970 dropTickleDesire
= true;
4972 // Was tickled since the last idle timer expiration,
4973 // but not in the last minute.
4974 clock_get_uptime(&now
);
4975 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
4976 absolutetime_to_nanoseconds(now
, &nsec
);
4977 if (nsec
>= kNoTickleCancelWindow
) {
4978 dropTickleDesire
= true;
4982 if (dropTickleDesire
) {
4983 // Force the next tickle to raise power state
4984 fDeviceWasActive
= false;
4985 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4988 IOLockUnlock(fActivityLock
);
4991 if (dropTickleDesire
) {
4992 // Advisory tickle desire is intentionally untouched since
4993 // it has no effect until system is promoted to full wake.
4995 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4996 computeDesiredState(kPowerStateZero
, true);
4997 PM_LOG1("%s: tickle desire dropped\n", fName
);
5002 //*********************************************************************************
5003 // [private] ParentChangeTellPriorityClientsPowerDown
5005 // All applications and kernel clients have acknowledged our intention to drop
5006 // power. Here we notify "priority" clients that we are lowering power.
5007 //*********************************************************************************
5010 IOService::ParentChangeTellPriorityClientsPowerDown( void )
5012 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
5013 tellChangeDown2(fHeadNotePowerState
);
5016 //*********************************************************************************
5017 // [private] ParentChangeTellCapabilityWillChange
5019 // All (legacy) applications and kernel clients have acknowledged, extra stage for
5020 // root domain to notify apps and drivers about the system capability change.
5021 //*********************************************************************************
5024 IOService::ParentChangeTellCapabilityWillChange( void )
5026 if (!IS_ROOT_DOMAIN
) {
5027 return ParentChangeNotifyInterestedDriversWillChange();
5030 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
5033 //*********************************************************************************
5034 // [private] ParentChangeNotifyInterestedDriversWillChange
5036 // All applications and kernel clients have acknowledged our power state change.
5037 // Here we notify interested drivers pre-change.
5038 //*********************************************************************************
5041 IOService::ParentChangeNotifyInterestedDriversWillChange( void )
5043 notifyAll( kIOPM_ParentChangeSetPowerState
);
5046 //*********************************************************************************
5047 // [private] ParentChangeSetPowerState
5049 // Instruct our controlling driver to program the hardware for the power state
5050 // change. Wait for async completions.
5051 //*********************************************************************************
5054 IOService::ParentChangeSetPowerState( void )
5056 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
5057 fMachineState
= kIOPM_DriverThreadCallDone
;
5058 fDriverCallReason
= kDriverCallSetPowerState
;
5060 if (notifyControllingDriver() == false) {
5061 notifyControllingDriverDone();
5065 //*********************************************************************************
5066 // [private] ParentChangeWaitForPowerSettle
5068 // Our controlling driver has completed the power state change initiated by our
5069 // parent. Wait for the driver specified settle time to expire.
5070 //*********************************************************************************
5073 IOService::ParentChangeWaitForPowerSettle( void )
5075 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
5079 //*********************************************************************************
5080 // [private] ParentChangeNotifyInterestedDriversDidChange
5082 // Power has settled on a power change initiated by our parent. Here we notify
5083 // all our interested drivers post-change.
5084 //*********************************************************************************
5087 IOService::ParentChangeNotifyInterestedDriversDidChange( void )
5089 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
5092 //*********************************************************************************
5093 // [private] ParentChangeTellCapabilityDidChange
5095 // For root domain to notify capability power-change.
5096 //*********************************************************************************
5099 IOService::ParentChangeTellCapabilityDidChange( void )
5101 if (!IS_ROOT_DOMAIN
) {
5102 return ParentChangeAcknowledgePowerChange();
5105 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
5108 //*********************************************************************************
5109 // [private] ParentAcknowledgePowerChange
5111 // Acknowledge our power parent that our power change is done.
5112 //*********************************************************************************
5115 IOService::ParentChangeAcknowledgePowerChange( void )
5117 IORegistryEntry
* nub
;
5120 nub
= fHeadNoteParentConnection
;
5123 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
5125 parent
->acknowledgePowerChange((IOService
*)nub
);
5132 // MARK: Ack and Settle timers
5134 //*********************************************************************************
5135 // [private] settleTimerExpired
5137 // Power has settled after our last change. Notify interested parties that
5138 // there is a new power state.
5139 //*********************************************************************************
5142 IOService::settleTimerExpired( void )
5145 gIOPMWorkQueue
->signalWorkAvailable();
5148 //*********************************************************************************
5149 // settle_timer_expired
5151 // Holds a retain while the settle timer callout is in flight.
5152 //*********************************************************************************
5155 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5157 IOService
* me
= (IOService
*) arg0
;
5159 if (gIOPMWorkLoop
&& gIOPMWorkQueue
) {
5160 gIOPMWorkLoop
->runAction(
5161 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5167 //*********************************************************************************
5168 // [private] startSettleTimer
5170 // Calculate a power-settling delay in microseconds and start a timer.
5171 //*********************************************************************************
5174 IOService::startSettleTimer( void )
5177 // This function is broken and serves no useful purpose since it never
5178 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5179 // yet it starts a delay timer. It appears no driver relies on a delay
5180 // from settleUpTime and settleDownTime in the power state table.
5182 AbsoluteTime deadline
;
5183 IOPMPowerStateIndex stateIndex
;
5184 IOPMPowerStateIndex currentOrder
, newOrder
, i
;
5185 uint32_t settleTime
= 0;
5188 PM_ASSERT_IN_GATE();
5190 currentOrder
= StateOrder(fCurrentPowerState
);
5191 newOrder
= StateOrder(fHeadNotePowerState
);
5196 if (newOrder
< currentOrder
) {
5197 while (i
> newOrder
) {
5198 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
5199 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleDownTime
;
5205 if (newOrder
> currentOrder
) {
5206 while (i
< newOrder
) {
5207 stateIndex
= fPowerStates
[i
+ 1].stateOrderToIndex
;
5208 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleUpTime
;
5215 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5216 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5224 //*********************************************************************************
5225 // [private] ackTimerTick
5227 // The acknowledgement timeout periodic timer has ticked.
5228 // If we are awaiting acks for a power change notification,
5229 // we decrement the timer word of each interested driver which hasn't acked.
5230 // If a timer word becomes zero, we pretend the driver aknowledged.
5231 // If we are waiting for the controlling driver to change the power
5232 // state of the hardware, we decrement its timer word, and if it becomes
5233 // zero, we pretend the driver acknowledged.
5235 // Returns true if the timer tick made it possible to advance to the next
5236 // machine state, false otherwise.
5237 //*********************************************************************************
5244 IOService::ack_timer_ticked( void )
5248 #endif /* !__LP64__ */
5251 IOService::ackTimerTick( void )
5253 IOPMinformee
* nextObject
;
5256 PM_ASSERT_IN_GATE();
5257 switch (fMachineState
) {
5258 case kIOPM_OurChangeWaitForPowerSettle
:
5259 case kIOPM_ParentChangeWaitForPowerSettle
:
5260 // are we waiting for controlling driver to acknowledge?
5261 if (fDriverTimer
> 0) {
5262 // yes, decrement timer tick
5264 if (fDriverTimer
== 0) {
5265 // controlling driver is tardy
5266 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5267 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
5268 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
5269 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5270 fName
, OBFUSCATE(this), fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5272 #if DEBUG || DEVELOPMENT || CONFIG_EMBEDDED
5273 uint32_t panic_allowed
= -1;
5274 PE_parse_boot_argn("setpowerstate_panic", &panic_allowed
, sizeof(panic_allowed
));
5275 if (panic_allowed
!= 0) {
5276 // rdar://problem/48743340 - excluding AppleSEPManager from panic
5277 const char *whitelist
= "AppleSEPManager";
5278 if (strncmp(fName
, whitelist
, strlen(whitelist
))) {
5279 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5280 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5283 PM_ERROR("setPowerState panic disabled by setpowerstate_panic boot-arg\n");
5286 if (gIOKitDebug
& kIOLogDebugPower
) {
5287 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5288 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5290 // panic for first party kexts
5291 const void *function_addr
= NULL
;
5292 OSKext
*kext
= NULL
;
5293 function_addr
= OSMemberFunctionCast(const void *, fControllingDriver
, &IOService::setPowerState
);
5294 kext
= OSKext::lookupKextWithAddress((vm_address_t
)function_addr
);
5296 const char *bundleID
= kext
->getIdentifierCString();
5297 const char *apple_prefix
= "com.apple";
5298 const char *kernel_prefix
= "__kernel__";
5299 if (strncmp(bundleID
, apple_prefix
, strlen(apple_prefix
)) == 0 || strncmp(bundleID
, kernel_prefix
, strlen(kernel_prefix
)) == 0) {
5300 // first party client
5301 panic("%s::setPowerState(%p : %p, %lu -> %lu) timed out after %d ms",
5302 fName
, this, function_addr
, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5306 // Unblock state machine and pretend driver has acked.
5310 getPMRootDomain()->reset_watchdog_timer(this, 0);
5312 // still waiting, set timer again
5318 case kIOPM_NotifyChildrenStart
:
5319 // are we waiting for interested parties to acknowledge?
5320 if (fHeadNotePendingAcks
!= 0) {
5321 // yes, go through the list of interested drivers
5322 nextObject
= fInterestedDrivers
->firstInList();
5323 // and check each one
5324 while (nextObject
!= NULL
) {
5325 if (nextObject
->timer
> 0) {
5326 nextObject
->timer
--;
5327 // this one should have acked by now
5328 if (nextObject
->timer
== 0) {
5329 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5330 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5331 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5332 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5333 nextObject
->whatObject
->getName(),
5334 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5335 OBFUSCATE(nextObject
->whatObject
), fName
, fCurrentPowerState
, fHeadNotePowerState
,
5338 // Pretend driver has acked.
5339 fHeadNotePendingAcks
--;
5342 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5345 // is that the last?
5346 if (fHeadNotePendingAcks
== 0) {
5347 // yes, we can continue
5349 getPMRootDomain()->reset_watchdog_timer(this, 0);
5351 // no, set timer again
5357 // TODO: aggreggate this
5358 case kIOPM_OurChangeTellClientsPowerDown
:
5359 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
5360 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5361 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5362 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5363 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5364 case kIOPM_SyncTellClientsPowerDown
:
5365 case kIOPM_SyncTellPriorityClientsPowerDown
:
5366 case kIOPM_SyncNotifyWillChange
:
5367 case kIOPM_TellCapabilityChangeDone
:
5368 // apps didn't respond in time
5369 cleanClientResponses(true);
5370 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5371 // tardy equates to approval
5376 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5377 getName(), fMachineState
);
5383 //*********************************************************************************
5384 // [private] start_watchdog_timer
5385 //*********************************************************************************
5387 IOService::start_watchdog_timer( void )
5392 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5396 IOLockLock(fWatchdogLock
);
5398 timeout
= getPMRootDomain()->getWatchdogTimeout();
5399 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5400 fWatchdogDeadline
= deadline
;
5401 start_watchdog_timer(deadline
);
5402 IOLockUnlock(fWatchdogLock
);
5406 IOService::start_watchdog_timer(uint64_t deadline
)
5408 IOLockAssert(fWatchdogLock
, kIOLockAssertOwned
);
5410 if (!thread_call_isactive(fWatchdogTimer
)) {
5411 thread_call_enter_delayed(fWatchdogTimer
, deadline
);
5415 //*********************************************************************************
5416 // [private] stop_watchdog_timer
5417 //*********************************************************************************
5420 IOService::stop_watchdog_timer( void )
5422 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5426 IOLockLock(fWatchdogLock
);
5428 thread_call_cancel(fWatchdogTimer
);
5429 fWatchdogDeadline
= 0;
5431 while (fBlockedArray
->getCount()) {
5432 IOService
*obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(0));
5434 PM_ERROR("WDOG:Object %s unexpected in blocked array\n", obj
->fName
);
5435 fBlockedArray
->removeObject(0);
5439 IOLockUnlock(fWatchdogLock
);
5442 //*********************************************************************************
5443 // reset_watchdog_timer
5444 //*********************************************************************************
5447 IOService::reset_watchdog_timer(IOService
*blockedObject
, int pendingResponseTimeout
)
5453 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5458 IOLockLock(fWatchdogLock
);
5459 if (!fWatchdogDeadline
) {
5463 i
= fBlockedArray
->getNextIndexOfObject(blockedObject
, 0);
5464 if (pendingResponseTimeout
== 0) {
5465 blockedObject
->fPendingResponseDeadline
= 0;
5466 if (i
== (unsigned int)-1) {
5469 fBlockedArray
->removeObject(i
);
5471 // Set deadline 2secs after the expected response timeout to allow
5472 // ack timer to handle the timeout.
5473 clock_interval_to_deadline(pendingResponseTimeout
+ 2, kSecondScale
, &deadline
);
5475 if (i
!= (unsigned int)-1) {
5476 PM_ERROR("WDOG:Object %s is already blocked for responses. Ignoring timeout %d\n",
5477 fName
, pendingResponseTimeout
);
5481 for (i
= 0; i
< fBlockedArray
->getCount(); i
++) {
5482 obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(i
));
5483 if (obj
&& (obj
->fPendingResponseDeadline
< deadline
)) {
5484 blockedObject
->fPendingResponseDeadline
= deadline
;
5485 fBlockedArray
->setObject(i
, blockedObject
);
5489 if (i
== fBlockedArray
->getCount()) {
5490 blockedObject
->fPendingResponseDeadline
= deadline
;
5491 fBlockedArray
->setObject(blockedObject
);
5495 obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(0));
5497 int timeout
= getPMRootDomain()->getWatchdogTimeout();
5498 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5500 deadline
= obj
->fPendingResponseDeadline
;
5503 thread_call_cancel(fWatchdogTimer
);
5504 start_watchdog_timer(deadline
);
5507 IOLockUnlock(fWatchdogLock
);
5511 //*********************************************************************************
5512 // [static] watchdog_timer_expired
5514 // Inside PM work loop's gate.
5515 //*********************************************************************************
5518 IOService::watchdog_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5520 IOService
* me
= (IOService
*) arg0
;
5523 gIOPMWatchDogThread
= current_thread();
5524 getPMRootDomain()->sleepWakeDebugTrig(true);
5525 gIOPMWatchDogThread
= NULL
;
5526 thread_call_free(me
->fWatchdogTimer
);
5527 me
->fWatchdogTimer
= NULL
;
5534 IOService::getIOPMWorkloop( void )
5536 return gIOPMWorkLoop
;
5541 //*********************************************************************************
5542 // [private] start_ack_timer
5543 //*********************************************************************************
5546 IOService::start_ack_timer( void )
5548 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5552 IOService::start_ack_timer( UInt32 interval
, UInt32 scale
)
5554 AbsoluteTime deadline
;
5557 clock_interval_to_deadline(interval
, scale
, &deadline
);
5560 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5566 //*********************************************************************************
5567 // [private] stop_ack_timer
5568 //*********************************************************************************
5571 IOService::stop_ack_timer( void )
5575 pending
= thread_call_cancel(fAckTimer
);
5581 //*********************************************************************************
5582 // [static] actionAckTimerExpired
5584 // Inside PM work loop's gate.
5585 //*********************************************************************************
5588 IOService::actionAckTimerExpired(
5590 void * arg0
, void * arg1
,
5591 void * arg2
, void * arg3
)
5593 IOService
* me
= (IOService
*) target
;
5596 // done will be true if the timer tick unblocks the machine state,
5597 // otherwise no need to signal the work loop.
5599 done
= me
->ackTimerTick();
5600 if (done
&& gIOPMWorkQueue
) {
5601 gIOPMWorkQueue
->signalWorkAvailable();
5604 return kIOReturnSuccess
;
5607 //*********************************************************************************
5608 // ack_timer_expired
5610 // Thread call function. Holds a retain while the callout is in flight.
5611 //*********************************************************************************
5614 IOService::ack_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5616 IOService
* me
= (IOService
*) arg0
;
5618 if (gIOPMWorkLoop
) {
5619 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5626 // MARK: Client Messaging
5628 //*********************************************************************************
5629 // [private] tellSystemCapabilityChange
5630 //*********************************************************************************
5633 IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5636 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5637 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5640 // Notify app first on pre-change.
5641 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5643 // Notify kernel clients first on post-change.
5644 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5647 tellClientsWithResponse( fOutOfBandMessage
);
5650 //*********************************************************************************
5651 // [public] askChangeDown
5653 // Ask registered applications and kernel clients if we can change to a lower
5656 // Subclass can override this to send a different message type. Parameter is
5657 // the destination state number.
5659 // Return true if we don't have to wait for acknowledgements
5660 //*********************************************************************************
5663 IOService::askChangeDown( unsigned long stateNum
)
5665 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5668 //*********************************************************************************
5669 // [private] tellChangeDown1
5671 // Notify registered applications and kernel clients that we are definitely
5674 // Return true if we don't have to wait for acknowledgements
5675 //*********************************************************************************
5678 IOService::tellChangeDown1( unsigned long stateNum
)
5680 fOutOfBandParameter
= kNotifyApps
;
5681 return tellChangeDown(stateNum
);
5684 //*********************************************************************************
5685 // [private] tellChangeDown2
5687 // Notify priority clients that we are definitely dropping power.
5689 // Return true if we don't have to wait for acknowledgements
5690 //*********************************************************************************
5693 IOService::tellChangeDown2( unsigned long stateNum
)
5695 fOutOfBandParameter
= kNotifyPriority
;
5696 return tellChangeDown(stateNum
);
5699 //*********************************************************************************
5700 // [public] tellChangeDown
5702 // Notify registered applications and kernel clients that we are definitely
5705 // Subclass can override this to send a different message type. Parameter is
5706 // the destination state number.
5708 // Return true if we don't have to wait for acknowledgements
5709 //*********************************************************************************
5712 IOService::tellChangeDown( unsigned long stateNum
)
5714 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5717 //*********************************************************************************
5718 // cleanClientResponses
5720 //*********************************************************************************
5723 logAppTimeouts( OSObject
* object
, void * arg
)
5725 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5727 unsigned int clientIndex
;
5731 if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
5732 // Discover the 'counter' value or index assigned to this client
5733 // when it was notified, by searching for the array index of the
5734 // client in an array holding the cached interested clients.
5736 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5738 if ((clientIndex
!= (unsigned int) -1) &&
5739 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5740 (flag
!= kOSBooleanTrue
)) {
5741 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5745 pid
= clientID
->unsigned32BitValue();
5746 proc_name(pid
, name
, sizeof(name
));
5747 clientID
->release();
5750 PM_ERROR(context
->errorLog
, pid
, name
);
5752 // TODO: record message type if possible
5753 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5754 gIOPMStatsResponseTimedOut
,
5755 name
, 0, (30 * 1000), pid
, object
);
5761 IOService::cleanClientResponses( bool logErrors
)
5763 if (logErrors
&& fResponseArray
) {
5764 switch (fOutOfBandParameter
) {
5766 case kNotifyCapabilityChangeApps
:
5767 if (fNotifyClientArray
) {
5768 IOPMInterestContext context
;
5770 context
.responseArray
= fResponseArray
;
5771 context
.notifyClients
= fNotifyClientArray
;
5772 context
.serialNumber
= fSerialNumber
;
5773 context
.messageType
= kIOMessageCopyClientID
;
5774 context
.notifyType
= kNotifyApps
;
5775 context
.isPreChange
= fIsPreChange
;
5776 context
.enableTracing
= false;
5778 context
.maxTimeRequested
= 0;
5779 context
.stateNumber
= fHeadNotePowerState
;
5780 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5781 context
.changeFlags
= fHeadNoteChangeFlags
;
5782 context
.errorLog
= "PM notification timeout (pid %d, %s)\n";
5784 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5789 // kNotifyPriority, kNotifyCapabilityChangePriority
5790 // TODO: identify the priority client that has not acked
5791 PM_ERROR("PM priority notification timeout\n");
5792 if (gIOKitDebug
& kIOLogDebugPower
) {
5793 panic("PM priority notification timeout");
5799 if (IS_ROOT_DOMAIN
) {
5800 getPMRootDomain()->reset_watchdog_timer(this, 0);
5802 if (fResponseArray
) {
5803 fResponseArray
->release();
5804 fResponseArray
= NULL
;
5806 if (fNotifyClientArray
) {
5807 fNotifyClientArray
->release();
5808 fNotifyClientArray
= NULL
;
5812 //*********************************************************************************
5813 // [protected] tellClientsWithResponse
5815 // Notify registered applications and kernel clients that we are definitely
5818 // Return true if we don't have to wait for acknowledgements
5819 //*********************************************************************************
5822 IOService::tellClientsWithResponse( int messageType
)
5824 IOPMInterestContext context
;
5825 bool isRootDomain
= IS_ROOT_DOMAIN
;
5826 uint32_t maxTimeOut
= kMaxTimeRequested
;
5828 PM_ASSERT_IN_GATE();
5829 assert( fResponseArray
== NULL
);
5830 assert( fNotifyClientArray
== NULL
);
5832 if (messageType
== (int)kIOPMMessageLastCallBeforeSleep
) {
5833 RD_LOG("tellClientsWithResponse( kIOPMMessageLastCallBeforeSleep, %d )\n",
5834 fOutOfBandParameter
);
5836 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5837 getIOMessageString(messageType
), fOutOfBandParameter
);
5840 fResponseArray
= OSArray::withCapacity( 1 );
5841 if (!fResponseArray
) {
5845 fResponseArray
->setCapacityIncrement(8);
5846 if (++fSerialNumber
== 0) {
5850 context
.responseArray
= fResponseArray
;
5851 context
.notifyClients
= NULL
;
5852 context
.serialNumber
= fSerialNumber
;
5853 context
.messageType
= messageType
;
5854 context
.notifyType
= fOutOfBandParameter
;
5855 context
.skippedInDark
= 0;
5856 context
.notSkippedInDark
= 0;
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
.messageFilter
= (isRootDomain
) ?
5865 OSMemberFunctionCast(
5868 &IOPMrootDomain::systemMessageFilter
) : NULL
;
5870 switch (fOutOfBandParameter
) {
5872 applyToInterested( gIOAppPowerStateInterest
,
5873 pmTellAppWithResponse
, (void *) &context
);
5876 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5877 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
) &&
5878 (context
.messageType
!= kIOPMMessageLastCallBeforeSleep
)) {
5879 // Notify capability app for tellChangeDown1()
5880 // but not for askChangeDown().
5881 context
.notifyType
= kNotifyCapabilityChangeApps
;
5882 context
.messageType
= kIOMessageSystemCapabilityChange
;
5883 applyToInterested( gIOAppPowerStateInterest
,
5884 pmTellCapabilityAppWithResponse
, (void *) &context
);
5885 context
.notifyType
= fOutOfBandParameter
;
5886 context
.messageType
= messageType
;
5888 if (context
.messageType
== kIOMessageCanSystemSleep
) {
5889 maxTimeOut
= kCanSleepMaxTimeReq
;
5890 if (gCanSleepTimeout
) {
5891 maxTimeOut
= (gCanSleepTimeout
* us_per_s
);
5894 context
.maxTimeRequested
= maxTimeOut
;
5895 context
.enableTracing
= isRootDomain
;
5896 applyToInterested( gIOGeneralInterest
,
5897 pmTellClientWithResponse
, (void *) &context
);
5901 case kNotifyPriority
:
5902 context
.enableTracing
= isRootDomain
;
5903 applyToInterested( gIOPriorityPowerStateInterest
,
5904 pmTellClientWithResponse
, (void *) &context
);
5907 // Notify capability clients for tellChangeDown2().
5908 context
.notifyType
= kNotifyCapabilityChangePriority
;
5909 context
.messageType
= kIOMessageSystemCapabilityChange
;
5910 applyToInterested( gIOPriorityPowerStateInterest
,
5911 pmTellCapabilityClientWithResponse
, (void *) &context
);
5915 case kNotifyCapabilityChangeApps
:
5916 applyToInterested( gIOAppPowerStateInterest
,
5917 pmTellCapabilityAppWithResponse
, (void *) &context
);
5918 if (context
.messageType
== kIOMessageCanSystemSleep
) {
5919 maxTimeOut
= kCanSleepMaxTimeReq
;
5920 if (gCanSleepTimeout
) {
5921 maxTimeOut
= (gCanSleepTimeout
* us_per_s
);
5924 context
.maxTimeRequested
= maxTimeOut
;
5927 case kNotifyCapabilityChangePriority
:
5928 context
.enableTracing
= isRootDomain
;
5929 applyToInterested( gIOPriorityPowerStateInterest
,
5930 pmTellCapabilityClientWithResponse
, (void *) &context
);
5933 fNotifyClientArray
= context
.notifyClients
;
5935 if (context
.skippedInDark
) {
5936 IOLog("tellClientsWithResponse(%s, %d) %d of %d skipped in dark\n",
5937 getIOMessageString(messageType
), fOutOfBandParameter
,
5938 context
.skippedInDark
, context
.skippedInDark
+ context
.notSkippedInDark
);
5941 // do we have to wait for somebody?
5942 if (!checkForDone()) {
5943 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5944 if (context
.enableTracing
) {
5945 getPMRootDomain()->traceDetail(context
.messageType
, 0, context
.maxTimeRequested
/ 1000);
5946 getPMRootDomain()->reset_watchdog_timer(this, context
.maxTimeRequested
/ USEC_PER_SEC
+ 1);
5948 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5953 // everybody responded
5954 if (fResponseArray
) {
5955 fResponseArray
->release();
5956 fResponseArray
= NULL
;
5958 if (fNotifyClientArray
) {
5959 fNotifyClientArray
->release();
5960 fNotifyClientArray
= NULL
;
5966 //*********************************************************************************
5967 // [static private] pmTellAppWithResponse
5969 // We send a message to an application, and we expect a response, so we compute a
5970 // cookie we can identify the response with.
5971 //*********************************************************************************
5974 IOService::pmTellAppWithResponse( OSObject
* object
, void * arg
)
5976 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5977 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5978 uint32_t msgIndex
, msgRef
, msgType
;
5979 OSNumber
*clientID
= NULL
;
5981 boolean_t proc_suspended
= FALSE
;
5982 OSObject
* waitForReply
= kOSBooleanTrue
;
5983 #if LOG_APP_RESPONSE_TIMES
5987 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
5991 if (context
->us
== getPMRootDomain()) {
5992 if ((clientID
= copyClientIDForNotification(object
, context
))) {
5993 uint32_t clientPID
= clientID
->unsigned32BitValue();
5994 clientID
->release();
5995 proc
= proc_find(clientPID
);
5998 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
5999 if (proc_suspended
) {
6000 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
6001 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
6002 } else if (getPMRootDomain()->isAOTMode() && get_task_suspended((task_t
) proc
->task
)) {
6003 proc_suspended
= true;
6004 context
->skippedInDark
++;
6005 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
6008 if (proc_suspended
) {
6015 if (context
->messageFilter
&&
6016 !context
->messageFilter(context
->us
, object
, context
, NULL
, &waitForReply
)) {
6017 if (kIOLogDebugPower
& gIOKitDebug
) {
6018 logClientIDForNotification(object
, context
, "DROP App");
6022 context
->notSkippedInDark
++;
6024 // Create client array (for tracking purposes) only if the service
6025 // has app clients. Usually only root domain does.
6026 if (NULL
== context
->notifyClients
) {
6027 context
->notifyClients
= OSArray::withCapacity( 32 );
6030 msgType
= context
->messageType
;
6031 msgIndex
= context
->responseArray
->getCount();
6032 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6034 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6035 if (kIOLogDebugPower
& gIOKitDebug
) {
6036 logClientIDForNotification(object
, context
, "MESG App");
6039 if (waitForReply
== kOSBooleanTrue
) {
6041 clock_get_uptime(&now
);
6042 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6044 context
->responseArray
->setObject(msgIndex
, num
);
6047 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6050 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6051 if (kIOLogDebugPower
& gIOKitDebug
) {
6052 logClientIDForNotification(object
, context
, "App response ignored");
6056 if (context
->notifyClients
) {
6057 context
->notifyClients
->setObject(msgIndex
, object
);
6060 context
->us
->messageClient(msgType
, object
, (void *)(uintptr_t) msgRef
);
6063 //*********************************************************************************
6064 // [static private] pmTellClientWithResponse
6066 // We send a message to an in-kernel client, and we expect a response,
6067 // so we compute a cookie we can identify the response with.
6068 //*********************************************************************************
6071 IOService::pmTellClientWithResponse( OSObject
* object
, void * arg
)
6073 IOPowerStateChangeNotification notify
;
6074 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6075 OSObject
* replied
= kOSBooleanTrue
;
6076 _IOServiceInterestNotifier
* notifier
;
6077 uint32_t msgIndex
, msgRef
, msgType
;
6079 AbsoluteTime start
, end
;
6082 if (context
->messageFilter
&&
6083 !context
->messageFilter(context
->us
, object
, context
, NULL
, NULL
)) {
6084 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6085 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6086 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6087 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6088 context
->us
->getName(),
6089 getIOMessageString(context
->messageType
),
6090 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6095 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6096 msgType
= context
->messageType
;
6097 msgIndex
= context
->responseArray
->getCount();
6098 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6100 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6101 if (gIOKitDebug
& kIOLogPower
) {
6102 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6103 if (OSDynamicCast(IOService
, object
)) {
6104 const char *who
= ((IOService
*) object
)->getName();
6105 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6106 } else if (notifier
) {
6107 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6110 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
) {
6111 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6112 context
->us
->getName(),
6113 getIOMessageString(msgType
),
6114 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6117 if (NULL
== context
->notifyClients
) {
6118 context
->notifyClients
= OSArray::withCapacity( 32 );
6121 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
6122 notify
.returnValue
= 0;
6123 notify
.stateNumber
= context
->stateNumber
;
6124 notify
.stateFlags
= context
->stateFlags
;
6126 if (context
->enableTracing
&& (notifier
!= NULL
)) {
6127 getPMRootDomain()->traceDetail(notifier
, true);
6130 clock_get_uptime(&start
);
6131 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
6132 clock_get_uptime(&end
);
6134 if (context
->enableTracing
&& (notifier
!= NULL
)) {
6135 getPMRootDomain()->traceDetail(notifier
, false);
6139 if (kIOReturnSuccess
== retCode
) {
6140 if (0 == notify
.returnValue
) {
6141 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6142 context
->responseArray
->setObject(msgIndex
, replied
);
6144 replied
= kOSBooleanFalse
;
6145 if (notify
.returnValue
> context
->maxTimeRequested
) {
6146 if (notify
.returnValue
> kPriorityClientMaxWait
) {
6147 context
->maxTimeRequested
= kPriorityClientMaxWait
;
6148 PM_ERROR("%s: client %p returned %llu for %s\n",
6149 context
->us
->getName(),
6150 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6151 (uint64_t) notify
.returnValue
,
6152 getIOMessageString(msgType
));
6154 context
->maxTimeRequested
= notify
.returnValue
;
6158 // Track time taken to ack, by storing the timestamp of
6159 // callback completion
6161 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6163 context
->responseArray
->setObject(msgIndex
, num
);
6166 context
->responseArray
->setObject(msgIndex
, replied
);
6170 if (context
->enableTracing
) {
6171 SUB_ABSOLUTETIME(&end
, &start
);
6172 absolutetime_to_nanoseconds(end
, &nsec
);
6174 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (notify
.returnValue
!= 0)) {
6175 getPMRootDomain()->traceAckDelay(notifier
, notify
.returnValue
/ 1000, NS_TO_MS(nsec
));
6179 // not a client of ours
6180 // so we won't be waiting for response
6181 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6182 context
->responseArray
->setObject(msgIndex
, replied
);
6184 if (context
->notifyClients
) {
6185 context
->notifyClients
->setObject(msgIndex
, object
);
6189 //*********************************************************************************
6190 // [static private] pmTellCapabilityAppWithResponse
6191 //*********************************************************************************
6194 IOService::pmTellCapabilityAppWithResponse( OSObject
* object
, void * arg
)
6196 IOPMSystemCapabilityChangeParameters msgArg
;
6197 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6198 OSObject
* replied
= kOSBooleanTrue
;
6199 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6200 uint32_t msgIndex
, msgRef
, msgType
;
6201 #if LOG_APP_RESPONSE_TIMES
6205 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
6209 memset(&msgArg
, 0, sizeof(msgArg
));
6210 if (context
->messageFilter
&&
6211 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
)) {
6215 if (context
->us
== getPMRootDomain() &&
6216 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
6217 getPMRootDomain()->isAOTMode()
6218 #else /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
6220 #endif /* (defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
6222 OSNumber
*clientID
= NULL
;
6223 boolean_t proc_suspended
= FALSE
;
6225 if ((clientID
= copyClientIDForNotification(object
, context
))) {
6226 uint32_t clientPID
= clientID
->unsigned32BitValue();
6227 clientID
->release();
6228 proc
= proc_find(clientPID
);
6230 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6231 if (proc_suspended
) {
6232 logClientIDForNotification(object
, context
, "PMTellCapablityAppWithResponse - Suspended");
6233 } else if (get_task_suspended((task_t
) proc
->task
)) {
6234 proc_suspended
= true;
6235 context
->skippedInDark
++;
6238 if (proc_suspended
) {
6244 context
->notSkippedInDark
++;
6246 // Create client array (for tracking purposes) only if the service
6247 // has app clients. Usually only root domain does.
6248 if (NULL
== context
->notifyClients
) {
6249 context
->notifyClients
= OSArray::withCapacity( 32 );
6252 msgType
= context
->messageType
;
6253 msgIndex
= context
->responseArray
->getCount();
6254 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6256 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6257 if (kIOLogDebugPower
& gIOKitDebug
) {
6258 // Log client pid/name and client array index.
6259 OSNumber
* clientID
= NULL
;
6260 OSString
* clientIDString
= NULL
;;
6261 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6263 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6266 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
6267 context
->us
->getName(),
6268 msgIndex
, getIOMessageString(msgType
),
6269 (replied
!= kOSBooleanTrue
),
6270 clientIDString
? clientIDString
->getCStringNoCopy() : "");
6272 clientID
->release();
6274 if (clientIDString
) {
6275 clientIDString
->release();
6279 msgArg
.notifyRef
= msgRef
;
6280 msgArg
.maxWaitForReply
= 0;
6282 if (replied
== kOSBooleanTrue
) {
6283 msgArg
.notifyRef
= 0;
6284 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6285 if (context
->notifyClients
) {
6286 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
6290 clock_get_uptime(&now
);
6291 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6293 context
->responseArray
->setObject(msgIndex
, num
);
6296 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6299 if (context
->notifyClients
) {
6300 context
->notifyClients
->setObject(msgIndex
, object
);
6304 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6307 //*********************************************************************************
6308 // [static private] pmTellCapabilityClientWithResponse
6309 //*********************************************************************************
6312 IOService::pmTellCapabilityClientWithResponse(
6313 OSObject
* object
, void * arg
)
6315 IOPMSystemCapabilityChangeParameters msgArg
;
6316 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6317 OSObject
* replied
= kOSBooleanTrue
;
6318 _IOServiceInterestNotifier
* notifier
;
6319 uint32_t msgIndex
, msgRef
, msgType
;
6321 AbsoluteTime start
, end
;
6324 memset(&msgArg
, 0, sizeof(msgArg
));
6325 if (context
->messageFilter
&&
6326 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, NULL
)) {
6327 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6328 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6329 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6330 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6331 context
->us
->getName(),
6332 getIOMessageString(context
->messageType
),
6333 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6338 if (NULL
== context
->notifyClients
) {
6339 context
->notifyClients
= OSArray::withCapacity( 32 );
6341 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6342 msgType
= context
->messageType
;
6343 msgIndex
= context
->responseArray
->getCount();
6344 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6346 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6347 if (gIOKitDebug
& kIOLogPower
) {
6348 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6349 if (OSDynamicCast(IOService
, object
)) {
6350 const char *who
= ((IOService
*) object
)->getName();
6351 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6352 } else if (notifier
) {
6353 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6356 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
) {
6357 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6358 context
->us
->getName(),
6359 getIOMessageString(msgType
),
6360 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6363 msgArg
.notifyRef
= msgRef
;
6364 msgArg
.maxWaitForReply
= 0;
6366 if (context
->enableTracing
&& (notifier
!= NULL
)) {
6367 getPMRootDomain()->traceDetail(notifier
, true);
6370 clock_get_uptime(&start
);
6371 retCode
= context
->us
->messageClient(
6372 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6373 clock_get_uptime(&end
);
6374 if (context
->enableTracing
&& (notifier
!= NULL
)) {
6375 getPMRootDomain()->traceDetail(notifier
, false);
6378 if (kIOReturnSuccess
== retCode
) {
6379 if (0 == msgArg
.maxWaitForReply
) {
6380 // client doesn't want time to respond
6381 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6382 context
->responseArray
->setObject(msgIndex
, replied
);
6384 replied
= kOSBooleanFalse
;
6385 if (msgArg
.maxWaitForReply
> context
->maxTimeRequested
) {
6386 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
) {
6387 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
6388 PM_ERROR("%s: client %p returned %u for %s\n",
6389 context
->us
->getName(),
6390 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6391 msgArg
.maxWaitForReply
,
6392 getIOMessageString(msgType
));
6394 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6398 // Track time taken to ack, by storing the timestamp of
6399 // callback completion
6401 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6403 context
->responseArray
->setObject(msgIndex
, num
);
6406 context
->responseArray
->setObject(msgIndex
, replied
);
6410 if (context
->enableTracing
) {
6411 SUB_ABSOLUTETIME(&end
, &start
);
6412 absolutetime_to_nanoseconds(end
, &nsec
);
6414 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (msgArg
.maxWaitForReply
!= 0)) {
6415 getPMRootDomain()->traceAckDelay(notifier
, msgArg
.maxWaitForReply
/ 1000, NS_TO_MS(nsec
));
6419 // not a client of ours
6420 // so we won't be waiting for response
6421 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6422 context
->responseArray
->setObject(msgIndex
, replied
);
6424 if (context
->notifyClients
) {
6425 context
->notifyClients
->setObject(msgIndex
, object
);
6429 //*********************************************************************************
6430 // [public] tellNoChangeDown
6432 // Notify registered applications and kernel clients that we are not
6435 // Subclass can override this to send a different message type. Parameter is
6436 // the aborted destination state number.
6437 //*********************************************************************************
6440 IOService::tellNoChangeDown( unsigned long )
6442 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6445 //*********************************************************************************
6446 // [public] tellChangeUp
6448 // Notify registered applications and kernel clients that we are raising power.
6450 // Subclass can override this to send a different message type. Parameter is
6451 // the aborted destination state number.
6452 //*********************************************************************************
6455 IOService::tellChangeUp( unsigned long )
6457 return tellClients( kIOMessageDeviceHasPoweredOn
);
6460 //*********************************************************************************
6461 // [protected] tellClients
6463 // Notify registered applications and kernel clients of something.
6464 //*********************************************************************************
6467 IOService::tellClients( int messageType
)
6469 IOPMInterestContext context
;
6471 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6473 memset(&context
, 0, sizeof(context
));
6474 context
.messageType
= messageType
;
6475 context
.isPreChange
= fIsPreChange
;
6477 context
.stateNumber
= fHeadNotePowerState
;
6478 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6479 context
.changeFlags
= fHeadNoteChangeFlags
;
6480 context
.enableTracing
= IS_ROOT_DOMAIN
;
6481 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6482 OSMemberFunctionCast(
6485 &IOPMrootDomain::systemMessageFilter
) : NULL
;
6487 context
.notifyType
= kNotifyPriority
;
6488 applyToInterested( gIOPriorityPowerStateInterest
,
6489 tellKernelClientApplier
, (void *) &context
);
6491 context
.notifyType
= kNotifyApps
;
6492 applyToInterested( gIOAppPowerStateInterest
,
6493 tellAppClientApplier
, (void *) &context
);
6495 applyToInterested( gIOGeneralInterest
,
6496 tellKernelClientApplier
, (void *) &context
);
6499 //*********************************************************************************
6500 // [private] tellKernelClientApplier
6502 // Message a kernel client.
6503 //*********************************************************************************
6506 tellKernelClientApplier( OSObject
* object
, void * arg
)
6508 IOPowerStateChangeNotification notify
;
6509 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6511 if (context
->messageFilter
&&
6512 !context
->messageFilter(context
->us
, object
, context
, NULL
, NULL
)) {
6513 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6514 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6515 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6516 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6517 context
->us
->getName(),
6518 IOService::getIOMessageString(context
->messageType
),
6519 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6524 notify
.powerRef
= (void *) NULL
;
6525 notify
.returnValue
= 0;
6526 notify
.stateNumber
= context
->stateNumber
;
6527 notify
.stateFlags
= context
->stateFlags
;
6529 if (context
->enableTracing
&& object
) {
6530 IOService::getPMRootDomain()->traceDetail(object
, true);
6532 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6533 if (context
->enableTracing
&& object
) {
6534 IOService::getPMRootDomain()->traceDetail(object
, false);
6539 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6540 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6541 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6542 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6543 context
->us
->getName(),
6544 IOService::getIOMessageString(context
->messageType
),
6545 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6550 copyClientIDForNotification(
6552 IOPMInterestContext
*context
)
6554 OSNumber
*clientID
= NULL
;
6555 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6560 logClientIDForNotification(
6562 IOPMInterestContext
*context
,
6563 const char *logString
)
6565 OSString
*logClientID
= NULL
;
6566 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6570 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6573 PM_LOG("%s %s %s, %s\n",
6574 context
->us
->getName(), logString
,
6575 IOService::getIOMessageString(context
->messageType
),
6576 logClientID
? logClientID
->getCStringNoCopy() : "");
6579 logClientID
->release();
6584 clientID
->release();
6591 tellAppClientApplier( OSObject
* object
, void * arg
)
6593 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6594 OSNumber
* clientID
= NULL
;
6596 boolean_t proc_suspended
= FALSE
;
6598 if (context
->us
== IOService::getPMRootDomain()) {
6599 if ((clientID
= copyClientIDForNotification(object
, context
))) {
6600 uint32_t clientPID
= clientID
->unsigned32BitValue();
6601 clientID
->release();
6602 proc
= proc_find(clientPID
);
6605 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6606 if (proc_suspended
) {
6607 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6608 #if !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146))
6609 } else if (IOService::getPMRootDomain()->isAOTMode() && get_task_suspended((task_t
) proc
->task
)) {
6610 proc_suspended
= true;
6611 context
->skippedInDark
++;
6612 #endif /* !(defined(RC_HIDE_N144) || defined(RC_HIDE_N146)) */
6615 if (proc_suspended
) {
6622 if (context
->messageFilter
&&
6623 !context
->messageFilter(context
->us
, object
, context
, NULL
, NULL
)) {
6624 if (kIOLogDebugPower
& gIOKitDebug
) {
6625 logClientIDForNotification(object
, context
, "DROP App");
6629 context
->notSkippedInDark
++;
6631 if (kIOLogDebugPower
& gIOKitDebug
) {
6632 logClientIDForNotification(object
, context
, "MESG App");
6635 context
->us
->messageClient(context
->messageType
, object
, NULL
);
6638 //*********************************************************************************
6639 // [private] checkForDone
6640 //*********************************************************************************
6643 IOService::checkForDone( void )
6648 if (fResponseArray
== NULL
) {
6653 theFlag
= fResponseArray
->getObject(i
);
6655 if (NULL
== theFlag
) {
6659 if (kOSBooleanTrue
!= theFlag
) {
6666 //*********************************************************************************
6667 // [public] responseValid
6668 //*********************************************************************************
6671 IOService::responseValid( uint32_t refcon
, int pid
)
6673 UInt16 serialComponent
;
6674 UInt16 ordinalComponent
;
6676 OSObject
*object
= NULL
;
6678 serialComponent
= (refcon
>> 16) & 0xFFFF;
6679 ordinalComponent
= (refcon
& 0xFFFF);
6681 if (serialComponent
!= fSerialNumber
) {
6685 if (fResponseArray
== NULL
) {
6689 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6691 if (theFlag
== NULL
) {
6695 if (fNotifyClientArray
) {
6696 object
= fNotifyClientArray
->getObject(ordinalComponent
);
6700 if ((num
= OSDynamicCast(OSNumber
, theFlag
))) {
6706 clock_get_uptime(&now
);
6707 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6708 SUB_ABSOLUTETIME(&now
, &start
);
6709 absolutetime_to_nanoseconds(now
, &nsec
);
6713 proc_name(pid
, name
, sizeof(name
));
6715 if (nsec
> LOG_APP_RESPONSE_TIMES
) {
6716 IOLog("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec
),
6721 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
) {
6722 // TODO: populate the messageType argument
6723 getPMRootDomain()->pmStatsRecordApplicationResponse(
6724 gIOPMStatsResponseSlow
,
6725 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6727 getPMRootDomain()->pmStatsRecordApplicationResponse(
6728 gIOPMStatsResponsePrompt
,
6729 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6732 getPMRootDomain()->traceAckDelay(object
, 0, NS_TO_MS(nsec
));
6735 if (kIOLogDebugPower
& gIOKitDebug
) {
6736 PM_LOG("Ack(%u) %u ms\n",
6737 (uint32_t) ordinalComponent
,
6740 theFlag
= kOSBooleanFalse
;
6741 } else if (object
) {
6742 getPMRootDomain()->pmStatsRecordApplicationResponse(
6743 gIOPMStatsResponsePrompt
,
6744 NULL
, 0, 0, pid
, object
);
6747 if (kOSBooleanFalse
== theFlag
) {
6748 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6754 //*********************************************************************************
6755 // [public] allowPowerChange
6757 // Our power state is about to lower, and we have notified applications
6758 // and kernel clients, and one of them has acknowledged. If this is the last to do
6759 // so, and all acknowledgements are positive, we continue with the power change.
6760 //*********************************************************************************
6763 IOService::allowPowerChange( unsigned long refcon
)
6765 IOPMRequest
* request
;
6769 return kIOReturnSuccess
;
6772 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6774 return kIOReturnNoMemory
;
6777 request
->fArg0
= (void *) refcon
;
6778 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6779 request
->fArg2
= (void *) NULL
;
6780 submitPMRequest( request
);
6782 return kIOReturnSuccess
;
6787 IOService::serializedAllowPowerChange2( unsigned long refcon
)
6789 // [deprecated] public
6790 return kIOReturnUnsupported
;
6792 #endif /* !__LP64__ */
6794 //*********************************************************************************
6795 // [public] cancelPowerChange
6797 // Our power state is about to lower, and we have notified applications
6798 // and kernel clients, and one of them has vetoed the change. If this is the last
6799 // client to respond, we abandon the power change.
6800 //*********************************************************************************
6803 IOService::cancelPowerChange( unsigned long refcon
)
6805 IOPMRequest
* request
;
6807 pid_t pid
= proc_selfpid();
6811 return kIOReturnSuccess
;
6815 proc_name(pid
, name
, sizeof(name
));
6816 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid
, name
);
6818 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6820 return kIOReturnNoMemory
;
6823 request
->fArg0
= (void *) refcon
;
6824 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6825 request
->fArg2
= (void *) OSString::withCString(name
);
6826 submitPMRequest( request
);
6828 return kIOReturnSuccess
;
6831 //*********************************************************************************
6832 // cancelIdlePowerDown
6834 // Internal method to trigger an idle cancel or revert
6835 //*********************************************************************************
6838 IOService::cancelIdlePowerDown( IOService
* service
)
6840 IOPMRequest
* request
;
6842 request
= acquirePMRequest(service
, kIOPMRequestTypeIdleCancel
);
6844 submitPMRequest(request
);
6850 IOService::serializedCancelPowerChange2( unsigned long refcon
)
6852 // [deprecated] public
6853 return kIOReturnUnsupported
;
6856 //*********************************************************************************
6857 // PM_Clamp_Timer_Expired
6859 // called when clamp timer expires...set power state to 0.
6860 //*********************************************************************************
6863 IOService::PM_Clamp_Timer_Expired( void )
6867 //*********************************************************************************
6870 // Set to highest available power state for a minimum of duration milliseconds
6871 //*********************************************************************************
6874 IOService::clampPowerOn( unsigned long duration
)
6877 #endif /* !__LP64__ */
6879 //*********************************************************************************
6880 // configurePowerStateReport
6882 // Configures the IOStateReport for kPMPowerStateChannel
6883 //*********************************************************************************
6885 IOService::configurePowerStatesReport( IOReportConfigureAction action
, void *result
)
6887 IOReturn rc
= kIOReturnSuccess
;
6893 return kIOReturnUnsupported
;
6896 if (!fNumberOfPowerStates
) {
6897 return kIOReturnSuccess
; // For drivers which are in power plane, but haven't called registerPowerDriver()
6902 case kIOReportEnable
:
6907 reportSize
= STATEREPORT_BUFSIZE(fNumberOfPowerStates
);
6908 fReportBuf
= IOMalloc(reportSize
);
6910 rc
= kIOReturnNoMemory
;
6913 memset(fReportBuf
, 0, reportSize
);
6915 STATEREPORT_INIT(fNumberOfPowerStates
, fReportBuf
, reportSize
,
6916 getRegistryEntryID(), kPMPowerStatesChID
, kIOReportCategoryPower
);
6918 for (i
= 0; i
< fNumberOfPowerStates
; i
++) {
6921 if (fPowerStates
[i
].capabilityFlags
& kIOPMPowerOn
) {
6922 bits
|= kPMReportPowerOn
;
6924 if (fPowerStates
[i
].capabilityFlags
& kIOPMDeviceUsable
) {
6925 bits
|= kPMReportDeviceUsable
;
6927 if (fPowerStates
[i
].capabilityFlags
& kIOPMLowPower
) {
6928 bits
|= kPMReportLowPower
;
6931 STATEREPORT_SETSTATEID(fReportBuf
, i
, ((bits
& 0xff) << 8) |
6932 ((StateOrder(fMaxPowerState
) & 0xf) << 4) | (StateOrder(i
) & 0xf));
6934 ts
= mach_absolute_time();
6935 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
6938 case kIOReportDisable
:
6939 if (fReportClientCnt
== 0) {
6940 rc
= kIOReturnBadArgument
;
6943 if (fReportClientCnt
== 1) {
6944 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
6950 case kIOReportGetDimensions
:
6952 STATEREPORT_UPDATERES(fReportBuf
, kIOReportGetDimensions
, result
);
6962 //*********************************************************************************
6963 // updatePowerStateReport
6965 // Updates the IOStateReport for kPMPowerStateChannel
6966 //*********************************************************************************
6968 IOService::updatePowerStatesReport( IOReportConfigureAction action
, void *result
, void *destination
)
6973 IOReturn rc
= kIOReturnSuccess
;
6974 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6978 return kIOReturnUnsupported
;
6980 if (!fNumberOfPowerStates
) {
6981 return kIOReturnSuccess
;
6984 if (!result
|| !dest
) {
6985 return kIOReturnBadArgument
;
6990 case kIOReportCopyChannelData
:
6992 rc
= kIOReturnNotOpen
;
6996 ts
= mach_absolute_time();
6997 STATEREPORT_UPDATEPREP(fReportBuf
, ts
, data2cpy
, size2cpy
);
6998 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
6999 rc
= kIOReturnOverrun
;
7003 STATEREPORT_UPDATERES(fReportBuf
, kIOReportCopyChannelData
, result
);
7004 dest
->appendBytes(data2cpy
, size2cpy
);
7016 //*********************************************************************************
7017 // configureSimplePowerReport
7019 // Configures the IOSimpleReport for given channel id
7020 //*********************************************************************************
7022 IOService::configureSimplePowerReport(IOReportConfigureAction action
, void *result
)
7024 IOReturn rc
= kIOReturnSuccess
;
7027 return kIOReturnUnsupported
;
7030 if (!fNumberOfPowerStates
) {
7035 case kIOReportEnable
:
7036 case kIOReportDisable
:
7039 case kIOReportGetDimensions
:
7040 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
7048 //*********************************************************************************
7049 // updateSimplePowerReport
7051 // Updates the IOSimpleReport for the given chanel id
7052 //*********************************************************************************
7054 IOService::updateSimplePowerReport( IOReportConfigureAction action
, void *result
, void *destination
)
7058 uint64_t buf
[SIMPLEREPORT_BUFSIZE
/ sizeof(uint64_t) + 1]; // Force a 8-byte alignment
7059 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
7060 IOReturn rc
= kIOReturnSuccess
;
7065 return kIOReturnUnsupported
;
7067 if (!result
|| !dest
) {
7068 return kIOReturnBadArgument
;
7071 if (!fNumberOfPowerStates
) {
7077 case kIOReportCopyChannelData
:
7079 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), kPMCurrStateChID
, kIOReportCategoryPower
);
7081 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMPowerOn
) {
7082 bits
|= kPMReportPowerOn
;
7084 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMDeviceUsable
) {
7085 bits
|= kPMReportDeviceUsable
;
7087 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMLowPower
) {
7088 bits
|= kPMReportLowPower
;
7092 SIMPLEREPORT_SETVALUE(buf
, ((bits
& 0xff) << 8) | ((StateOrder(fMaxPowerState
) & 0xf) << 4) |
7093 (StateOrder(fCurrentPowerState
) & 0xf));
7095 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
7096 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
7097 rc
= kIOReturnOverrun
;
7101 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
7102 dest
->appendBytes(data2cpy
, size2cpy
);
7111 return kIOReturnSuccess
;
7117 // MARK: Driver Overrides
7119 //*********************************************************************************
7120 // [public] setPowerState
7122 // Does nothing here. This should be implemented in a subclass driver.
7123 //*********************************************************************************
7126 IOService::setPowerState(
7127 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
7132 //*********************************************************************************
7133 // [public] maxCapabilityForDomainState
7135 // Finds the highest power state in the array whose input power requirement
7136 // is equal to the input parameter. Where a more intelligent decision is
7137 // possible, override this in the subclassed driver.
7138 //*********************************************************************************
7141 IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags
)
7143 IOPMPowerStateIndex stateIndex
;
7145 if (!fNumberOfPowerStates
) {
7146 return kPowerStateZero
;
7149 for (int order
= fNumberOfPowerStates
- 1; order
>= 0; order
--) {
7150 stateIndex
= fPowerStates
[order
].stateOrderToIndex
;
7152 if ((flags
& fPowerStates
[stateIndex
].inputPowerFlags
) ==
7153 fPowerStates
[stateIndex
].inputPowerFlags
) {
7157 return kPowerStateZero
;
7161 IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState
)
7163 return getPowerStateForDomainFlags(domainState
);
7166 //*********************************************************************************
7167 // [public] initialPowerStateForDomainState
7169 // Called to query the power state for the initial power transition.
7170 //*********************************************************************************
7173 IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState
)
7175 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
)) {
7176 // Return lowest power state for any root power domain changes
7177 return kPowerStateZero
;
7180 return getPowerStateForDomainFlags(domainState
);
7183 //*********************************************************************************
7184 // [public] powerStateForDomainState
7186 // This method is not called from PM.
7187 //*********************************************************************************
7190 IOService::powerStateForDomainState( IOPMPowerFlags domainState
)
7192 return getPowerStateForDomainFlags(domainState
);
7196 //*********************************************************************************
7197 // [deprecated] didYouWakeSystem
7199 // Does nothing here. This should be implemented in a subclass driver.
7200 //*********************************************************************************
7203 IOService::didYouWakeSystem( void )
7207 #endif /* !__LP64__ */
7209 //*********************************************************************************
7210 // [public] powerStateWillChangeTo
7212 // Does nothing here. This should be implemented in a subclass driver.
7213 //*********************************************************************************
7216 IOService::powerStateWillChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7218 return kIOPMAckImplied
;
7221 //*********************************************************************************
7222 // [public] powerStateDidChangeTo
7224 // Does nothing here. This should be implemented in a subclass driver.
7225 //*********************************************************************************
7228 IOService::powerStateDidChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7230 return kIOPMAckImplied
;
7233 //*********************************************************************************
7234 // [protected] powerChangeDone
7236 // Called from PM work loop thread.
7237 // Does nothing here. This should be implemented in a subclass policy-maker.
7238 //*********************************************************************************
7241 IOService::powerChangeDone( unsigned long )
7246 //*********************************************************************************
7247 // [deprecated] newTemperature
7249 // Does nothing here. This should be implemented in a subclass driver.
7250 //*********************************************************************************
7253 IOService::newTemperature( long currentTemp
, IOService
* whichZone
)
7257 #endif /* !__LP64__ */
7259 //*********************************************************************************
7260 // [public] systemWillShutdown
7262 // System shutdown and restart notification.
7263 //*********************************************************************************
7266 IOService::systemWillShutdown( IOOptionBits specifier
)
7268 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
7270 rootDomain
->acknowledgeSystemWillShutdown( this );
7275 // MARK: PM State Machine
7277 //*********************************************************************************
7278 // [private static] acquirePMRequest
7279 //*********************************************************************************
7282 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
7283 IOPMRequest
* active
)
7285 IOPMRequest
* request
;
7289 request
= IOPMRequest::create();
7291 request
->init( target
, requestType
);
7293 IOPMRequest
* root
= active
->getRootRequest();
7295 request
->attachRootRequest(root
);
7299 PM_ERROR("%s: No memory for PM request type 0x%x\n",
7300 target
->getName(), (uint32_t) requestType
);
7305 //*********************************************************************************
7306 // [private static] releasePMRequest
7307 //*********************************************************************************
7310 IOService::releasePMRequest( IOPMRequest
* request
)
7318 //*********************************************************************************
7319 // [private static] submitPMRequest
7320 //*********************************************************************************
7323 IOService::submitPMRequest( IOPMRequest
* request
)
7326 assert( gIOPMReplyQueue
);
7327 assert( gIOPMRequestQueue
);
7329 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7330 (long)request
->getType(), OBFUSCATE(request
),
7331 OBFUSCATE(request
->getTarget()), request
->getTarget()->getName(),
7332 OBFUSCATE(request
->fArg0
),
7333 OBFUSCATE(request
->fArg1
), OBFUSCATE(request
->fArg2
));
7335 if (request
->isReplyType()) {
7336 gIOPMReplyQueue
->queuePMRequest( request
);
7338 gIOPMRequestQueue
->queuePMRequest( request
);
7343 IOService::submitPMRequests( IOPMRequest
** requests
, IOItemCount count
)
7346 assert( count
> 0 );
7347 assert( gIOPMRequestQueue
);
7349 for (IOItemCount i
= 0; i
< count
; i
++) {
7350 IOPMRequest
* req
= requests
[i
];
7351 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7352 (long)req
->getType(), OBFUSCATE(req
),
7353 OBFUSCATE(req
->getTarget()), req
->getTarget()->getName(),
7354 OBFUSCATE(req
->fArg0
),
7355 OBFUSCATE(req
->fArg1
), OBFUSCATE(req
->fArg2
));
7358 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
7361 //*********************************************************************************
7362 // [private] actionPMRequestQueue
7364 // IOPMRequestQueue::checkForWork() passing a new request to the request target.
7365 //*********************************************************************************
7368 IOService::actionPMRequestQueue(
7369 IOPMRequest
* request
,
7370 IOPMRequestQueue
* queue
)
7375 // Work queue will immediately execute the request if the per-service
7376 // request queue is empty. Note pwrMgt is the target's IOServicePM.
7378 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
7380 // Calling PM without PMinit() is not allowed, fail the request.
7381 // Need to signal more when completing attached requests.
7383 PM_LOG("%s: PM not initialized\n", getName());
7384 PM_LOG1("[- %02x] %p [%p %s] !initialized\n",
7385 request
->getType(), OBFUSCATE(request
),
7386 OBFUSCATE(this), getName());
7388 more
= gIOPMCompletionQueue
->queuePMRequest(request
);
7390 gIOPMWorkQueue
->incrementProducerCount();
7397 //*********************************************************************************
7398 // [private] actionPMCompletionQueue
7400 // IOPMCompletionQueue::checkForWork() passing a completed request to the
7402 //*********************************************************************************
7405 IOService::actionPMCompletionQueue(
7406 IOPMRequest
* request
,
7407 IOPMCompletionQueue
* queue
)
7409 bool more
= (request
->getNextRequest() != NULL
);
7410 IOPMRequest
* root
= request
->getRootRequest();
7412 if (root
&& (root
!= request
)) {
7416 gIOPMWorkQueue
->incrementProducerCount();
7419 releasePMRequest( request
);
7423 //*********************************************************************************
7424 // [private] actionPMWorkQueueRetire
7426 // IOPMWorkQueue::checkForWork() passing a retired request to the request target.
7427 //*********************************************************************************
7430 IOService::actionPMWorkQueueRetire( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7432 assert(request
&& queue
);
7434 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7435 request
->getType(), OBFUSCATE(request
),
7436 OBFUSCATE(this), getName(),
7437 fMachineState
, gIOPMBusyRequestCount
);
7439 // Catch requests created by idleTimerExpired()
7440 if (request
->getType() == kIOPMRequestTypeActivityTickle
) {
7441 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
7443 if ((tickleFlags
& kTickleTypePowerDrop
) && fIdleTimerPeriod
) {
7445 } else if (tickleFlags
== (kTickleTypeActivity
| kTickleTypePowerRise
)) {
7446 // Invalidate any idle power drop that got queued while
7447 // processing this request.
7448 fIdleTimerGeneration
++;
7452 // When the completed request is linked, tell work queue there is
7453 // more work pending.
7455 return gIOPMCompletionQueue
->queuePMRequest( request
);
7458 //*********************************************************************************
7459 // [private] isPMBlocked
7461 // Check if machine state transition is blocked.
7462 //*********************************************************************************
7465 IOService::isPMBlocked( IOPMRequest
* request
, int count
)
7470 if (kIOPM_Finished
== fMachineState
) {
7474 if (kIOPM_DriverThreadCallDone
== fMachineState
) {
7475 // 5 = kDriverCallInformPreChange
7476 // 6 = kDriverCallInformPostChange
7477 // 7 = kDriverCallSetPowerState
7478 // 8 = kRootDomainInformPreChange
7479 if (fDriverCallBusy
) {
7480 reason
= 5 + fDriverCallReason
;
7485 // Waiting on driver's setPowerState() timeout.
7490 // Child or interested driver acks pending.
7491 if (fHeadNotePendingAcks
) {
7495 // Waiting on apps or priority power interest clients.
7496 if (fResponseArray
) {
7500 // Waiting on settle timer expiration.
7501 if (fSettleTimeUS
) {
7506 fWaitReason
= reason
;
7510 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7511 request
->getType(), OBFUSCATE(request
),
7512 OBFUSCATE(this), getName(),
7513 fMachineState
, reason
);
7522 //*********************************************************************************
7523 // [private] actionPMWorkQueueInvoke
7525 // IOPMWorkQueue::checkForWork() passing a request to the
7526 // request target for execution.
7527 //*********************************************************************************
7530 IOService::actionPMWorkQueueInvoke( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7535 assert(request
&& queue
);
7537 while (isPMBlocked(request
, loop
++) == false) {
7538 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7539 request
->getType(), OBFUSCATE(request
),
7540 OBFUSCATE(this), getName(), fMachineState
);
7542 gIOPMRequest
= request
;
7543 gIOPMWorkInvokeCount
++;
7545 // Every PM machine states must be handled in one of the cases below.
7547 switch (fMachineState
) {
7548 case kIOPM_Finished
:
7549 start_watchdog_timer();
7551 executePMRequest( request
);
7554 case kIOPM_OurChangeTellClientsPowerDown
:
7555 // Root domain might self cancel due to assertions.
7556 if (IS_ROOT_DOMAIN
) {
7557 bool cancel
= (bool) fDoNotPowerDown
;
7558 getPMRootDomain()->askChangeDownDone(
7559 &fHeadNoteChangeFlags
, &cancel
);
7560 fDoNotPowerDown
= cancel
;
7563 // askChangeDown() done, was it vetoed?
7564 if (!fDoNotPowerDown
) {
7565 // no, we can continue
7566 OurChangeTellClientsPowerDown();
7568 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7569 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7570 if (IS_ROOT_DOMAIN
) {
7571 // RootDomain already sent "WillSleep" to its clients
7572 tellChangeUp(fCurrentPowerState
);
7574 tellNoChangeDown(fHeadNotePowerState
);
7576 // mark the change note un-actioned
7577 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7583 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
7584 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7585 if (fDoNotPowerDown
) {
7586 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7587 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7588 if (IS_ROOT_DOMAIN
) {
7589 // RootDomain already sent "WillSleep" to its clients
7590 tellChangeUp(fCurrentPowerState
);
7592 tellNoChangeDown(fHeadNotePowerState
);
7594 // mark the change note un-actioned
7595 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7599 OurChangeTellUserPMPolicyPowerDown();
7603 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
7604 // PMRD: LastCallBeforeSleep notify done
7605 // Non-PMRD: tellChangeDown/kNotifyApps done
7606 if (fDoNotPowerDown
) {
7607 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7608 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7609 // no, tell clients we're back in the old state
7610 tellChangeUp(fCurrentPowerState
);
7611 // mark the change note un-actioned
7612 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7616 // yes, we can continue
7617 OurChangeTellPriorityClientsPowerDown();
7621 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
7622 OurChangeNotifyInterestedDriversWillChange();
7625 case kIOPM_OurChangeSetPowerState
:
7626 OurChangeSetPowerState();
7629 case kIOPM_OurChangeWaitForPowerSettle
:
7630 OurChangeWaitForPowerSettle();
7633 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
7634 OurChangeNotifyInterestedDriversDidChange();
7637 case kIOPM_OurChangeTellCapabilityDidChange
:
7638 OurChangeTellCapabilityDidChange();
7641 case kIOPM_OurChangeFinish
:
7645 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
7646 ParentChangeTellPriorityClientsPowerDown();
7649 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
7650 ParentChangeNotifyInterestedDriversWillChange();
7653 case kIOPM_ParentChangeSetPowerState
:
7654 ParentChangeSetPowerState();
7657 case kIOPM_ParentChangeWaitForPowerSettle
:
7658 ParentChangeWaitForPowerSettle();
7661 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7662 ParentChangeNotifyInterestedDriversDidChange();
7665 case kIOPM_ParentChangeTellCapabilityDidChange
:
7666 ParentChangeTellCapabilityDidChange();
7669 case kIOPM_ParentChangeAcknowledgePowerChange
:
7670 ParentChangeAcknowledgePowerChange();
7673 case kIOPM_DriverThreadCallDone
:
7674 switch (fDriverCallReason
) {
7675 case kDriverCallInformPreChange
:
7676 case kDriverCallInformPostChange
:
7677 notifyInterestedDriversDone();
7679 case kDriverCallSetPowerState
:
7680 notifyControllingDriverDone();
7682 case kRootDomainInformPreChange
:
7683 notifyRootDomainDone();
7686 panic("%s: bad call reason %x",
7687 getName(), fDriverCallReason
);
7691 case kIOPM_NotifyChildrenOrdered
:
7692 notifyChildrenOrdered();
7695 case kIOPM_NotifyChildrenDelayed
:
7696 notifyChildrenDelayed();
7699 case kIOPM_NotifyChildrenStart
:
7700 // pop notifyAll() state saved by notifyInterestedDriversDone()
7705 case kIOPM_SyncTellClientsPowerDown
:
7706 // Root domain might self cancel due to assertions.
7707 if (IS_ROOT_DOMAIN
) {
7708 bool cancel
= (bool) fDoNotPowerDown
;
7709 getPMRootDomain()->askChangeDownDone(
7710 &fHeadNoteChangeFlags
, &cancel
);
7711 fDoNotPowerDown
= cancel
;
7713 if (!fDoNotPowerDown
) {
7714 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7715 fOutOfBandParameter
= kNotifyApps
;
7716 tellChangeDown(fHeadNotePowerState
);
7718 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7719 // askChangeDown/kNotifyApps
7720 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7721 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7722 tellNoChangeDown(fHeadNotePowerState
);
7723 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7728 case kIOPM_SyncTellPriorityClientsPowerDown
:
7729 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7730 if (!fDoNotPowerDown
) {
7731 fMachineState
= kIOPM_SyncNotifyWillChange
;
7732 fOutOfBandParameter
= kNotifyPriority
;
7733 tellChangeDown(fHeadNotePowerState
);
7735 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7736 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7737 tellChangeUp(fCurrentPowerState
);
7738 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7743 case kIOPM_SyncNotifyWillChange
:
7744 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
) {
7745 fMachineState
= kIOPM_SyncFinish
;
7748 fMachineState
= kIOPM_SyncNotifyDidChange
;
7749 fDriverCallReason
= kDriverCallInformPreChange
;
7753 case kIOPM_SyncNotifyDidChange
:
7754 fIsPreChange
= false;
7756 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
7757 fMachineState
= kIOPM_SyncFinish
;
7759 assert(IS_ROOT_DOMAIN
);
7760 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7763 fDriverCallReason
= kDriverCallInformPostChange
;
7767 case kIOPM_SyncTellCapabilityDidChange
:
7768 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7771 case kIOPM_SyncFinish
:
7772 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
7773 ParentChangeAcknowledgePowerChange();
7779 case kIOPM_TellCapabilityChangeDone
:
7781 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
) {
7782 MS_POP(); // tellSystemCapabilityChange()
7785 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7787 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
) {
7788 MS_POP(); // tellSystemCapabilityChange()
7791 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7793 tellClientsWithResponse( fOutOfBandMessage
);
7797 panic("PMWorkQueueInvoke: unknown machine state %x",
7801 gIOPMRequest
= NULL
;
7803 if (fMachineState
== kIOPM_Finished
) {
7804 stop_watchdog_timer();
7813 //*********************************************************************************
7814 // [private] executePMRequest
7815 //*********************************************************************************
7818 IOService::executePMRequest( IOPMRequest
* request
)
7820 assert( kIOPM_Finished
== fMachineState
);
7822 switch (request
->getType()) {
7823 case kIOPMRequestTypePMStop
:
7824 handlePMstop( request
);
7827 case kIOPMRequestTypeAddPowerChild1
:
7828 addPowerChild1( request
);
7831 case kIOPMRequestTypeAddPowerChild2
:
7832 addPowerChild2( request
);
7835 case kIOPMRequestTypeAddPowerChild3
:
7836 addPowerChild3( request
);
7839 case kIOPMRequestTypeRegisterPowerDriver
:
7840 handleRegisterPowerDriver( request
);
7843 case kIOPMRequestTypeAdjustPowerState
:
7844 fAdjustPowerScheduled
= false;
7848 case kIOPMRequestTypePowerDomainWillChange
:
7849 handlePowerDomainWillChangeTo( request
);
7852 case kIOPMRequestTypePowerDomainDidChange
:
7853 handlePowerDomainDidChangeTo( request
);
7856 case kIOPMRequestTypeRequestPowerState
:
7857 case kIOPMRequestTypeRequestPowerStateOverride
:
7858 handleRequestPowerState( request
);
7861 case kIOPMRequestTypePowerOverrideOnPriv
:
7862 case kIOPMRequestTypePowerOverrideOffPriv
:
7863 handlePowerOverrideChanged( request
);
7866 case kIOPMRequestTypeActivityTickle
:
7867 handleActivityTickle( request
);
7870 case kIOPMRequestTypeSynchronizePowerTree
:
7871 handleSynchronizePowerTree( request
);
7874 case kIOPMRequestTypeSetIdleTimerPeriod
:
7876 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7877 fNextIdleTimerPeriod
= fIdleTimerPeriod
;
7878 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0)) {
7884 case kIOPMRequestTypeIgnoreIdleTimer
:
7885 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7888 case kIOPMRequestTypeQuiescePowerTree
:
7889 gIOPMWorkQueue
->finishQuiesceRequest(request
);
7893 panic("executePMRequest: unknown request type %x", request
->getType());
7897 //*********************************************************************************
7898 // [private] actionPMReplyQueue
7900 // IOPMRequestQueue::checkForWork() passing a reply-type request to the
7902 //*********************************************************************************
7905 IOService::actionPMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7909 assert( request
&& queue
);
7910 assert( request
->isReplyType());
7912 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7913 request
->getType(), OBFUSCATE(request
),
7914 OBFUSCATE(this), getName(), fMachineState
);
7916 switch (request
->getType()) {
7917 case kIOPMRequestTypeAllowPowerChange
:
7918 case kIOPMRequestTypeCancelPowerChange
:
7919 // Check if we are expecting this response.
7920 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7921 (int)(uintptr_t) request
->fArg1
)) {
7922 if (kIOPMRequestTypeCancelPowerChange
== request
->getType()) {
7923 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7924 // flag is set. Only root domain will set this flag.
7925 // However, there is one exception to this rule. User-space PM
7926 // policy may choose to cancel sleep even after all clients have
7927 // been notified that we will lower power.
7929 if ((fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7930 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7931 || ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0)) {
7932 fDoNotPowerDown
= true;
7934 OSString
* name
= (OSString
*) request
->fArg2
;
7935 getPMRootDomain()->pmStatsRecordApplicationResponse(
7936 gIOPMStatsResponseCancel
,
7937 name
? name
->getCStringNoCopy() : "", 0,
7938 0, (int)(uintptr_t) request
->fArg1
, NULL
);
7942 if (checkForDone()) {
7944 cleanClientResponses(false);
7948 // OSString containing app name in Arg2 must be released.
7949 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
) {
7950 OSObject
* obj
= (OSObject
*) request
->fArg2
;
7957 case kIOPMRequestTypeAckPowerChange
:
7958 more
= handleAcknowledgePowerChange( request
);
7961 case kIOPMRequestTypeAckSetPowerState
:
7962 if (fDriverTimer
== -1) {
7963 // driver acked while setPowerState() call is in-flight.
7964 // take this ack, return value from setPowerState() is irrelevant.
7965 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
7966 (uintptr_t) this, fDriverTimer
);
7968 } else if (fDriverTimer
> 0) {
7969 // expected ack, stop the timer
7972 getPMRootDomain()->reset_watchdog_timer(this, 0);
7974 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
7975 if (nsec
> LOG_SETPOWER_TIMES
) {
7976 getPMRootDomain()->pmStatsRecordApplicationResponse(
7977 gIOPMStatsDriverPSChangeSlow
,
7978 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
7979 NULL
, fHeadNotePowerState
);
7982 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
7987 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
7991 case kIOPMRequestTypeInterestChanged
:
7992 handleInterestChanged( request
);
7996 case kIOPMRequestTypeIdleCancel
:
7997 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
7998 || (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7999 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
8000 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
8001 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
)) {
8002 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
8003 PM_LOG2("%s: cancel from machine state %d\n",
8004 getName(), fMachineState
);
8005 fDoNotPowerDown
= true;
8006 // Stop waiting for app replys.
8007 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
8008 (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
) ||
8009 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
) ||
8010 (fMachineState
== kIOPM_SyncTellClientsPowerDown
)) {
8011 cleanClientResponses(false);
8017 case kIOPMRequestTypeChildNotifyDelayCancel
:
8018 if (fMachineState
== kIOPM_NotifyChildrenDelayed
) {
8019 PM_LOG2("%s: delay notify cancelled\n", getName());
8020 notifyChildrenDelayed();
8025 panic("PMReplyQueue: unknown reply type %x", request
->getType());
8028 more
|= gIOPMCompletionQueue
->queuePMRequest(request
);
8030 gIOPMWorkQueue
->incrementProducerCount();
8036 //*********************************************************************************
8037 // [private] assertPMDriverCall / deassertPMDriverCall
8038 //*********************************************************************************
8041 IOService::assertPMDriverCall(
8042 IOPMDriverCallEntry
* entry
,
8043 IOOptionBits method
,
8044 const IOPMinformee
* inform
,
8045 IOOptionBits options
)
8047 IOService
* target
= NULL
;
8056 if (fLockedFlags
.PMStop
) {
8060 if (((options
& kIOPMDriverCallNoInactiveCheck
) == 0) && isInactive()) {
8065 if (!inform
->active
) {
8068 target
= inform
->whatObject
;
8069 if (target
->isInactive()) {
8074 // Record calling address for sleep failure diagnostics
8076 case kIOPMDriverCallMethodSetPowerState
:
8077 entry
->callMethod
= OSMemberFunctionCast(const void *, fControllingDriver
, &IOService::setPowerState
);
8079 case kIOPMDriverCallMethodWillChange
:
8080 entry
->callMethod
= OSMemberFunctionCast(const void *, target
, &IOService::powerStateWillChangeTo
);
8082 case kIOPMDriverCallMethodDidChange
:
8083 entry
->callMethod
= OSMemberFunctionCast(const void *, target
, &IOService::powerStateDidChangeTo
);
8085 case kIOPMDriverCallMethodUnknown
:
8086 case kIOPMDriverCallMethodSetAggressive
:
8088 entry
->callMethod
= NULL
;
8092 entry
->thread
= current_thread();
8093 entry
->target
= target
;
8094 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8104 IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
8106 bool wakeup
= false;
8110 assert( !queue_empty(&fPMDriverCallQueue
));
8111 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8112 if (fLockedFlags
.PMDriverCallWait
) {
8119 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
8124 IOService::getBlockingDriverCall(thread_t
*thread
, const void **callMethod
)
8126 const IOPMDriverCallEntry
* entry
= NULL
;
8127 bool blocked
= false;
8133 if (current_thread() != gIOPMWatchDogThread
) {
8134 // Meant to be accessed only from watchdog thread
8139 entry
= qe_queue_first(&fPMDriverCallQueue
, IOPMDriverCallEntry
, link
);
8141 *thread
= entry
->thread
;
8142 *callMethod
= entry
->callMethod
;
8152 IOService::waitForPMDriverCall( IOService
* target
)
8154 const IOPMDriverCallEntry
* entry
;
8155 thread_t thread
= current_thread();
8156 AbsoluteTime deadline
;
8163 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
8165 // Target of interested driver call
8166 if (target
&& (target
!= entry
->target
)) {
8170 if (entry
->thread
== thread
) {
8172 PM_LOG("%s: %s(%s) on PM thread\n",
8173 fName
, __FUNCTION__
, target
? target
->getName() : "");
8174 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
8175 fName
, __FUNCTION__
, target
? target
->getName() : "");
8186 fLockedFlags
.PMDriverCallWait
= true;
8187 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
8188 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
8189 fLockedFlags
.PMDriverCallWait
= false;
8190 if (THREAD_TIMED_OUT
== waitResult
) {
8191 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
8198 //*********************************************************************************
8199 // [private] Debug helpers
8200 //*********************************************************************************
8203 IOService::getIOMessageString( uint32_t msg
)
8205 #define MSG_ENTRY(x) {(int) x, #x}
8207 static const IONamedValue msgNames
[] = {
8208 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
8209 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
8210 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
8211 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
8212 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
8213 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
8214 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
8215 MSG_ENTRY( kIOMessageCanSystemSleep
),
8216 MSG_ENTRY( kIOMessageSystemWillSleep
),
8217 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
8218 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
8219 MSG_ENTRY( kIOMessageSystemWillRestart
),
8220 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
8221 MSG_ENTRY( kIOMessageSystemCapabilityChange
),
8222 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep
),
8223 MSG_ENTRY( kIOMessageSystemPagingOff
),
8227 return IOFindNameForValue(msg
, msgNames
);
8232 // MARK: IOPMRequest
8234 //*********************************************************************************
8235 // IOPMRequest Class
8237 // Requests from PM clients, and also used for inter-object messaging within PM.
8238 //*********************************************************************************
8240 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
8243 IOPMRequest::create( void )
8245 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
8246 if (me
&& !me
->init(NULL
, kIOPMRequestTypeInvalid
)) {
8254 IOPMRequest::init( IOService
* target
, IOOptionBits type
)
8256 if (!IOCommand::init()) {
8260 fRequestType
= type
;
8267 // Root node and root domain requests does not prevent the power tree from
8268 // becoming quiescent.
8270 fIsQuiesceBlocker
= ((fTarget
!= gIOPMRootNode
) &&
8271 (fTarget
!= IOService::getPMRootDomain()));
8277 IOPMRequest::reset( void )
8279 assert( fWorkWaitCount
== 0 );
8280 assert( fFreeWaitCount
== 0 );
8282 detachNextRequest();
8283 detachRootRequest();
8285 if (fCompletionAction
&& (fRequestType
== kIOPMRequestTypeQuiescePowerTree
)) {
8286 // Call the completion on PM work loop context
8287 fCompletionAction(fCompletionTarget
, fCompletionParam
);
8288 fCompletionAction
= NULL
;
8291 fRequestType
= kIOPMRequestTypeInvalid
;
8300 IOPMRequest::attachNextRequest( IOPMRequest
* next
)
8304 if (!fRequestNext
) {
8305 // Postpone the execution of the next request after
8307 fRequestNext
= next
;
8308 fRequestNext
->fWorkWaitCount
++;
8309 #if LOG_REQUEST_ATTACH
8310 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8311 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8312 fRequestNext
->fRequestType
,
8313 (uint32_t) fRequestNext
->fWorkWaitCount
,
8314 fTarget
->getName());
8322 IOPMRequest::detachNextRequest( void )
8327 assert(fRequestNext
->fWorkWaitCount
);
8328 if (fRequestNext
->fWorkWaitCount
) {
8329 fRequestNext
->fWorkWaitCount
--;
8331 #if LOG_REQUEST_ATTACH
8332 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8333 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8334 fRequestNext
->fRequestType
,
8335 (uint32_t) fRequestNext
->fWorkWaitCount
,
8336 fTarget
->getName());
8338 fRequestNext
= NULL
;
8345 IOPMRequest::attachRootRequest( IOPMRequest
* root
)
8349 if (!fRequestRoot
) {
8350 // Delay the completion of the root request after
8352 fRequestRoot
= root
;
8353 fRequestRoot
->fFreeWaitCount
++;
8354 #if LOG_REQUEST_ATTACH
8355 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8356 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8357 (uint32_t) fRequestRoot
->fType
,
8358 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8359 fTarget
->getName());
8367 IOPMRequest::detachRootRequest( void )
8372 assert(fRequestRoot
->fFreeWaitCount
);
8373 if (fRequestRoot
->fFreeWaitCount
) {
8374 fRequestRoot
->fFreeWaitCount
--;
8376 #if LOG_REQUEST_ATTACH
8377 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8378 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8379 (uint32_t) fRequestRoot
->fType
,
8380 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8381 fTarget
->getName());
8383 fRequestRoot
= NULL
;
8390 // MARK: IOPMRequestQueue
8392 //*********************************************************************************
8393 // IOPMRequestQueue Class
8395 // Global queues. Queues are created once and never released.
8396 //*********************************************************************************
8398 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
8401 IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
8403 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
8404 if (me
&& !me
->init(inOwner
, inAction
)) {
8412 IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
8414 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
)) {
8418 queue_init(&fQueue
);
8419 fLock
= IOLockAlloc();
8420 return fLock
!= NULL
;
8424 IOPMRequestQueue::free( void )
8430 return IOEventSource::free();
8434 IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
8438 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8439 IOLockUnlock(fLock
);
8441 signalWorkAvailable();
8446 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
8450 assert(requests
&& count
);
8455 queue_enter(&fQueue
, next
, typeof(next
), fCommandChain
);
8457 IOLockUnlock(fLock
);
8459 signalWorkAvailable();
8464 IOPMRequestQueue::checkForWork( void )
8466 Action dqAction
= (Action
) action
;
8467 IOPMRequest
* request
;
8469 int dequeueCount
= 0;
8472 IOLockLock( fLock
);
8474 while (!queue_empty(&fQueue
)) {
8475 if (dequeueCount
++ >= kMaxDequeueCount
) {
8476 // Allow other queues a chance to work
8481 queue_remove_first(&fQueue
, request
, typeof(request
), fCommandChain
);
8482 IOLockUnlock(fLock
);
8483 target
= request
->getTarget();
8485 more
|= (*dqAction
)( target
, request
, this );
8486 IOLockLock( fLock
);
8489 IOLockUnlock( fLock
);
8494 // MARK: IOPMWorkQueue
8496 //*********************************************************************************
8497 // IOPMWorkQueue Class
8499 // Queue of IOServicePM objects, each with a queue of IOPMRequest sharing the
8501 //*********************************************************************************
8503 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
8506 IOPMWorkQueue::create( IOService
* inOwner
, Action invoke
, Action retire
)
8508 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
8509 if (me
&& !me
->init(inOwner
, invoke
, retire
)) {
8517 IOPMWorkQueue::init( IOService
* inOwner
, Action invoke
, Action retire
)
8519 if (!invoke
|| !retire
||
8520 !IOEventSource::init(inOwner
, (IOEventSourceAction
)NULL
)) {
8524 queue_init(&fWorkQueue
);
8526 fInvokeAction
= invoke
;
8527 fRetireAction
= retire
;
8528 fConsumerCount
= fProducerCount
= 0;
8534 IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
8536 queue_head_t
* requestQueue
;
8542 assert( onThread());
8543 assert( queue_next(&request
->fCommandChain
) ==
8544 queue_prev(&request
->fCommandChain
));
8546 gIOPMBusyRequestCount
++;
8548 if (request
->isQuiesceType()) {
8549 if ((request
->getTarget() == gIOPMRootNode
) && !fQuiesceStartTime
) {
8550 // Attach new quiesce request to all quiesce blockers in the queue
8551 fQuiesceStartTime
= mach_absolute_time();
8552 attachQuiesceRequest(request
);
8553 fQuiesceRequest
= request
;
8555 } else if (fQuiesceRequest
&& request
->isQuiesceBlocker()) {
8556 // Attach the new quiesce blocker to the blocked quiesce request
8557 request
->attachNextRequest(fQuiesceRequest
);
8560 // Add new request to the tail of the per-service request queue.
8561 // Then immediately check the request queue to minimize latency
8562 // if the queue was empty.
8564 requestQueue
= &pwrMgt
->RequestHead
;
8565 empty
= queue_empty(requestQueue
);
8566 queue_enter(requestQueue
, request
, typeof(request
), fCommandChain
);
8568 more
= checkRequestQueue(requestQueue
, &empty
);
8570 // Request just added is blocked, add its target IOServicePM
8571 // to the work queue.
8572 assert( queue_next(&pwrMgt
->WorkChain
) ==
8573 queue_prev(&pwrMgt
->WorkChain
));
8575 queue_enter(&fWorkQueue
, pwrMgt
, typeof(pwrMgt
), WorkChain
);
8577 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8578 fQueueLength
, pwrMgt
->Name
, OBFUSCATE(pwrMgt
));
8586 IOPMWorkQueue::checkRequestQueue( queue_head_t
* requestQueue
, bool * empty
)
8588 IOPMRequest
* request
;
8593 assert(!queue_empty(requestQueue
));
8595 request
= (typeof(request
))queue_first(requestQueue
);
8596 if (request
->isWorkBlocked()) {
8597 break; // request dispatch blocked on attached request
8599 target
= request
->getTarget();
8600 if (fInvokeAction
) {
8601 done
= (*fInvokeAction
)( target
, request
, this );
8603 PM_LOG("PM request 0x%x dropped\n", request
->getType());
8607 break; // PM state machine blocked
8609 assert(gIOPMBusyRequestCount
> 0);
8610 if (gIOPMBusyRequestCount
) {
8611 gIOPMBusyRequestCount
--;
8614 if (request
== fQuiesceRequest
) {
8615 fQuiesceRequest
= NULL
;
8618 queue_remove_first(requestQueue
, request
, typeof(request
), fCommandChain
);
8619 more
|= (*fRetireAction
)( target
, request
, this );
8620 done
= queue_empty(requestQueue
);
8626 // Retired a request that may unblock a previously visited request
8627 // that is still waiting on the work queue. Must trigger another
8636 IOPMWorkQueue::checkForWork( void )
8638 IOServicePM
* entry
;
8643 #if WORK_QUEUE_STATS
8644 fStatCheckForWork
++;
8647 // Iterate over all IOServicePM entries in the work queue,
8648 // and check each entry's request queue.
8650 while (fConsumerCount
!= fProducerCount
) {
8651 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8652 fProducerCount
, fConsumerCount
);
8654 fConsumerCount
= fProducerCount
;
8656 #if WORK_QUEUE_STATS
8657 if (queue_empty(&fWorkQueue
)) {
8662 uint32_t cachedWorkCount
= gIOPMWorkInvokeCount
;
8665 __IGNORE_WCASTALIGN(entry
= (typeof(entry
))queue_first(&fWorkQueue
));
8666 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
)) {
8667 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
8669 // Get next entry, points to head if current entry is last.
8670 __IGNORE_WCASTALIGN(next
= (typeof(next
))queue_next(&entry
->WorkChain
));
8672 // if request queue is empty, remove IOServicePM from work queue.
8674 assert(fQueueLength
);
8678 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8679 fQueueLength
, entry
->Name
, OBFUSCATE(entry
));
8680 queue_remove(&fWorkQueue
, entry
, typeof(entry
), WorkChain
);
8685 #if WORK_QUEUE_STATS
8686 if (cachedWorkCount
== gIOPMWorkInvokeCount
) {
8696 IOPMWorkQueue::signalWorkAvailable( void )
8699 IOEventSource::signalWorkAvailable();
8703 IOPMWorkQueue::incrementProducerCount( void )
8709 IOPMWorkQueue::attachQuiesceRequest( IOPMRequest
* quiesceRequest
)
8711 IOServicePM
* entry
;
8712 IOPMRequest
* request
;
8714 if (queue_empty(&fWorkQueue
)) {
8718 queue_iterate(&fWorkQueue
, entry
, typeof(entry
), WorkChain
)
8720 queue_iterate(&entry
->RequestHead
, request
, typeof(request
), fCommandChain
)
8722 // Attach the quiesce request to any request in the queue that
8723 // is not linked to a next request. These requests will block
8724 // the quiesce request.
8726 if (request
->isQuiesceBlocker()) {
8727 request
->attachNextRequest(quiesceRequest
);
8734 IOPMWorkQueue::finishQuiesceRequest( IOPMRequest
* quiesceRequest
)
8736 if (fQuiesceRequest
&& (quiesceRequest
== fQuiesceRequest
) &&
8737 (fQuiesceStartTime
!= 0)) {
8738 fInvokeAction
= NULL
;
8739 fQuiesceFinishTime
= mach_absolute_time();
8744 // MARK: IOPMCompletionQueue
8746 //*********************************************************************************
8747 // IOPMCompletionQueue Class
8748 //*********************************************************************************
8750 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
8752 IOPMCompletionQueue
*
8753 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
8755 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
8756 if (me
&& !me
->init(inOwner
, inAction
)) {
8764 IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
8766 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
)) {
8770 queue_init(&fQueue
);
8775 IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
8780 // unblock dependent request
8781 more
= request
->detachNextRequest();
8782 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8787 IOPMCompletionQueue::checkForWork( void )
8789 Action dqAction
= (Action
) action
;
8790 IOPMRequest
* request
;
8795 request
= (typeof(request
))queue_first(&fQueue
);
8796 while (!queue_end(&fQueue
, (queue_entry_t
) request
)) {
8797 next
= (typeof(next
))queue_next(&request
->fCommandChain
);
8798 if (!request
->isFreeBlocked()) {
8799 queue_remove(&fQueue
, request
, typeof(request
), fCommandChain
);
8800 target
= request
->getTarget();
8802 more
|= (*dqAction
)( target
, request
, this );
8811 // MARK: IOServicePM
8813 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8815 //*********************************************************************************
8818 // Serialize IOServicePM for debugging.
8819 //*********************************************************************************
8822 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8824 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8826 dict
->setObject(key
, num
);
8832 IOServicePM::gatedSerialize( OSSerialize
* s
) const
8834 OSDictionary
* dict
;
8836 int powerClamp
= -1;
8839 if (IdleTimerPeriod
) {
8843 if (PMActions
.parameter
& kPMActionsFlagLimitPower
) {
8846 if (PMActions
.parameter
&
8847 (kPMActionsFlagIsDisplayWrangler
| kPMActionsFlagIsGraphicsDevice
)) {
8852 #if WORK_QUEUE_STATS
8853 if (gIOPMRootNode
== ControllingDriver
) {
8859 dict
= OSDictionary::withDictionary(
8860 PowerClients
, PowerClients
->getCount() + dictSize
);
8862 dict
= OSDictionary::withCapacity(dictSize
);
8866 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8867 setPMProperty(dict
, "CapabilityFlags", CurrentCapabilityFlags
);
8868 if (NumberOfPowerStates
) {
8869 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
- 1);
8871 if (DesiredPowerState
!= CurrentPowerState
) {
8872 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8874 if (kIOPM_Finished
!= MachineState
) {
8875 setPMProperty(dict
, "MachineState", MachineState
);
8877 if (DeviceOverrideEnabled
) {
8878 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8880 if (powerClamp
>= 0) {
8881 setPMProperty(dict
, "PowerClamp", powerClamp
);
8884 if (IdleTimerPeriod
) {
8889 clock_get_uptime(&now
);
8891 // The idle timer period in milliseconds
8892 setPMProperty(dict
, "IdleTimerPeriod", NextIdleTimerPeriod
* 1000ULL);
8894 // Number of tickles since the last idle timer expiration
8895 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8897 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
)) {
8898 // Milliseconds since the last activity tickle
8900 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8901 absolutetime_to_nanoseconds(delta
, &nsecs
);
8902 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
8905 if (!IdleTimerStopped
&& AbsoluteTime_to_scalar(&IdleTimerStartTime
)) {
8906 // Idle timer elapsed time in milliseconds
8908 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
8909 absolutetime_to_nanoseconds(delta
, &nsecs
);
8910 setPMProperty(dict
, "IdleTimerElapsedTime", NS_TO_MS(nsecs
));
8914 #if WORK_QUEUE_STATS
8915 if (gIOPMRootNode
== Owner
) {
8916 setPMProperty(dict
, "WQ-CheckForWork",
8917 gIOPMWorkQueue
->fStatCheckForWork
);
8918 setPMProperty(dict
, "WQ-ScanEntries",
8919 gIOPMWorkQueue
->fStatScanEntries
);
8920 setPMProperty(dict
, "WQ-QueueEmpty",
8921 gIOPMWorkQueue
->fStatQueueEmpty
);
8922 setPMProperty(dict
, "WQ-NoWorkDone",
8923 gIOPMWorkQueue
->fStatNoWorkDone
);
8927 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
) {
8928 // Don't report advisory tickle when it has no influence
8929 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
8932 ok
= dict
->serialize(s
);
8936 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;
8940 IOServicePM::serialize( OSSerialize
* s
) const
8942 IOReturn ret
= kIOReturnNotReady
;
8944 if (gIOPMWatchDogThread
== current_thread()) {
8945 // Calling without lock as this data is collected for debug purpose, before reboot.
8946 // The workloop is probably already hung in state machine.
8947 ret
= gatedSerialize(s
);
8948 } else if (gIOPMWorkLoop
) {
8949 ret
= gIOPMWorkLoop
->runAction(
8950 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
8951 (OSObject
*) this, (void *) s
);
8954 return kIOReturnSuccess
== ret
;
8958 IOServicePM::pmPrint(
8961 uintptr_t param2
) const
8963 gPlatform
->PMLog(Name
, event
, param1
, param2
);
8967 IOServicePM::pmTrace(
8971 uintptr_t param2
) const
8973 uintptr_t nameAsArg
= 0;
8975 assert(event
< KDBG_CODE_MAX
);
8976 assert((eventFunc
& ~KDBG_FUNC_MASK
) == 0);
8978 // Copy the first characters of the name into an uintptr_t.
8979 // NULL termination is not required.
8980 strncpy((char*)&nameAsArg
, Name
, sizeof(nameAsArg
));
8982 IOTimeStampConstant(IODBG_POWER(event
) | eventFunc
, nameAsArg
, (uintptr_t)Owner
->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1
)), (uintptr_t)(OBFUSCATE(param2
)));