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>
41 #include <IOKit/pwr_mgt/IOPMlog.h>
42 #include <IOKit/pwr_mgt/IOPMinformee.h>
43 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
44 #include <IOKit/pwr_mgt/IOPowerConnection.h>
45 #include <IOKit/pwr_mgt/RootDomain.h>
46 #include <IOKit/pwr_mgt/IOPMPrivate.h>
49 #include <sys/proc_internal.h>
50 #include <sys/sysctl.h>
51 #include <libkern/OSDebug.h>
52 #include <kern/thread.h>
54 // Required for notification instrumentation
55 #include "IOServicePrivate.h"
56 #include "IOServicePMPrivate.h"
57 #include "IOKitKernelInternal.h"
60 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
61 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
62 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
63 static void tellAppClientApplier(OSObject
* object
, void * arg
);
65 static uint64_t computeTimeDeltaNS( const AbsoluteTime
* start
)
70 clock_get_uptime(&now
);
71 SUB_ABSOLUTETIME(&now
, start
);
72 absolutetime_to_nanoseconds(now
, &nsec
);
77 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
80 //******************************************************************************
82 //******************************************************************************
84 static bool gIOPMInitialized
= false;
85 static uint32_t gIOPMBusyRequestCount
= 0;
86 static uint32_t gIOPMWorkInvokeCount
= 0;
87 static uint32_t gIOPMTickleGeneration
= 0;
88 static IOWorkLoop
* gIOPMWorkLoop
= 0;
89 static IOPMRequestQueue
* gIOPMRequestQueue
= 0;
90 static IOPMRequestQueue
* gIOPMReplyQueue
= 0;
91 static IOPMWorkQueue
* gIOPMWorkQueue
= 0;
92 static IOPMCompletionQueue
* gIOPMCompletionQueue
= 0;
93 static IOPMRequest
* gIOPMRequest
= 0;
94 static IOService
* gIOPMRootNode
= 0;
95 static IOPlatformExpert
* gPlatform
= 0;
97 static char gIOSpinDumpKextName
[128];
98 static char gIOSpinDumpDelayType
[16];
99 static uint32_t gIOSpinDumpDelayDuration
= 0;
101 static SYSCTL_STRING(_debug
, OID_AUTO
, swd_kext_name
,
102 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
103 &gIOSpinDumpKextName
, sizeof(gIOSpinDumpKextName
), "");
104 static SYSCTL_STRING(_debug
, OID_AUTO
, swd_delay_type
,
105 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
106 &gIOSpinDumpDelayType
, sizeof(gIOSpinDumpDelayType
), "");
107 static SYSCTL_INT(_debug
, OID_AUTO
, swd_delay_duration
,
108 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
109 &gIOSpinDumpDelayDuration
, 0, "");
111 const OSSymbol
* gIOPMPowerClientDevice
= 0;
112 const OSSymbol
* gIOPMPowerClientDriver
= 0;
113 const OSSymbol
* gIOPMPowerClientChildProxy
= 0;
114 const OSSymbol
* gIOPMPowerClientChildren
= 0;
115 const OSSymbol
* gIOPMPowerClientRootDomain
= 0;
117 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= 0;
118 static bool gIOPMAdvisoryTickleEnabled
= true;
119 static thread_t gIOPMWatchDogThread
= NULL
;
120 uint32_t gCanSleepTimeout
= 0;
122 static uint32_t getPMRequestType( void )
124 uint32_t type
= kIOPMRequestTypeInvalid
;
126 type
= gIOPMRequest
->getType();
130 static IOPMRequestTag
getPMRequestTag( void )
132 IOPMRequestTag tag
= 0;
134 (gIOPMRequest
->getType() == kIOPMRequestTypeRequestPowerStateOverride
))
136 tag
= gIOPMRequest
->fRequestTag
;
141 SYSCTL_UINT(_kern
, OID_AUTO
, pmtimeout
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &gCanSleepTimeout
, 0, "Power Management Timeout");
143 //******************************************************************************
145 //******************************************************************************
147 #define PM_ERROR(x...) do { kprintf(x);IOLog(x); \
149 #define PM_LOG(x...) do { kprintf(x); } while (false)
151 #define PM_LOG1(x...) do { \
152 if (kIOLogDebugPower & gIOKitDebug) \
153 kprintf(x); } while (false)
155 #define PM_LOG2(x...) do { \
156 if (kIOLogDebugPower & gIOKitDebug) \
157 kprintf(x); } while (false)
160 #define PM_LOG3(x...) do { kprintf(x); } while (false)
162 #define PM_LOG3(x...)
165 #define RD_LOG(x...) do { \
166 if ((kIOLogPMRootDomain & gIOKitDebug) && \
167 (getPMRootDomain() == this)) { \
168 kprintf("PMRD: " x); \
170 #define PM_ASSERT_IN_GATE(x) \
172 assert(gIOPMWorkLoop->inGate()); \
175 #define PM_LOCK() IOLockLock(fPMLock)
176 #define PM_UNLOCK() IOLockUnlock(fPMLock)
177 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
178 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
180 #define us_per_s 1000000
181 #define ns_per_us 1000
182 #define k30Seconds (30*us_per_s)
183 #define k5Seconds ( 5*us_per_s)
184 #define kCanSleepMaxTimeReq k30Seconds
185 #define kMaxTimeRequested k30Seconds
186 #define kMinAckTimeoutTicks (10*1000000)
187 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
188 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
189 #define kPwrMgtKey "IOPowerManagement"
191 #define OUR_PMLog(t, a, b) do { \
192 if (gIOKitDebug & kIOLogPower) \
193 pwrMgt->pmPrint(t, a, b); \
194 if (gIOKitTrace & kIOTracePowerMgmt) \
195 pwrMgt->pmTrace(t, a, b); \
198 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
199 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
201 #define SUPPORT_IDLE_CANCEL 1
203 #define kIOPMPowerStateMax 0xFFFFFFFF
204 #define kInvalidTicklePowerState kIOPMPowerStateMax
206 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
208 #define IS_PM_ROOT (this == gIOPMRootNode)
209 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
210 #define IS_POWER_DROP (StateOrder(fHeadNotePowerState) < StateOrder(fCurrentPowerState))
211 #define IS_POWER_RISE (StateOrder(fHeadNotePowerState) > StateOrder(fCurrentPowerState))
213 // log setPowerStates longer than (ns):
214 #if defined(__i386__) || defined(__x86_64__)
215 #define LOG_SETPOWER_TIMES (300ULL * 1000ULL * 1000ULL)
217 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
219 // log app responses longer than (ns):
220 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
221 // use message tracer to log messages longer than (ns):
222 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
225 kReserveDomainPower
= 1
229 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
230 assert(kIOPM_BadMachineState != n); \
231 fSavedMachineState = n; } while (false)
234 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
235 fMachineState = fSavedMachineState; \
236 fSavedMachineState = kIOPM_BadMachineState; } while (false)
238 #define PM_ACTION_0(a) \
239 do { if (fPMActions.a) { \
240 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
243 #define PM_ACTION_2(a, x, y) \
244 do { if (fPMActions.a) { \
245 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, \
246 getPMRequestTag()); } \
249 #define PM_ACTION_3(a, x, y, z) \
250 do { if (fPMActions.a) { \
251 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, z); } \
254 static OSNumber
* copyClientIDForNotification(
256 IOPMInterestContext
*context
);
258 static void logClientIDForNotification(
260 IOPMInterestContext
*context
,
261 const char *logString
);
263 //*********************************************************************************
266 // Check kgmacros after modifying machine states.
267 //*********************************************************************************
272 kIOPM_OurChangeTellClientsPowerDown
= 1,
273 kIOPM_OurChangeTellUserPMPolicyPowerDown
= 2,
274 kIOPM_OurChangeTellPriorityClientsPowerDown
= 3,
275 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 4,
276 kIOPM_OurChangeSetPowerState
= 5,
277 kIOPM_OurChangeWaitForPowerSettle
= 6,
278 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 7,
279 kIOPM_OurChangeTellCapabilityDidChange
= 8,
280 kIOPM_OurChangeFinish
= 9,
282 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
283 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
284 kIOPM_ParentChangeSetPowerState
= 12,
285 kIOPM_ParentChangeWaitForPowerSettle
= 13,
286 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
287 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
288 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
290 kIOPM_NotifyChildrenStart
= 17,
291 kIOPM_NotifyChildrenOrdered
= 18,
292 kIOPM_NotifyChildrenDelayed
= 19,
293 kIOPM_SyncTellClientsPowerDown
= 20,
294 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
295 kIOPM_SyncNotifyWillChange
= 22,
296 kIOPM_SyncNotifyDidChange
= 23,
297 kIOPM_SyncTellCapabilityDidChange
= 24,
298 kIOPM_SyncFinish
= 25,
299 kIOPM_TellCapabilityChangeDone
= 26,
300 kIOPM_DriverThreadCallDone
= 27,
302 kIOPM_BadMachineState
= 0xFFFFFFFF
305 //*********************************************************************************
308 // Initialize power management.
309 //*********************************************************************************
311 void IOService::PMinit( void )
315 if ( !gIOPMInitialized
)
317 gPlatform
= getPlatform();
318 gIOPMWorkLoop
= IOWorkLoop::workLoop();
321 gIOPMRequestQueue
= IOPMRequestQueue::create(
322 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
323 this, &IOService::actionPMRequestQueue
));
325 gIOPMReplyQueue
= IOPMRequestQueue::create(
326 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
327 this, &IOService::actionPMReplyQueue
));
329 gIOPMWorkQueue
= IOPMWorkQueue::create(this,
330 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
331 &IOService::actionPMWorkQueueInvoke
),
332 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
333 &IOService::actionPMWorkQueueRetire
));
335 gIOPMCompletionQueue
= IOPMCompletionQueue::create(
336 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
337 this, &IOService::actionPMCompletionQueue
));
339 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
342 gIOPMRequestQueue
->release();
343 gIOPMRequestQueue
= 0;
346 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
349 gIOPMReplyQueue
->release();
353 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
356 gIOPMWorkQueue
->release();
360 // Must be added after the work queue, which pushes request
361 // to the completion queue without signaling the work loop.
362 if (gIOPMWorkLoop
->addEventSource(gIOPMCompletionQueue
) !=
365 gIOPMCompletionQueue
->release();
366 gIOPMCompletionQueue
= 0;
369 gIOPMPowerClientDevice
=
370 OSSymbol::withCStringNoCopy( "DevicePowerState" );
372 gIOPMPowerClientDriver
=
373 OSSymbol::withCStringNoCopy( "DriverPowerState" );
375 gIOPMPowerClientChildProxy
=
376 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
378 gIOPMPowerClientChildren
=
379 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
381 gIOPMPowerClientAdvisoryTickle
=
382 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
384 gIOPMPowerClientRootDomain
=
385 OSSymbol::withCStringNoCopy( "RootDomainPower" );
387 gIOSpinDumpKextName
[0] = '\0';
388 gIOSpinDumpDelayType
[0] = '\0';
391 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMCompletionQueue
)
392 gIOPMInitialized
= true;
394 if (!gIOPMInitialized
)
397 pwrMgt
= new IOServicePM
;
399 setProperty(kPwrMgtKey
, pwrMgt
);
401 queue_init(&pwrMgt
->WorkChain
);
402 queue_init(&pwrMgt
->RequestHead
);
403 queue_init(&pwrMgt
->PMDriverCallQueue
);
406 fPMLock
= IOLockAlloc();
407 fInterestedDrivers
= new IOPMinformeeList
;
408 fInterestedDrivers
->initialize();
409 fDesiredPowerState
= kPowerStateZero
;
410 fDeviceDesire
= kPowerStateZero
;
411 fInitialPowerChange
= true;
412 fInitialSetPowerState
= true;
413 fPreviousRequestPowerFlags
= 0;
414 fDeviceOverrideEnabled
= false;
415 fMachineState
= kIOPM_Finished
;
416 fSavedMachineState
= kIOPM_BadMachineState
;
417 fIdleTimerMinPowerState
= kPowerStateZero
;
418 fActivityLock
= IOLockAlloc();
419 fStrictTreeOrder
= false;
420 fActivityTicklePowerState
= kInvalidTicklePowerState
;
421 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
422 fControllingDriver
= NULL
;
424 fNumberOfPowerStates
= 0;
425 fCurrentPowerState
= kPowerStateZero
;
426 fParentsCurrentPowerFlags
= 0;
427 fMaxPowerState
= kPowerStateZero
;
429 fParentsKnowState
= false;
431 fResponseArray
= NULL
;
432 fNotifyClientArray
= NULL
;
433 fCurrentPowerConsumption
= kIOPMUnknown
;
434 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
436 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot()))
438 gIOPMRootNode
= this;
439 fParentsKnowState
= true;
441 else if (getProperty(kIOPMResetPowerStateOnWakeKey
) == kOSBooleanTrue
)
443 fResetPowerStateOnWake
= true;
448 fWatchdogTimer
= thread_call_allocate(
449 &IOService::watchdog_timer_expired
, (thread_call_param_t
)this);
452 fAckTimer
= thread_call_allocate(
453 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
454 fSettleTimer
= thread_call_allocate(
455 &settle_timer_expired
, (thread_call_param_t
)this);
456 fIdleTimer
= thread_call_allocate(
457 &idle_timer_expired
, (thread_call_param_t
)this);
458 fDriverCallEntry
= thread_call_allocate(
459 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
460 assert(fDriverCallEntry
);
461 if (kIOKextSpinDump
& gIOKitDebug
)
463 fSpinDumpTimer
= thread_call_allocate(
464 &IOService::spindump_timer_expired
, (thread_call_param_t
)this);
467 // Check for powerChangeDone override.
468 if (OSMemberFunctionCast(void (*)(void),
469 getResourceService(), &IOService::powerChangeDone
) !=
470 OSMemberFunctionCast(void (*)(void),
471 this, &IOService::powerChangeDone
))
473 fPCDFunctionOverride
= true;
477 IOPMprot
* prot
= new IOPMprot
;
481 prot
->ourName
= fName
;
482 prot
->thePlatform
= gPlatform
;
487 pm_vars
= (void *) (uintptr_t) true;
494 //*********************************************************************************
497 // Free the data created by PMinit. Only called from IOService::free().
498 //*********************************************************************************
500 void IOService::PMfree( void )
507 assert(fMachineState
== kIOPM_Finished
);
508 assert(fInsertInterestSet
== NULL
);
509 assert(fRemoveInterestSet
== NULL
);
510 assert(fNotifyChildArray
== NULL
);
511 assert(queue_empty(&pwrMgt
->RequestHead
));
512 assert(queue_empty(&fPMDriverCallQueue
));
514 if (fWatchdogTimer
) {
515 thread_call_cancel(fWatchdogTimer
);
516 thread_call_free(fWatchdogTimer
);
517 fWatchdogTimer
= NULL
;
520 if ( fSettleTimer
) {
521 thread_call_cancel(fSettleTimer
);
522 thread_call_free(fSettleTimer
);
526 thread_call_cancel(fAckTimer
);
527 thread_call_free(fAckTimer
);
531 thread_call_cancel(fIdleTimer
);
532 thread_call_free(fIdleTimer
);
535 if ( fDriverCallEntry
) {
536 thread_call_free(fDriverCallEntry
);
537 fDriverCallEntry
= NULL
;
539 if ( fSpinDumpTimer
) {
540 thread_call_cancel(fSpinDumpTimer
);
541 thread_call_free(fSpinDumpTimer
);
542 fSpinDumpTimer
= NULL
;
548 if ( fActivityLock
) {
549 IOLockFree(fActivityLock
);
550 fActivityLock
= NULL
;
552 if ( fInterestedDrivers
) {
553 fInterestedDrivers
->release();
554 fInterestedDrivers
= NULL
;
556 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
557 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
558 fDriverCallParamPtr
= 0;
559 fDriverCallParamSlots
= 0;
561 if ( fResponseArray
) {
562 fResponseArray
->release();
563 fResponseArray
= NULL
;
565 if ( fNotifyClientArray
) {
566 fNotifyClientArray
->release();
567 fNotifyClientArray
= NULL
;
569 if (fPowerStates
&& fNumberOfPowerStates
) {
570 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
571 fNumberOfPowerStates
= 0;
575 fPowerClients
->release();
592 void IOService::PMDebug( uint32_t event
, uintptr_t param1
, uintptr_t param2
)
594 OUR_PMLog(event
, param1
, param2
);
597 //*********************************************************************************
598 // [public] joinPMtree
600 // A policy-maker calls its nub here when initializing, to be attached into
601 // the power management hierarchy. The default function is to call the
602 // platform expert, which knows how to do it. This method is overridden
603 // by a nub subclass which may either know how to do it, or may need to
604 // take other action.
606 // This may be the only "power management" method used in a nub,
607 // meaning it may not be initialized for power management.
608 //*********************************************************************************
610 void IOService::joinPMtree( IOService
* driver
)
612 IOPlatformExpert
* platform
;
614 platform
= getPlatform();
615 assert(platform
!= 0);
616 platform
->PMRegisterDevice(this, driver
);
620 //*********************************************************************************
621 // [deprecated] youAreRoot
623 // Power Managment is informing us that we are the root power domain.
624 //*********************************************************************************
626 IOReturn
IOService::youAreRoot( void )
630 #endif /* !__LP64__ */
632 //*********************************************************************************
635 // Immediately stop driver callouts. Schedule an async stop request to detach
637 //*********************************************************************************
639 void IOService::PMstop( void )
641 IOPMRequest
* request
;
648 if (fLockedFlags
.PMStop
)
650 PM_LOG2("%s: PMstop() already stopped\n", fName
);
655 // Inhibit future driver calls.
656 fLockedFlags
.PMStop
= true;
658 // Wait for all prior driver calls to finish.
659 waitForPMDriverCall();
663 // The rest of the work is performed async.
664 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
667 PM_LOG2("%s: %p PMstop\n", getName(), OBFUSCATE(this));
668 submitPMRequest( request
);
672 //*********************************************************************************
673 // [private] handlePMstop
675 // Disconnect the node from all parents and children in the power plane.
676 //*********************************************************************************
678 void IOService::handlePMstop( IOPMRequest
* request
)
682 IOPowerConnection
* connection
;
683 IOService
* theChild
;
684 IOService
* theParent
;
687 PM_LOG2("%s: %p %s start\n", getName(), OBFUSCATE(this), __FUNCTION__
);
689 // remove driver from prevent system sleep lists
690 getPMRootDomain()->updatePreventIdleSleepList(this, false);
691 getPMRootDomain()->updatePreventSystemSleepList(this, false);
693 // remove the property
694 removeProperty(kPwrMgtKey
);
697 iter
= getParentIterator(gIOPowerPlane
);
700 while ( (next
= iter
->getNextObject()) )
702 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
704 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
707 theParent
->removePowerChild(connection
);
708 theParent
->release();
715 // detach IOConnections
716 detachAbove( gIOPowerPlane
);
718 // no more power state changes
719 fParentsKnowState
= false;
722 iter
= getChildIterator(gIOPowerPlane
);
725 while ( (next
= iter
->getNextObject()) )
727 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
729 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
732 // detach nub from child
733 connection
->detachFromChild(theChild
, gIOPowerPlane
);
736 // detach us from nub
737 detachFromChild(connection
, gIOPowerPlane
);
743 // Remove all interested drivers from the list, including the power
744 // controlling driver.
746 // Usually, the controlling driver and the policy-maker functionality
747 // are implemented by the same object, and without the deregistration,
748 // the object will be holding an extra retain on itself, and cannot
751 if ( fInterestedDrivers
)
753 IOPMinformeeList
* list
= fInterestedDrivers
;
757 while ((item
= list
->firstInList()))
759 list
->removeFromList(item
->whatObject
);
764 // Clear idle period to prevent idleTimerExpired() from servicing
765 // idle timer expirations.
767 fIdleTimerPeriod
= 0;
768 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
771 PM_LOG2("%s: %p %s done\n", getName(), OBFUSCATE(this), __FUNCTION__
);
774 //*********************************************************************************
775 // [public] addPowerChild
777 // Power Management is informing us who our children are.
778 //*********************************************************************************
780 IOReturn
IOService::addPowerChild( IOService
* child
)
782 IOPowerConnection
* connection
= 0;
783 IOPMRequest
* requests
[3] = {0, 0, 0};
788 return kIOReturnBadArgument
;
790 if (!initialized
|| !child
->initialized
)
791 return IOPMNotYetInitialized
;
793 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
796 // Is this child already one of our children?
798 iter
= child
->getParentIterator( gIOPowerPlane
);
801 IORegistryEntry
* entry
;
804 while ((next
= iter
->getNextObject()))
806 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
807 isChild(entry
, gIOPowerPlane
))
817 PM_LOG("%s: %s (%p) is already a child\n",
818 getName(), child
->getName(), OBFUSCATE(child
));
822 // Add the child to the power plane immediately, but the
823 // joining connection is marked as not ready.
824 // We want the child to appear in the power plane before
825 // returning to the caller, but don't want the caller to
826 // block on the PM work loop.
828 connection
= new IOPowerConnection
;
832 // Create a chain of PM requests to perform the bottom-half
833 // work from the PM work loop.
835 requests
[0] = acquirePMRequest(
837 /* type */ kIOPMRequestTypeAddPowerChild1
);
839 requests
[1] = acquirePMRequest(
841 /* type */ kIOPMRequestTypeAddPowerChild2
);
843 requests
[2] = acquirePMRequest(
845 /* type */ kIOPMRequestTypeAddPowerChild3
);
847 if (!requests
[0] || !requests
[1] || !requests
[2])
850 requests
[0]->attachNextRequest( requests
[1] );
851 requests
[1]->attachNextRequest( requests
[2] );
854 connection
->start(this);
855 connection
->setAwaitingAck(false);
856 connection
->setReadyFlag(false);
858 attachToChild( connection
, gIOPowerPlane
);
859 connection
->attachToChild( child
, gIOPowerPlane
);
861 // connection needs to be released
862 requests
[0]->fArg0
= connection
;
863 requests
[1]->fArg0
= connection
;
864 requests
[2]->fArg0
= connection
;
866 submitPMRequests( requests
, 3 );
867 return kIOReturnSuccess
;
871 if (connection
) connection
->release();
872 if (requests
[0]) releasePMRequest(requests
[0]);
873 if (requests
[1]) releasePMRequest(requests
[1]);
874 if (requests
[2]) releasePMRequest(requests
[2]);
876 // Silent failure, to prevent platform drivers from adding the child
877 // to the root domain.
879 return kIOReturnSuccess
;
882 //*********************************************************************************
883 // [private] addPowerChild1
885 // Step 1/3 of adding a power child. Called on the power parent.
886 //*********************************************************************************
888 void IOService::addPowerChild1( IOPMRequest
* request
)
890 IOPMPowerStateIndex tempDesire
= kPowerStateZero
;
892 // Make us temporary usable before adding the child.
895 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
897 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
899 tempDesire
= fHighestPowerState
;
902 if ((tempDesire
!= kPowerStateZero
) &&
903 (IS_PM_ROOT
|| (StateOrder(fMaxPowerState
) >= StateOrder(tempDesire
))))
905 adjustPowerState(tempDesire
);
909 //*********************************************************************************
910 // [private] addPowerChild2
912 // Step 2/3 of adding a power child. Called on the joining child.
913 // Execution blocked behind addPowerChild1.
914 //*********************************************************************************
916 void IOService::addPowerChild2( IOPMRequest
* request
)
918 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
920 IOPMPowerFlags powerFlags
;
922 unsigned long powerState
;
923 unsigned long tempDesire
;
926 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
928 if (!parent
|| !inPlane(gIOPowerPlane
))
930 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
934 // Parent will be waiting for us to complete this stage.
935 // It is safe to directly access parent's vars.
937 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
938 powerState
= parent
->fCurrentPowerState
;
941 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
945 // Set our power parent.
947 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
949 setParentInfo( powerFlags
, connection
, knowsState
);
951 connection
->setReadyFlag(true);
953 if ( fControllingDriver
&& fParentsKnowState
)
955 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
956 // initially change into the state we are already in
957 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
958 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
959 adjustPowerState(tempDesire
);
962 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
965 //*********************************************************************************
966 // [private] addPowerChild3
968 // Step 3/3 of adding a power child. Called on the parent.
969 // Execution blocked behind addPowerChild2.
970 //*********************************************************************************
972 void IOService::addPowerChild3( IOPMRequest
* request
)
974 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
976 IOPMrootDomain
* rootDomain
= getPMRootDomain();
979 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
981 if (child
&& inPlane(gIOPowerPlane
))
983 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder"))
985 PM_LOG1("%s: strict PM order enforced\n", getName());
986 fStrictTreeOrder
= true;
990 rootDomain
->joinAggressiveness( child
);
994 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
997 connection
->release();
1001 //*********************************************************************************
1002 // [deprecated] setPowerParent
1004 // Power Management is informing us who our parent is.
1005 // If we have a controlling driver, find out, given our newly-informed
1006 // power domain state, what state it would be in, and then tell it
1007 // to assume that state.
1008 //*********************************************************************************
1010 IOReturn
IOService::setPowerParent(
1011 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
1013 return kIOReturnUnsupported
;
1015 #endif /* !__LP64__ */
1017 //*********************************************************************************
1018 // [public] removePowerChild
1020 // Called on a parent whose child is being removed by PMstop().
1021 //*********************************************************************************
1023 IOReturn
IOService::removePowerChild( IOPowerConnection
* theNub
)
1025 IORegistryEntry
* theChild
;
1027 PM_ASSERT_IN_GATE();
1028 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1032 // detach nub from child
1033 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1036 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1037 theChild
->release();
1039 // detach from the nub
1040 detachFromChild(theNub
, gIOPowerPlane
);
1042 // Are we awaiting an ack from this child?
1043 if ( theNub
->getAwaitingAck() )
1045 // yes, pretend we got one
1046 theNub
->setAwaitingAck(false);
1047 if (fHeadNotePendingAcks
!= 0 )
1049 // that's one fewer ack to worry about
1050 fHeadNotePendingAcks
--;
1052 // is that the last?
1053 if ( fHeadNotePendingAcks
== 0 )
1057 // This parent may have a request in the work queue that is
1058 // blocked on fHeadNotePendingAcks=0. And removePowerChild()
1059 // is called while executing the child's PMstop request so they
1060 // can occur simultaneously. IOPMWorkQueue::checkForWork() must
1061 // restart and check all request queues again.
1063 gIOPMWorkQueue
->incrementProducerCount();
1070 // A child has gone away, re-scan children desires and clamp bits.
1071 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1073 if (!fAdjustPowerScheduled
)
1075 IOPMRequest
* request
;
1076 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1079 submitPMRequest( request
);
1080 fAdjustPowerScheduled
= true;
1087 //*********************************************************************************
1088 // [public] registerPowerDriver
1090 // A driver has called us volunteering to control power to our device.
1091 //*********************************************************************************
1093 IOReturn
IOService::registerPowerDriver(
1094 IOService
* powerDriver
,
1095 IOPMPowerState
* powerStates
,
1096 unsigned long numberOfStates
)
1098 IOPMRequest
* request
;
1099 IOPMPSEntry
* powerStatesCopy
= 0;
1100 IOPMPowerStateIndex stateOrder
;
1101 IOReturn error
= kIOReturnSuccess
;
1104 return IOPMNotYetInitialized
;
1106 if (!powerStates
|| (numberOfStates
< 2))
1108 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1109 return kIOReturnBadArgument
;
1112 if (!powerDriver
|| !powerDriver
->initialized
)
1114 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1115 return kIOReturnBadArgument
;
1118 if (powerStates
[0].version
> kIOPMPowerStateVersion2
)
1120 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1121 return kIOReturnBadArgument
;
1125 // Make a copy of the supplied power state array.
1126 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1127 if (!powerStatesCopy
)
1129 error
= kIOReturnNoMemory
;
1133 // Initialize to bogus values
1134 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1135 powerStatesCopy
[i
].stateOrderToIndex
= kIOPMPowerStateMax
;
1137 for (uint32_t i
= 0; i
< numberOfStates
; i
++)
1139 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1140 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1141 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1142 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1143 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1144 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1145 if (powerStates
[i
].version
>= kIOPMPowerStateVersion2
)
1146 stateOrder
= powerStates
[i
].stateOrder
;
1150 if (stateOrder
< numberOfStates
)
1152 powerStatesCopy
[i
].stateOrder
= stateOrder
;
1153 powerStatesCopy
[stateOrder
].stateOrderToIndex
= i
;
1157 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1159 if (powerStatesCopy
[i
].stateOrderToIndex
== kIOPMPowerStateMax
)
1161 // power state order missing
1162 error
= kIOReturnBadArgument
;
1166 if (kIOReturnSuccess
!= error
)
1169 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
;
1186 if (powerStatesCopy
)
1187 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1192 //*********************************************************************************
1193 // [private] handleRegisterPowerDriver
1194 //*********************************************************************************
1196 void IOService::handleRegisterPowerDriver( IOPMRequest
* request
)
1198 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1199 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1200 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1201 unsigned long i
, stateIndex
;
1202 unsigned long lowestPowerState
;
1206 PM_ASSERT_IN_GATE();
1207 assert(powerStates
);
1208 assert(powerDriver
);
1209 assert(numberOfStates
> 1);
1211 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 // OR'in all the output power flags
1226 fMergedOutputPowerFlags
= 0;
1227 fDeviceUsablePowerState
= lowestPowerState
;
1228 for ( i
= 0; i
< numberOfStates
; i
++ )
1230 fMergedOutputPowerFlags
|= fPowerStates
[i
].outputPowerFlags
;
1232 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
1233 assert(stateIndex
< numberOfStates
);
1234 if ((fDeviceUsablePowerState
== lowestPowerState
) &&
1235 (fPowerStates
[stateIndex
].capabilityFlags
& IOPMDeviceUsable
))
1237 // The minimum power state that the device is usable
1238 fDeviceUsablePowerState
= stateIndex
;
1242 // Register powerDriver as interested, unless already done.
1243 // We don't want to register the default implementation since
1244 // it does nothing. One ramification of not always registering
1245 // is the one fewer retain count held.
1247 root
= getPlatform()->getProvider();
1250 ((OSMemberFunctionCast(void (*)(void),
1251 root
, &IOService::powerStateDidChangeTo
)) !=
1252 ((OSMemberFunctionCast(void (*)(void),
1253 this, &IOService::powerStateDidChangeTo
)))) ||
1254 ((OSMemberFunctionCast(void (*)(void),
1255 root
, &IOService::powerStateWillChangeTo
)) !=
1256 ((OSMemberFunctionCast(void (*)(void),
1257 this, &IOService::powerStateWillChangeTo
)))))
1259 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
)
1262 fInterestedDrivers
->appendNewInformee(powerDriver
);
1267 // Examine all existing power clients and perform limit check.
1269 if (fPowerClients
&&
1270 (iter
= OSCollectionIterator::withCollection(fPowerClients
)))
1272 const OSSymbol
* client
;
1273 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
1275 IOPMPowerStateIndex powerState
= getPowerStateForClient(client
);
1276 if (powerState
>= numberOfStates
)
1278 updatePowerClient(client
, fHighestPowerState
);
1284 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1286 IOPMPowerStateIndex tempDesire
;
1287 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1288 // initially change into the state we are already in
1289 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1290 adjustPowerState(tempDesire
);
1295 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1296 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1299 powerDriver
->release();
1302 //*********************************************************************************
1303 // [public] registerInterestedDriver
1305 // Add the caller to our list of interested drivers and return our current
1306 // power state. If we don't have a power-controlling driver yet, we will
1307 // call this interested driver again later when we do get a driver and find
1308 // out what the current power state of the device is.
1309 //*********************************************************************************
1311 IOPMPowerFlags
IOService::registerInterestedDriver( IOService
* driver
)
1313 IOPMRequest
* request
;
1316 if (!driver
|| !initialized
|| !fInterestedDrivers
)
1320 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1321 if (fInsertInterestSet
== NULL
)
1322 fInsertInterestSet
= OSSet::withCapacity(4);
1323 if (fInsertInterestSet
)
1325 fInsertInterestSet
->setObject(driver
);
1326 if (fRemoveInterestSet
)
1327 fRemoveInterestSet
->removeObject(driver
);
1333 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1335 submitPMRequest( request
);
1338 // This return value cannot be trusted, but return a value
1339 // for those clients that care.
1341 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1342 return kIOPMDeviceUsable
;
1345 //*********************************************************************************
1346 // [public] deRegisterInterestedDriver
1347 //*********************************************************************************
1349 IOReturn
IOService::deRegisterInterestedDriver( IOService
* driver
)
1351 IOPMinformee
* item
;
1352 IOPMRequest
* request
;
1356 return kIOReturnBadArgument
;
1357 if (!initialized
|| !fInterestedDrivers
)
1358 return IOPMNotPowerManaged
;
1361 if (fInsertInterestSet
)
1363 fInsertInterestSet
->removeObject(driver
);
1366 item
= fInterestedDrivers
->findItem(driver
);
1370 return kIOReturnNotFound
;
1373 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1374 if (fRemoveInterestSet
== NULL
)
1375 fRemoveInterestSet
= OSSet::withCapacity(4);
1376 if (fRemoveInterestSet
)
1378 fRemoveInterestSet
->setObject(driver
);
1381 item
->active
= false;
1382 waitForPMDriverCall( driver
);
1389 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1391 submitPMRequest( request
);
1397 //*********************************************************************************
1398 // [private] handleInterestChanged
1400 // Handle interest added or removed.
1401 //*********************************************************************************
1403 void IOService::handleInterestChanged( IOPMRequest
* request
)
1406 IOPMinformee
* informee
;
1407 IOPMinformeeList
* list
= fInterestedDrivers
;
1411 if (fInsertInterestSet
)
1413 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject()))
1415 if (list
->findItem(driver
) == NULL
)
1417 informee
= list
->appendNewInformee(driver
);
1419 fInsertInterestSet
->removeObject(driver
);
1421 fInsertInterestSet
->release();
1422 fInsertInterestSet
= 0;
1425 if (fRemoveInterestSet
)
1427 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject()))
1429 informee
= list
->findItem(driver
);
1432 // Clean-up async interest acknowledgement
1433 if (fHeadNotePendingAcks
&& informee
->timer
)
1435 informee
->timer
= 0;
1436 fHeadNotePendingAcks
--;
1438 list
->removeFromList(driver
);
1440 fRemoveInterestSet
->removeObject(driver
);
1442 fRemoveInterestSet
->release();
1443 fRemoveInterestSet
= 0;
1449 //*********************************************************************************
1450 // [public] acknowledgePowerChange
1452 // After we notified one of the interested drivers or a power-domain child
1453 // of an impending change in power, it has called to say it is now
1454 // prepared for the change. If this object is the last to
1455 // acknowledge this change, we take whatever action we have been waiting
1457 // That may include acknowledging to our parent. In this case, we do it
1458 // last of all to insure that this doesn't cause the parent to call us some-
1459 // where else and alter data we are relying on here (like the very existance
1460 // of a "current change note".)
1461 //*********************************************************************************
1463 IOReturn
IOService::acknowledgePowerChange( IOService
* whichObject
)
1465 IOPMRequest
* request
;
1468 return IOPMNotYetInitialized
;
1470 return kIOReturnBadArgument
;
1472 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1474 return kIOReturnNoMemory
;
1476 whichObject
->retain();
1477 request
->fArg0
= whichObject
;
1479 submitPMRequest( request
);
1483 //*********************************************************************************
1484 // [private] handleAcknowledgePowerChange
1485 //*********************************************************************************
1487 bool IOService::handleAcknowledgePowerChange( IOPMRequest
* request
)
1489 IOPMinformee
* informee
;
1490 unsigned long childPower
= kIOPMUnknown
;
1491 IOService
* theChild
;
1492 IOService
* whichObject
;
1493 bool all_acked
= false;
1495 PM_ASSERT_IN_GATE();
1496 whichObject
= (IOService
*) request
->fArg0
;
1497 assert(whichObject
);
1499 // one of our interested drivers?
1500 informee
= fInterestedDrivers
->findItem( whichObject
);
1501 if ( informee
== NULL
)
1503 if ( !isChild(whichObject
, gIOPowerPlane
) )
1505 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1508 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1511 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1514 if ( fHeadNotePendingAcks
!= 0 )
1516 assert(fPowerStates
!= NULL
);
1518 // yes, make sure we're expecting acks
1519 if ( informee
!= NULL
)
1521 // it's an interested driver
1522 // make sure we're expecting this ack
1523 if ( informee
->timer
!= 0 )
1526 if (informee
->timer
> 0)
1528 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1529 if (nsec
> LOG_SETPOWER_TIMES
) {
1530 getPMRootDomain()->pmStatsRecordApplicationResponse(
1531 gIOPMStatsDriverPSChangeSlow
, informee
->whatObject
->getName(),
1532 fDriverCallReason
, NS_TO_MS(nsec
), informee
->whatObject
->getRegistryEntryID(),
1533 NULL
, fHeadNotePowerState
);
1538 informee
->timer
= 0;
1539 // that's one fewer to worry about
1540 fHeadNotePendingAcks
--;
1542 // this driver has already acked
1543 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1547 // make sure we're expecting this ack
1548 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1550 // that's one fewer to worry about
1551 fHeadNotePendingAcks
--;
1552 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1553 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1556 childPower
= theChild
->currentPowerConsumption();
1557 theChild
->release();
1559 if ( childPower
== kIOPMUnknown
)
1561 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1563 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
1565 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1571 if ( fHeadNotePendingAcks
== 0 ) {
1572 // yes, stop the timer
1574 // and now we can continue
1578 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1583 whichObject
->release();
1588 //*********************************************************************************
1589 // [public] acknowledgeSetPowerState
1591 // After we instructed our controlling driver to change power states,
1592 // it has called to say it has finished doing so.
1593 // We continue to process the power state change.
1594 //*********************************************************************************
1596 IOReturn
IOService::acknowledgeSetPowerState( void )
1598 IOPMRequest
* request
;
1601 return IOPMNotYetInitialized
;
1603 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1605 return kIOReturnNoMemory
;
1607 submitPMRequest( request
);
1608 return kIOReturnSuccess
;
1611 //*********************************************************************************
1612 // [private] adjustPowerState
1613 //*********************************************************************************
1615 void IOService::adjustPowerState( uint32_t clamp
)
1617 PM_ASSERT_IN_GATE();
1618 computeDesiredState(clamp
, false);
1619 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
))
1621 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1623 // Indicate that children desires must be ignored, and do not ask
1624 // apps for permission to drop power. This is used by root domain
1625 // for demand sleep.
1627 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
1628 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1631 /* flags */ changeFlags
,
1632 /* power state */ fDesiredPowerState
,
1633 /* domain flags */ 0,
1635 /* parent flags */ 0);
1639 //*********************************************************************************
1640 // [public] synchronizePowerTree
1641 //*********************************************************************************
1643 IOReturn
IOService::synchronizePowerTree(
1644 IOOptionBits options
,
1645 IOService
* notifyRoot
)
1647 IOPMRequest
* request_c
= 0;
1648 IOPMRequest
* request_s
;
1650 if (this != getPMRootDomain())
1651 return kIOReturnBadArgument
;
1653 return kIOPMNotYetInitialized
;
1655 OUR_PMLog(kPMLogCSynchronizePowerTree
, options
, (notifyRoot
!= 0));
1661 // Cancels don't need to be synchronized.
1662 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1663 if (nr
) submitPMRequest(nr
);
1664 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1665 if (nr
) submitPMRequest(nr
);
1668 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1670 goto error_no_memory
;
1672 if (options
& kIOPMSyncCancelPowerDown
)
1673 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1676 request_c
->attachNextRequest( request_s
);
1677 submitPMRequest(request_c
);
1680 request_s
->fArg0
= (void *)(uintptr_t) options
;
1681 submitPMRequest(request_s
);
1683 return kIOReturnSuccess
;
1686 if (request_c
) releasePMRequest(request_c
);
1687 if (request_s
) releasePMRequest(request_s
);
1688 return kIOReturnNoMemory
;
1691 //*********************************************************************************
1692 // [private] handleSynchronizePowerTree
1693 //*********************************************************************************
1695 void IOService::handleSynchronizePowerTree( IOPMRequest
* request
)
1697 PM_ASSERT_IN_GATE();
1698 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1699 (fCurrentPowerState
== fHighestPowerState
))
1701 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1704 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1705 (options
& kIOPMSyncNoChildNotify
),
1706 /* power state */ fCurrentPowerState
,
1707 /* domain flags */ 0,
1709 /* parent flags */ 0);
1714 //*********************************************************************************
1715 // [deprecated] powerDomainWillChangeTo
1717 // Called by the power-hierarchy parent notifying of a new power state
1718 // in the power domain.
1719 // We enqueue a parent power-change to our queue of power changes.
1720 // This may or may not cause us to change power, depending on what
1721 // kind of change is occuring in the domain.
1722 //*********************************************************************************
1724 IOReturn
IOService::powerDomainWillChangeTo(
1725 IOPMPowerFlags newPowerFlags
,
1726 IOPowerConnection
* whichParent
)
1729 return kIOReturnUnsupported
;
1731 #endif /* !__LP64__ */
1733 //*********************************************************************************
1734 // [private] handlePowerDomainWillChangeTo
1735 //*********************************************************************************
1737 void IOService::handlePowerDomainWillChangeTo( IOPMRequest
* request
)
1739 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1740 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1741 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1742 IOPMPowerChangeFlags myChangeFlags
;
1745 IOPowerConnection
* connection
;
1746 IOPMPowerStateIndex maxPowerState
;
1747 IOPMPowerFlags combinedPowerFlags
;
1748 bool savedParentsKnowState
;
1749 IOReturn result
= IOPMAckImplied
;
1751 PM_ASSERT_IN_GATE();
1752 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1754 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1756 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1760 savedParentsKnowState
= fParentsKnowState
;
1762 // Combine parents' output power flags.
1764 combinedPowerFlags
= 0;
1766 iter
= getParentIterator(gIOPowerPlane
);
1769 while ( (next
= iter
->getNextObject()) )
1771 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1773 if ( connection
== whichParent
)
1774 combinedPowerFlags
|= parentPowerFlags
;
1776 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1782 // If our initial change has yet to occur, then defer the power change
1783 // until after the power domain has completed its power transition.
1785 if ( fControllingDriver
&& !fInitialPowerChange
)
1787 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1788 combinedPowerFlags
);
1790 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1792 // fMaxPowerState set a limit on self-initiated power changes.
1793 // Update it before a parent power drop.
1794 fMaxPowerState
= maxPowerState
;
1797 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1798 // to avoid propagating the root change flags if any service must
1799 // change power state due to root's will-change notification.
1800 // Root does not change power state for kIOPMSynchronize.
1802 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1803 (parentChangeFlags
& kIOPMSynchronize
);
1805 result
= startPowerChange(
1806 /* flags */ myChangeFlags
,
1807 /* power state */ maxPowerState
,
1808 /* domain flags */ combinedPowerFlags
,
1809 /* connection */ whichParent
,
1810 /* parent flags */ parentPowerFlags
);
1813 // If parent is dropping power, immediately update the parent's
1814 // capability flags. Any future merging of parent(s) combined
1815 // power flags should account for this power drop.
1817 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1819 setParentInfo(parentPowerFlags
, whichParent
, true);
1822 // Parent is expecting an ACK from us. If we did not embark on a state
1823 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1824 // still required to issue an ACK to our parent.
1826 if (IOPMAckImplied
== result
)
1829 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1833 parent
->acknowledgePowerChange( whichParent
);
1839 // Drop the retain from notifyChild().
1840 if (whichParent
) whichParent
->release();
1844 //*********************************************************************************
1845 // [deprecated] powerDomainDidChangeTo
1847 // Called by the power-hierarchy parent after the power state of the power domain
1848 // has settled at a new level.
1849 // We enqueue a parent power-change to our queue of power changes.
1850 // This may or may not cause us to change power, depending on what
1851 // kind of change is occuring in the domain.
1852 //*********************************************************************************
1854 IOReturn
IOService::powerDomainDidChangeTo(
1855 IOPMPowerFlags newPowerFlags
,
1856 IOPowerConnection
* whichParent
)
1859 return kIOReturnUnsupported
;
1861 #endif /* !__LP64__ */
1863 //*********************************************************************************
1864 // [private] handlePowerDomainDidChangeTo
1865 //*********************************************************************************
1867 void IOService::handlePowerDomainDidChangeTo( IOPMRequest
* request
)
1869 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1870 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1871 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1872 IOPMPowerChangeFlags myChangeFlags
;
1873 IOPMPowerStateIndex maxPowerState
;
1874 IOPMPowerStateIndex initialDesire
= kPowerStateZero
;
1875 bool computeDesire
= false;
1876 bool desireChanged
= false;
1877 bool savedParentsKnowState
;
1878 IOReturn result
= IOPMAckImplied
;
1880 PM_ASSERT_IN_GATE();
1881 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1883 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1885 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1889 savedParentsKnowState
= fParentsKnowState
;
1891 setParentInfo(parentPowerFlags
, whichParent
, true);
1893 if ( fControllingDriver
)
1895 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1896 fParentsCurrentPowerFlags
);
1898 if ((parentChangeFlags
& kIOPMDomainPowerDrop
) == 0)
1900 // fMaxPowerState set a limit on self-initiated power changes.
1901 // Update it after a parent power rise.
1902 fMaxPowerState
= maxPowerState
;
1905 if (fInitialPowerChange
)
1907 computeDesire
= true;
1908 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1909 fParentsCurrentPowerFlags
);
1911 else if (parentChangeFlags
& kIOPMRootChangeUp
)
1913 if (fAdvisoryTickleUsed
)
1915 // On system wake, re-compute the desired power state since
1916 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1917 // which is an input to computeDesiredState(). This is not
1918 // necessary for a dark wake because powerChangeDone() will
1919 // handle the dark to full wake case, but it does no harm.
1921 desireChanged
= true;
1924 if (fResetPowerStateOnWake
)
1926 // Query the driver for the desired power state on system wake.
1927 // Default implementation returns the lowest power state.
1929 IOPMPowerStateIndex wakePowerState
=
1930 fControllingDriver
->initialPowerStateForDomainState(
1931 kIOPMRootDomainState
| kIOPMPowerOn
);
1933 // fDesiredPowerState was adjusted before going to sleep
1934 // with fDeviceDesire at min.
1936 if (StateOrder(wakePowerState
) > StateOrder(fDesiredPowerState
))
1938 // Must schedule a power adjustment if we changed the
1939 // device desire. That will update the desired domain
1940 // power on the parent power connection and ping the
1941 // power parent if necessary.
1943 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1944 desireChanged
= true;
1949 if (computeDesire
|| desireChanged
)
1950 computeDesiredState(initialDesire
, false);
1952 // Absorb and propagate parent's broadcast flags
1953 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1954 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1956 result
= startPowerChange(
1957 /* flags */ myChangeFlags
,
1958 /* power state */ maxPowerState
,
1959 /* domain flags */ fParentsCurrentPowerFlags
,
1960 /* connection */ whichParent
,
1961 /* parent flags */ 0);
1964 // Parent is expecting an ACK from us. If we did not embark on a state
1965 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1966 // still required to issue an ACK to our parent.
1968 if (IOPMAckImplied
== result
)
1971 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1975 parent
->acknowledgePowerChange( whichParent
);
1980 // If the parent registers its power driver late, then this is the
1981 // first opportunity to tell our parent about our desire. Or if the
1982 // child's desire changed during a parent change notify.
1984 if (fControllingDriver
&&
1985 ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
))
1987 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
1988 getName(), fParentsKnowState
);
1989 requestDomainPower( fDesiredPowerState
);
1993 // Drop the retain from notifyChild().
1994 if (whichParent
) whichParent
->release();
1997 //*********************************************************************************
1998 // [private] setParentInfo
2000 // Set our connection data for one specific parent, and then combine all the parent
2002 //*********************************************************************************
2004 void IOService::setParentInfo(
2005 IOPMPowerFlags newPowerFlags
,
2006 IOPowerConnection
* whichParent
,
2011 IOPowerConnection
* conn
;
2013 PM_ASSERT_IN_GATE();
2015 // set our connection data
2016 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
2017 whichParent
->setParentKnowsState(knowsState
);
2019 // recompute our parent info
2020 fParentsCurrentPowerFlags
= 0;
2021 fParentsKnowState
= true;
2023 iter
= getParentIterator(gIOPowerPlane
);
2026 while ( (next
= iter
->getNextObject()) )
2028 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
2030 fParentsKnowState
&= conn
->parentKnowsState();
2031 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
2038 //******************************************************************************
2039 // [private] trackSystemSleepPreventers
2040 //******************************************************************************
2042 void IOService::trackSystemSleepPreventers(
2043 IOPMPowerStateIndex oldPowerState
,
2044 IOPMPowerStateIndex newPowerState
,
2045 IOPMPowerChangeFlags changeFlags __unused
)
2047 IOPMPowerFlags oldCapability
, newCapability
;
2049 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2050 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2051 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2052 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2054 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)
2056 if (oldCapability
== newCapability
)
2059 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
)
2061 bool enablePrevention
= ((oldCapability
& kIOPMPreventIdleSleep
) == 0);
2062 bool idleCancelAllowed
= getPMRootDomain()->updatePreventIdleSleepList(
2063 this, enablePrevention
);
2064 #if SUPPORT_IDLE_CANCEL
2065 if (idleCancelAllowed
&& enablePrevention
)
2067 IOPMRequest
* cancelRequest
;
2069 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2072 submitPMRequest( cancelRequest
);
2078 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
)
2080 getPMRootDomain()->updatePreventSystemSleepList(this,
2081 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2085 //*********************************************************************************
2086 // [public] requestPowerDomainState
2088 // Called on a power parent when a child's power requirement changes.
2089 //*********************************************************************************
2091 IOReturn
IOService::requestPowerDomainState(
2092 IOPMPowerFlags childRequestPowerFlags
,
2093 IOPowerConnection
* childConnection
,
2094 unsigned long specification
)
2096 IOPMPowerStateIndex order
, powerState
;
2097 IOPMPowerFlags outputPowerFlags
;
2099 IOPMRequest
* subRequest
;
2100 bool adjustPower
= false;
2103 return IOPMNotYetInitialized
;
2105 if (gIOPMWorkLoop
->onThread() == false)
2107 PM_LOG("%s::requestPowerDomainState\n", getName());
2108 return kIOReturnSuccess
;
2111 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2113 if (!isChild(childConnection
, gIOPowerPlane
))
2114 return kIOReturnNotAttached
;
2116 if (!fControllingDriver
|| !fNumberOfPowerStates
)
2117 return kIOReturnNotReady
;
2119 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2122 // Remove flags from child request which we can't possibly supply
2123 childRequestPowerFlags
&= fMergedOutputPowerFlags
;
2125 // Merge in the power flags contributed by this power parent
2126 // at its current or impending power state.
2128 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2129 if (fMachineState
!= kIOPM_Finished
)
2131 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
)
2133 // Use the lower power state when dropping power.
2134 // Must be careful since a power drop can be cancelled
2135 // from the following states:
2136 // - kIOPM_OurChangeTellClientsPowerDown
2137 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2139 // The child must not wait for this parent to raise power
2140 // if the power drop was cancelled. The solution is to cancel
2141 // the power drop if possible, then schedule an adjustment to
2142 // re-evaluate the parent's power state.
2144 // Root domain is excluded to avoid idle sleep issues. And allow
2145 // root domain children to pop up when system is going to sleep.
2147 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2148 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
2150 fDoNotPowerDown
= true; // cancel power drop
2151 adjustPower
= true; // schedule an adjustment
2152 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2153 getName(), fMachineState
, child
->getName());
2157 // Beyond cancellation point, report the impending state.
2159 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2162 else if (IS_POWER_RISE
)
2164 // When raising power, must report the output power flags from
2165 // child's perspective. A child power request may arrive while
2166 // parent is transitioning upwards. If a request arrives after
2167 // setParentInfo() has already recorded the output power flags
2168 // for the next power state, then using the power supplied by
2169 // fCurrentPowerState is incorrect, and might cause the child
2170 // to wait when it should not.
2172 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2175 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2177 // Map child's requested power flags to one of our power state.
2179 for (order
= 0; order
< fNumberOfPowerStates
; order
++)
2181 powerState
= fPowerStates
[order
].stateOrderToIndex
;
2182 if ((fPowerStates
[powerState
].outputPowerFlags
& childRequestPowerFlags
)
2183 == childRequestPowerFlags
)
2186 if (order
>= fNumberOfPowerStates
)
2188 powerState
= kPowerStateZero
;
2191 // Conditions that warrants a power adjustment on this parent.
2192 // Adjust power will also propagate any changes to the child's
2193 // prevent idle/sleep flags towards the root domain.
2195 if (!childConnection
->childHasRequestedPower() ||
2196 (powerState
!= childConnection
->getDesiredDomainState()))
2199 #if ENABLE_DEBUG_LOGS
2202 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2203 getName(), child
->getName(),
2204 !childConnection
->childHasRequestedPower(),
2205 (uint32_t) childConnection
->getDesiredDomainState(),
2206 (uint32_t) powerState
);
2210 // Record the child's desires on the connection.
2211 childConnection
->setChildHasRequestedPower();
2212 childConnection
->setDesiredDomainState( powerState
);
2214 // Schedule a request to re-evaluate all children desires and
2215 // adjust power state. Submit a request if one wasn't pending,
2216 // or if the current request is part of a call tree.
2218 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2219 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest()))
2221 subRequest
= acquirePMRequest(
2222 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2225 submitPMRequest( subRequest
);
2226 fAdjustPowerScheduled
= true;
2230 return kIOReturnSuccess
;
2233 //*********************************************************************************
2234 // [public] temporaryPowerClampOn
2236 // A power domain wants to clamp its power on till it has children which
2237 // will thendetermine the power domain state.
2239 // We enter the highest state until addPowerChild is called.
2240 //*********************************************************************************
2242 IOReturn
IOService::temporaryPowerClampOn( void )
2244 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2247 //*********************************************************************************
2248 // [public] makeUsable
2250 // Some client of our device is asking that we become usable. Although
2251 // this has not come from a subclassed device object, treat it exactly
2252 // as if it had. In this way, subsequent requests for lower power from
2253 // a subclassed device object will pre-empt this request.
2255 // We treat this as a subclass object request to switch to the
2256 // highest power state.
2257 //*********************************************************************************
2259 IOReturn
IOService::makeUsable( void )
2261 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2262 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2265 //*********************************************************************************
2266 // [public] currentCapability
2267 //*********************************************************************************
2269 IOPMPowerFlags
IOService::currentCapability( void )
2272 return IOPMNotPowerManaged
;
2274 return fCurrentCapabilityFlags
;
2277 //*********************************************************************************
2278 // [public] changePowerStateTo
2280 // Called by our power-controlling driver to change power state. The new desired
2281 // power state is computed and compared against the current power state. If those
2282 // power states differ, then a power state change is initiated.
2283 //*********************************************************************************
2285 IOReturn
IOService::changePowerStateTo( unsigned long ordinal
)
2287 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2288 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2291 //*********************************************************************************
2292 // [protected] changePowerStateToPriv
2294 // Called by our driver subclass to change power state. The new desired power
2295 // state is computed and compared against the current power state. If those
2296 // power states differ, then a power state change is initiated.
2297 //*********************************************************************************
2299 IOReturn
IOService::changePowerStateToPriv( unsigned long ordinal
)
2301 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2302 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2305 //*********************************************************************************
2306 // [public] changePowerStateWithOverrideTo
2308 // Called by our driver subclass to change power state. The new desired power
2309 // state is computed and compared against the current power state. If those
2310 // power states differ, then a power state change is initiated.
2311 // Override enforced - Children and Driver desires are ignored.
2312 //*********************************************************************************
2314 IOReturn
IOService::changePowerStateWithOverrideTo( IOPMPowerStateIndex ordinal
,
2315 IOPMRequestTag tag
)
2317 IOPMRequest
* request
;
2320 return kIOPMNotYetInitialized
;
2322 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2324 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2326 return kIOReturnNoMemory
;
2328 gIOPMPowerClientDevice
->retain();
2329 request
->fRequestTag
= tag
;
2330 request
->fArg0
= (void *) ordinal
;
2331 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2335 request
->installCompletionAction( action
, target
, param
);
2338 // Prevent needless downwards power transitions by clamping power
2339 // until the scheduled request is executed.
2341 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
))
2343 fTempClampPowerState
= StateMax(fTempClampPowerState
, ordinal
);
2345 fOverrideMaxPowerState
= ordinal
;
2346 request
->fArg2
= (void *) (uintptr_t) true;
2349 submitPMRequest( request
);
2353 //*********************************************************************************
2354 // [public] changePowerStateForRootDomain
2356 // Adjust the root domain's power desire on the target
2357 //*********************************************************************************
2359 IOReturn
IOService::changePowerStateForRootDomain( IOPMPowerStateIndex ordinal
)
2361 OUR_PMLog(kPMLogChangeStateForRootDomain
, ordinal
, 0);
2362 return requestPowerState( gIOPMPowerClientRootDomain
, ordinal
);
2365 //*********************************************************************************
2366 // [public for PMRD] quiescePowerTree
2368 // For root domain to issue a request to quiesce the power tree.
2369 // Supplied callback invoked upon completion.
2370 //*********************************************************************************
2372 IOReturn
IOService::quiescePowerTree(
2373 void * target
, IOPMCompletionAction action
, void * param
)
2375 IOPMRequest
* request
;
2378 return kIOPMNotYetInitialized
;
2379 if (!target
|| !action
)
2380 return kIOReturnBadArgument
;
2382 OUR_PMLog(kPMLogQuiescePowerTree
, 0, 0);
2384 // Target the root node instead of root domain. This is to avoid blocking
2385 // the quiesce request behind an existing root domain request in the work
2386 // queue. Root parent and root domain requests in the work queue must not
2387 // block the completion of the quiesce request.
2389 request
= acquirePMRequest(gIOPMRootNode
, kIOPMRequestTypeQuiescePowerTree
);
2391 return kIOReturnNoMemory
;
2393 request
->installCompletionAction(target
, action
, param
);
2395 // Submit through the normal request flow. This will make sure any request
2396 // already in the request queue will get pushed over to the work queue for
2397 // execution. Any request submitted after this request may not be serviced.
2399 submitPMRequest( request
);
2400 return kIOReturnSuccess
;
2403 //*********************************************************************************
2404 // [private] requestPowerState
2405 //*********************************************************************************
2407 IOReturn
IOService::requestPowerState(
2408 const OSSymbol
* client
,
2411 IOPMRequest
* request
;
2414 return kIOReturnBadArgument
;
2416 return kIOPMNotYetInitialized
;
2418 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2420 return kIOReturnNoMemory
;
2423 request
->fArg0
= (void *)(uintptr_t) state
;
2424 request
->fArg1
= (void *) client
;
2428 request
->installCompletionAction( action
, target
, param
);
2431 // Prevent needless downwards power transitions by clamping power
2432 // until the scheduled request is executed.
2434 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
))
2436 fTempClampPowerState
= StateMax(fTempClampPowerState
, state
);
2438 request
->fArg2
= (void *) (uintptr_t) true;
2441 submitPMRequest( request
);
2445 //*********************************************************************************
2446 // [private] handleRequestPowerState
2447 //*********************************************************************************
2449 void IOService::handleRequestPowerState( IOPMRequest
* request
)
2451 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2452 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2454 PM_ASSERT_IN_GATE();
2457 assert(fTempClampCount
!= 0);
2458 if (fTempClampCount
) fTempClampCount
--;
2459 if (!fTempClampCount
) fTempClampPowerState
= kPowerStateZero
;
2462 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
))
2463 state
= fHighestPowerState
;
2465 // The power suppression due to changePowerStateWithOverrideTo() expires
2466 // upon the next "device" power request - changePowerStateToPriv().
2468 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2469 (client
== gIOPMPowerClientDevice
))
2470 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2472 if ((state
== kPowerStateZero
) &&
2473 (client
!= gIOPMPowerClientDevice
) &&
2474 (client
!= gIOPMPowerClientDriver
) &&
2475 (client
!= gIOPMPowerClientChildProxy
))
2476 removePowerClient(client
);
2478 updatePowerClient(client
, state
);
2484 //*********************************************************************************
2485 // [private] Helper functions to update/remove power clients.
2486 //*********************************************************************************
2488 void IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2490 IOPMPowerStateIndex oldPowerState
= kPowerStateZero
;
2493 fPowerClients
= OSDictionary::withCapacity(4);
2494 if (fPowerClients
&& client
)
2496 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2499 oldPowerState
= num
->unsigned32BitValue();
2500 num
->setValue(powerState
);
2504 num
= OSNumber::withNumber(powerState
, 32);
2507 fPowerClients
->setObject(client
, num
);
2512 PM_ACTION_3(actionUpdatePowerClient
, client
, oldPowerState
, powerState
);
2516 void IOService::removePowerClient( const OSSymbol
* client
)
2518 if (fPowerClients
&& client
)
2519 fPowerClients
->removeObject(client
);
2522 uint32_t IOService::getPowerStateForClient( const OSSymbol
* client
)
2524 uint32_t powerState
= kPowerStateZero
;
2526 if (fPowerClients
&& client
)
2528 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2529 if (num
) powerState
= num
->unsigned32BitValue();
2534 //*********************************************************************************
2535 // [protected] powerOverrideOnPriv
2536 //*********************************************************************************
2538 IOReturn
IOService::powerOverrideOnPriv( void )
2540 IOPMRequest
* request
;
2543 return IOPMNotYetInitialized
;
2545 if (gIOPMWorkLoop
->inGate())
2547 fDeviceOverrideEnabled
= true;
2551 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2553 return kIOReturnNoMemory
;
2555 submitPMRequest( request
);
2559 //*********************************************************************************
2560 // [protected] powerOverrideOffPriv
2561 //*********************************************************************************
2563 IOReturn
IOService::powerOverrideOffPriv( void )
2565 IOPMRequest
* request
;
2568 return IOPMNotYetInitialized
;
2570 if (gIOPMWorkLoop
->inGate())
2572 fDeviceOverrideEnabled
= false;
2576 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2578 return kIOReturnNoMemory
;
2580 submitPMRequest( request
);
2584 //*********************************************************************************
2585 // [private] handlePowerOverrideChanged
2586 //*********************************************************************************
2588 void IOService::handlePowerOverrideChanged( IOPMRequest
* request
)
2590 PM_ASSERT_IN_GATE();
2591 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
)
2593 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2594 fDeviceOverrideEnabled
= true;
2598 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2599 fDeviceOverrideEnabled
= false;
2605 //*********************************************************************************
2606 // [private] computeDesiredState
2607 //*********************************************************************************
2609 void IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2613 IOPowerConnection
* connection
;
2614 uint32_t desiredState
= kPowerStateZero
;
2615 uint32_t newPowerState
= kPowerStateZero
;
2616 bool hasChildren
= false;
2618 // Desired power state is always 0 without a controlling driver.
2620 if (!fNumberOfPowerStates
)
2622 fDesiredPowerState
= kPowerStateZero
;
2626 // Examine the children's desired power state.
2628 iter
= getChildIterator(gIOPowerPlane
);
2631 while ((next
= iter
->getNextObject()))
2633 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
2635 if (connection
->getReadyFlag() == false)
2637 PM_LOG3("[%s] %s: connection not ready\n",
2638 getName(), __FUNCTION__
);
2641 if (connection
->childHasRequestedPower())
2643 desiredState
= StateMax(connection
->getDesiredDomainState(), desiredState
);
2649 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2651 removePowerClient(gIOPMPowerClientChildren
);
2653 // Iterate through all power clients to determine the min power state.
2655 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2658 const OSSymbol
* client
;
2659 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
2661 // Ignore child and driver when override is in effect.
2662 if ((fDeviceOverrideEnabled
||
2663 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2664 ((client
== gIOPMPowerClientChildren
) ||
2665 (client
== gIOPMPowerClientDriver
)))
2668 // Ignore child proxy when children are present.
2669 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
))
2672 // Advisory tickles are irrelevant unless system is in full wake
2673 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2674 !gIOPMAdvisoryTickleEnabled
)
2677 desiredState
= getPowerStateForClient(client
);
2678 assert(desiredState
< fNumberOfPowerStates
);
2680 desiredState
, client
->getCStringNoCopy());
2682 newPowerState
= StateMax(newPowerState
, desiredState
);
2684 if (client
== gIOPMPowerClientDevice
)
2685 fDeviceDesire
= desiredState
;
2690 // Factor in the temporary power desires.
2692 newPowerState
= StateMax(newPowerState
, localClamp
);
2693 newPowerState
= StateMax(newPowerState
, fTempClampPowerState
);
2695 // Limit check against max power override.
2697 newPowerState
= StateMin(newPowerState
, fOverrideMaxPowerState
);
2699 // Limit check against number of power states.
2701 if (newPowerState
>= fNumberOfPowerStates
)
2702 newPowerState
= fHighestPowerState
;
2704 fDesiredPowerState
= newPowerState
;
2706 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2707 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2708 (uint32_t) fCurrentPowerState
, newPowerState
);
2712 // Restart idle timer if possible when device desire has increased.
2713 // Or if an advisory desire exists.
2715 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
2720 // Invalidate cached tickle power state when desires change, and not
2721 // due to a tickle request. In case the driver has requested a lower
2722 // power state, but the tickle is caching a higher power state which
2723 // will drop future tickles until the cached value is lowered or in-
2724 // validated. The invalidation must occur before the power transition
2725 // to avoid dropping a necessary tickle.
2727 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2728 (fActivityTicklePowerState
!= kInvalidTicklePowerState
))
2730 IOLockLock(fActivityLock
);
2731 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2732 IOLockUnlock(fActivityLock
);
2737 //*********************************************************************************
2738 // [public] currentPowerConsumption
2740 //*********************************************************************************
2742 unsigned long IOService::currentPowerConsumption( void )
2745 return kIOPMUnknown
;
2747 return fCurrentPowerConsumption
;
2750 //*********************************************************************************
2751 // [deprecated] getPMworkloop
2752 //*********************************************************************************
2755 IOWorkLoop
* IOService::getPMworkloop( void )
2757 return gIOPMWorkLoop
;
2763 //*********************************************************************************
2764 // Power Parent/Children Applier
2765 //*********************************************************************************
2768 applyToPowerChildren(
2769 IOService
* service
,
2770 IOServiceApplierFunction applier
,
2772 IOOptionBits options
)
2774 PM_ASSERT_IN_GATE();
2776 IORegistryEntry
* entry
;
2777 IORegistryIterator
* iter
;
2778 IOPowerConnection
* connection
;
2781 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2784 while ((entry
= iter
->getNextObject()))
2786 // Get child of IOPowerConnection objects
2787 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2789 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2792 (*applier
)(child
, context
);
2803 IOService
* service
,
2804 IOServiceApplierFunction applier
,
2806 IOOptionBits options
)
2808 PM_ASSERT_IN_GATE();
2810 IORegistryEntry
* entry
;
2811 IORegistryIterator
* iter
;
2812 IOPowerConnection
* connection
;
2815 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2816 options
| kIORegistryIterateParents
);
2819 while ((entry
= iter
->getNextObject()))
2821 // Get child of IOPowerConnection objects
2822 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2824 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2827 (*applier
)(parent
, context
);
2836 #endif /* NOT_YET */
2839 // MARK: Activity Tickle & Idle Timer
2841 void IOService::setAdvisoryTickleEnable( bool enable
)
2843 gIOPMAdvisoryTickleEnabled
= enable
;
2846 //*********************************************************************************
2847 // [public] activityTickle
2849 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2850 // flag to be set, and the device state checked. If the device has been
2851 // powered down, it is powered up again.
2852 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2853 // should be intercepted by a subclass.
2854 //*********************************************************************************
2856 bool IOService::activityTickle( unsigned long type
, unsigned long stateNumber
)
2858 IOPMRequest
* request
;
2859 bool noPowerChange
= true;
2860 uint32_t tickleFlags
;
2863 return true; // no power change
2865 if ((type
== kIOPMSuperclassPolicy1
) && StateOrder(stateNumber
))
2867 IOLockLock(fActivityLock
);
2869 // Record device activity for the idle timer handler.
2871 fDeviceWasActive
= true;
2872 fActivityTickleCount
++;
2873 clock_get_uptime(&fDeviceActiveTimestamp
);
2875 PM_ACTION_0(actionActivityTickle
);
2877 // Record the last tickle power state.
2878 // This helps to filter out redundant tickles as
2879 // this function may be called from the data path.
2881 if ((fActivityTicklePowerState
== kInvalidTicklePowerState
)
2882 || StateOrder(fActivityTicklePowerState
) < StateOrder(stateNumber
))
2884 fActivityTicklePowerState
= stateNumber
;
2885 noPowerChange
= false;
2887 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2888 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2891 request
->fArg0
= (void *) stateNumber
;
2892 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2893 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2894 submitPMRequest(request
);
2898 IOLockUnlock(fActivityLock
);
2901 else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2902 ((stateNumber
= fDeviceUsablePowerState
) != kPowerStateZero
))
2904 IOLockLock(fActivityLock
);
2906 fAdvisoryTickled
= true;
2908 if (fAdvisoryTicklePowerState
!= stateNumber
)
2910 fAdvisoryTicklePowerState
= stateNumber
;
2911 noPowerChange
= false;
2913 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2914 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2917 request
->fArg0
= (void *) stateNumber
;
2918 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2919 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2920 submitPMRequest(request
);
2924 IOLockUnlock(fActivityLock
);
2927 // Returns false if the activityTickle might cause a transition to a
2928 // higher powered state, true otherwise.
2930 return noPowerChange
;
2933 //*********************************************************************************
2934 // [private] handleActivityTickle
2935 //*********************************************************************************
2937 void IOService::handleActivityTickle( IOPMRequest
* request
)
2939 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2940 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
2941 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
2942 bool adjustPower
= false;
2944 PM_ASSERT_IN_GATE();
2945 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
))
2947 // Drivers that don't want power restored on wake will drop any
2948 // tickles that pre-dates the current system wake. The model is
2949 // that each wake is a fresh start, with power state depressed
2950 // until a new tickle or an explicit power up request from the
2951 // driver. It is possible for the PM work loop to enter the
2952 // system sleep path with tickle requests queued.
2957 if (tickleFlags
& kTickleTypeActivity
)
2959 IOPMPowerStateIndex deviceDesireOrder
= StateOrder(fDeviceDesire
);
2960 uint32_t idleTimerGeneration
= ticklePowerState
; // kTickleTypePowerDrop
2962 if (tickleFlags
& kTickleTypePowerRise
)
2964 if ((StateOrder(ticklePowerState
) > deviceDesireOrder
) &&
2965 (ticklePowerState
< fNumberOfPowerStates
))
2967 fIdleTimerMinPowerState
= ticklePowerState
;
2968 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2972 else if ((deviceDesireOrder
> StateOrder(fIdleTimerMinPowerState
)) &&
2973 (idleTimerGeneration
== fIdleTimerGeneration
))
2975 // Power drop due to idle timer expiration.
2976 // Do not allow idle timer to reduce power below tickle power.
2977 // This prevents the idle timer from decreasing the device desire
2978 // to zero and cancelling the effect of a pre-sleep tickle when
2979 // system wakes up to doze state, while the device is unable to
2980 // raise its power state to satisfy the tickle.
2982 deviceDesireOrder
--;
2983 if (deviceDesireOrder
< fNumberOfPowerStates
)
2985 ticklePowerState
= fPowerStates
[deviceDesireOrder
].stateOrderToIndex
;
2986 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2991 else // advisory tickle
2993 if (tickleFlags
& kTickleTypePowerRise
)
2995 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
2996 (ticklePowerState
< fNumberOfPowerStates
))
2998 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
2999 fHasAdvisoryDesire
= true;
3000 fAdvisoryTickleUsed
= true;
3005 IOLockLock(fActivityLock
);
3006 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3007 IOLockUnlock(fActivityLock
);
3010 else if (fHasAdvisoryDesire
)
3012 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
3013 fHasAdvisoryDesire
= false;
3024 //******************************************************************************
3025 // [public] setIdleTimerPeriod
3027 // A subclass policy-maker is using our standard idleness detection service.
3028 // Start the idle timer. Period is in seconds.
3029 //******************************************************************************
3031 IOReturn
IOService::setIdleTimerPeriod( unsigned long period
)
3034 return IOPMNotYetInitialized
;
3036 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
3038 IOPMRequest
* request
=
3039 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
3041 return kIOReturnNoMemory
;
3043 request
->fArg0
= (void *) period
;
3044 submitPMRequest( request
);
3046 return kIOReturnSuccess
;
3049 IOReturn
IOService::setIgnoreIdleTimer( bool ignore
)
3052 return IOPMNotYetInitialized
;
3054 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
3056 IOPMRequest
* request
=
3057 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
3059 return kIOReturnNoMemory
;
3061 request
->fArg0
= (void *) ignore
;
3062 submitPMRequest( request
);
3064 return kIOReturnSuccess
;
3067 //******************************************************************************
3068 // [public] nextIdleTimeout
3070 // Returns how many "seconds from now" the device should idle into its
3071 // next lowest power state.
3072 //******************************************************************************
3074 SInt32
IOService::nextIdleTimeout(
3075 AbsoluteTime currentTime
,
3076 AbsoluteTime lastActivity
,
3077 unsigned int powerState
)
3084 // Calculate time difference using funky macro from clock.h.
3085 delta
= currentTime
;
3086 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
3088 // Figure it in seconds.
3089 absolutetime_to_nanoseconds(delta
, &delta_ns
);
3090 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
3092 // Be paranoid about delta somehow exceeding timer period.
3093 if (delta_secs
< (int) fIdleTimerPeriod
)
3094 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3096 delay_secs
= (int) fIdleTimerPeriod
;
3098 return (SInt32
)delay_secs
;
3101 //*********************************************************************************
3102 // [public] start_PM_idle_timer
3103 //*********************************************************************************
3105 void IOService::start_PM_idle_timer( void )
3107 static const int maxTimeout
= 100000;
3108 static const int minTimeout
= 1;
3109 AbsoluteTime uptime
, deadline
;
3113 if (!initialized
|| !fIdleTimerPeriod
)
3116 IOLockLock(fActivityLock
);
3118 clock_get_uptime(&uptime
);
3120 // Subclasses may modify idle sleep algorithm
3121 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3123 // Check for out-of range responses
3124 if (idle_in
> maxTimeout
)
3126 // use standard implementation
3127 idle_in
= IOService::nextIdleTimeout(uptime
,
3128 fDeviceActiveTimestamp
,
3129 fCurrentPowerState
);
3130 } else if (idle_in
< minTimeout
) {
3131 idle_in
= fIdleTimerPeriod
;
3134 IOLockUnlock(fActivityLock
);
3136 fNextIdleTimerPeriod
= idle_in
;
3137 fIdleTimerStartTime
= uptime
;
3140 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3141 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3142 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3143 if (pending
) release();
3146 //*********************************************************************************
3147 // [private] restartIdleTimer
3148 //*********************************************************************************
3150 void IOService::restartIdleTimer( void )
3152 if (fDeviceDesire
!= kPowerStateZero
)
3154 fIdleTimerStopped
= false;
3155 fActivityTickleCount
= 0;
3156 start_PM_idle_timer();
3158 else if (fHasAdvisoryDesire
)
3160 fIdleTimerStopped
= false;
3161 start_PM_idle_timer();
3165 fIdleTimerStopped
= true;
3169 //*********************************************************************************
3170 // idle_timer_expired
3171 //*********************************************************************************
3175 thread_call_param_t arg0
, thread_call_param_t arg1
)
3177 IOService
* me
= (IOService
*) arg0
;
3180 gIOPMWorkLoop
->runAction(
3181 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3182 &IOService::idleTimerExpired
),
3188 //*********************************************************************************
3189 // [private] idleTimerExpired
3191 // The idle timer has expired. If there has been activity since the last
3192 // expiration, just restart the timer and return. If there has not been
3193 // activity, switch to the next lower power state and restart the timer.
3194 //*********************************************************************************
3196 void IOService::idleTimerExpired( void )
3198 IOPMRequest
* request
;
3199 bool restartTimer
= true;
3200 uint32_t tickleFlags
;
3202 if ( !initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3203 fLockedFlags
.PMStop
)
3206 fIdleTimerStartTime
= 0;
3208 IOLockLock(fActivityLock
);
3210 // Check for device activity (tickles) over last timer period.
3212 if (fDeviceWasActive
)
3214 // Device was active - do not drop power, restart timer.
3215 fDeviceWasActive
= false;
3217 else if (!fIdleTimerIgnored
)
3219 // No device activity - drop power state by one level.
3220 // Decrement the cached tickle power state when possible.
3221 // This value may be kInvalidTicklePowerState before activityTickle()
3222 // is called, but the power drop request must be issued regardless.
3224 if ((fActivityTicklePowerState
!= kInvalidTicklePowerState
) &&
3225 (fActivityTicklePowerState
!= kPowerStateZero
))
3226 fActivityTicklePowerState
--;
3228 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3229 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3232 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3233 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3234 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3235 submitPMRequest( request
);
3237 // Do not restart timer until after the tickle request has been
3240 restartTimer
= false;
3244 if (fAdvisoryTickled
)
3246 fAdvisoryTickled
= false;
3248 else if (fHasAdvisoryDesire
)
3250 // Want new tickles to turn into pm request after we drop the lock
3251 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3253 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3254 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3257 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3258 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3259 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3260 submitPMRequest( request
);
3262 // Do not restart timer until after the tickle request has been
3265 restartTimer
= false;
3269 IOLockUnlock(fActivityLock
);
3272 start_PM_idle_timer();
3276 //*********************************************************************************
3277 // [deprecated] PM_idle_timer_expiration
3278 //*********************************************************************************
3280 void IOService::PM_idle_timer_expiration( void )
3284 //*********************************************************************************
3285 // [deprecated] command_received
3286 //*********************************************************************************
3288 void IOService::command_received( void *statePtr
, void *, void * , void * )
3291 #endif /* !__LP64__ */
3293 //*********************************************************************************
3294 // [public] setAggressiveness
3296 // Pass on the input parameters to all power domain children. All those which are
3297 // power domains will pass it on to their children, etc.
3298 //*********************************************************************************
3300 IOReturn
IOService::setAggressiveness( unsigned long type
, unsigned long newLevel
)
3302 return kIOReturnSuccess
;
3305 //*********************************************************************************
3306 // [public] getAggressiveness
3308 // Called by the user client.
3309 //*********************************************************************************
3311 IOReturn
IOService::getAggressiveness( unsigned long type
, unsigned long * currentLevel
)
3313 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3316 return kIOReturnNotReady
;
3318 return rootDomain
->getAggressiveness( type
, currentLevel
);
3321 //*********************************************************************************
3322 // [public] getPowerState
3324 //*********************************************************************************
3326 UInt32
IOService::getPowerState( void )
3329 return kPowerStateZero
;
3331 return fCurrentPowerState
;
3335 //*********************************************************************************
3336 // [deprecated] systemWake
3338 // Pass this to all power domain children. All those which are
3339 // power domains will pass it on to their children, etc.
3340 //*********************************************************************************
3342 IOReturn
IOService::systemWake( void )
3346 IOPowerConnection
* connection
;
3347 IOService
* theChild
;
3349 iter
= getChildIterator(gIOPowerPlane
);
3352 while ( (next
= iter
->getNextObject()) )
3354 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
3356 if (connection
->getReadyFlag() == false)
3358 PM_LOG3("[%s] %s: connection not ready\n",
3359 getName(), __FUNCTION__
);
3363 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3366 theChild
->systemWake();
3367 theChild
->release();
3374 if ( fControllingDriver
!= NULL
)
3376 if ( fControllingDriver
->didYouWakeSystem() )
3385 //*********************************************************************************
3386 // [deprecated] temperatureCriticalForZone
3387 //*********************************************************************************
3389 IOReturn
IOService::temperatureCriticalForZone( IOService
* whichZone
)
3391 IOService
* theParent
;
3394 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3396 if ( inPlane(gIOPowerPlane
) && !IS_PM_ROOT
)
3398 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3401 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3405 theParent
->temperatureCriticalForZone(whichZone
);
3406 theParent
->release();
3412 #endif /* !__LP64__ */
3415 // MARK: Power Change (Common)
3417 //*********************************************************************************
3418 // [private] startPowerChange
3420 // All power state changes starts here.
3421 //*********************************************************************************
3423 IOReturn
IOService::startPowerChange(
3424 IOPMPowerChangeFlags changeFlags
,
3425 IOPMPowerStateIndex powerState
,
3426 IOPMPowerFlags domainFlags
,
3427 IOPowerConnection
* parentConnection
,
3428 IOPMPowerFlags parentFlags
)
3430 PM_ASSERT_IN_GATE();
3431 assert( fMachineState
== kIOPM_Finished
);
3432 assert( powerState
< fNumberOfPowerStates
);
3434 if (powerState
>= fNumberOfPowerStates
)
3435 return IOPMAckImplied
;
3437 fIsPreChange
= true;
3438 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3440 if (changeFlags
& kIOPMExpireIdleTimer
)
3442 // Root domain requested removal of tickle influence
3443 if (StateOrder(fDeviceDesire
) > StateOrder(powerState
))
3445 // Reset device desire down to the clamped power state
3446 updatePowerClient(gIOPMPowerClientDevice
, powerState
);
3447 computeDesiredState(kPowerStateZero
, true);
3449 // Invalidate tickle cache so the next tickle will issue a request
3450 IOLockLock(fActivityLock
);
3451 fDeviceWasActive
= false;
3452 fActivityTicklePowerState
= kInvalidTicklePowerState
;
3453 IOLockUnlock(fActivityLock
);
3455 fIdleTimerMinPowerState
= kPowerStateZero
;
3459 // Root domain's override handler may cancel the power change by
3460 // setting the kIOPMNotDone flag.
3462 if (changeFlags
& kIOPMNotDone
)
3463 return IOPMAckImplied
;
3465 // Forks to either Driver or Parent initiated power change paths.
3467 fHeadNoteChangeFlags
= changeFlags
;
3468 fHeadNotePowerState
= powerState
;
3469 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
3470 fHeadNoteParentConnection
= NULL
;
3472 if (changeFlags
& kIOPMSelfInitiated
)
3474 if (changeFlags
& kIOPMSynchronize
)
3482 assert(changeFlags
& kIOPMParentInitiated
);
3483 fHeadNoteDomainFlags
= domainFlags
;
3484 fHeadNoteParentFlags
= parentFlags
;
3485 fHeadNoteParentConnection
= parentConnection
;
3486 return ParentChangeStart();
3490 //*********************************************************************************
3491 // [private] notifyInterestedDrivers
3492 //*********************************************************************************
3494 bool IOService::notifyInterestedDrivers( void )
3496 IOPMinformee
* informee
;
3497 IOPMinformeeList
* list
= fInterestedDrivers
;
3498 DriverCallParam
* param
;
3500 IOItemCount skipCnt
= 0;
3502 PM_ASSERT_IN_GATE();
3503 assert( fDriverCallParamCount
== 0 );
3504 assert( fHeadNotePendingAcks
== 0 );
3506 fHeadNotePendingAcks
= 0;
3508 count
= list
->numberOfItems();
3510 goto done
; // no interested drivers
3512 // Allocate an array of interested drivers and their return values
3513 // for the callout thread. Everything else is still "owned" by the
3514 // PM work loop, which can run to process acknowledgePowerChange()
3517 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3518 if (count
> fDriverCallParamSlots
)
3520 if (fDriverCallParamSlots
)
3522 assert(fDriverCallParamPtr
);
3523 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3524 fDriverCallParamPtr
= 0;
3525 fDriverCallParamSlots
= 0;
3528 param
= IONew(DriverCallParam
, count
);
3530 goto done
; // no memory
3532 fDriverCallParamPtr
= (void *) param
;
3533 fDriverCallParamSlots
= count
;
3536 informee
= list
->firstInList();
3538 for (IOItemCount i
= 0; i
< count
; i
++)
3540 if (fInitialSetPowerState
|| (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)) {
3541 // Skip notifying self, if 'kIOPMInitialDeviceState' is set and
3542 // this is the initial power state change
3543 if ((this == informee
->whatObject
) &&
3544 (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)) {
3549 informee
->timer
= -1;
3550 param
[i
].Target
= informee
;
3552 informee
= list
->nextInList( informee
);
3559 fDriverCallParamCount
= count
;
3560 fHeadNotePendingAcks
= count
;
3562 // Block state machine and wait for callout completion.
3563 assert(!fDriverCallBusy
);
3564 fDriverCallBusy
= true;
3565 thread_call_enter( fDriverCallEntry
);
3569 // Return false if there are no interested drivers or could not schedule
3570 // callout thread due to error.
3574 //*********************************************************************************
3575 // [private] notifyInterestedDriversDone
3576 //*********************************************************************************
3578 void IOService::notifyInterestedDriversDone( void )
3580 IOPMinformee
* informee
;
3582 DriverCallParam
* param
;
3585 PM_ASSERT_IN_GATE();
3586 assert( fDriverCallBusy
== false );
3587 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3589 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3590 count
= fDriverCallParamCount
;
3594 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3596 informee
= (IOPMinformee
*) param
->Target
;
3597 result
= param
->Result
;
3599 if ((result
== IOPMAckImplied
) || (result
< 0))
3601 // Interested driver return IOPMAckImplied.
3602 // If informee timer is zero, it must have de-registered
3603 // interest during the thread callout. That also drops
3604 // the pending ack count.
3606 if (fHeadNotePendingAcks
&& informee
->timer
)
3607 fHeadNotePendingAcks
--;
3609 informee
->timer
= 0;
3611 else if (informee
->timer
)
3613 assert(informee
->timer
== -1);
3615 // Driver has not acked, and has returned a positive result.
3616 // Enforce a minimum permissible timeout value.
3617 // Make the min value large enough so timeout is less likely
3618 // to occur if a driver misinterpreted that the return value
3619 // should be in microsecond units. And make it large enough
3620 // to be noticeable if a driver neglects to ack.
3622 if (result
< kMinAckTimeoutTicks
)
3623 result
= kMinAckTimeoutTicks
;
3625 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3627 // else, child has already acked or driver has removed interest,
3628 // and head_note_pendingAcks decremented.
3629 // informee may have been removed from the interested drivers list,
3630 // thus the informee must be retained across the callout.
3632 informee
->release();
3635 fDriverCallParamCount
= 0;
3637 if ( fHeadNotePendingAcks
)
3639 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3644 MS_POP(); // pop the machine state passed to notifyAll()
3646 // If interest acks are outstanding, block the state machine until
3647 // fHeadNotePendingAcks drops to zero before notifying root domain.
3648 // Otherwise notify root domain directly.
3650 if (!fHeadNotePendingAcks
)
3656 MS_PUSH(fMachineState
);
3657 fMachineState
= kIOPM_NotifyChildrenStart
;
3661 //*********************************************************************************
3662 // [private] notifyRootDomain
3663 //*********************************************************************************
3665 void IOService::notifyRootDomain( void )
3667 assert( fDriverCallBusy
== false );
3669 // Only for root domain in the will-change phase
3670 if (!IS_ROOT_DOMAIN
|| (fMachineState
!= kIOPM_OurChangeSetPowerState
))
3676 MS_PUSH(fMachineState
); // push notifyAll() machine state
3677 fMachineState
= kIOPM_DriverThreadCallDone
;
3679 // Call IOPMrootDomain::willNotifyPowerChildren() on a thread call
3680 // to avoid a deadlock.
3681 fDriverCallReason
= kRootDomainInformPreChange
;
3682 fDriverCallBusy
= true;
3683 thread_call_enter( fDriverCallEntry
);
3686 void IOService::notifyRootDomainDone( void )
3688 assert( fDriverCallBusy
== false );
3689 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3691 MS_POP(); // pop notifyAll() machine state
3695 //*********************************************************************************
3696 // [private] notifyChildren
3697 //*********************************************************************************
3699 void IOService::notifyChildren( void )
3703 IOPowerConnection
* connection
;
3704 OSArray
* children
= 0;
3705 IOPMrootDomain
* rootDomain
;
3706 bool delayNotify
= false;
3708 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3709 (IS_POWER_DROP
== fIsPreChange
) &&
3710 ((rootDomain
= getPMRootDomain()) == this))
3712 rootDomain
->tracePoint( IS_POWER_DROP
?
3713 kIOPMTracePointSleepPowerPlaneDrivers
:
3714 kIOPMTracePointWakePowerPlaneDrivers
);
3717 if (fStrictTreeOrder
)
3718 children
= OSArray::withCapacity(8);
3720 // Sum child power consumption in notifyChild()
3721 fHeadNotePowerArrayEntry
->staticPower
= 0;
3723 iter
= getChildIterator(gIOPowerPlane
);
3726 while ((next
= iter
->getNextObject()))
3728 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3730 if (connection
->getReadyFlag() == false)
3732 PM_LOG3("[%s] %s: connection not ready\n",
3733 getName(), __FUNCTION__
);
3737 // Mechanism to postpone the did-change notification to
3738 // certain power children to order those children last.
3739 // Cannot be used together with strict tree ordering.
3741 if (!fIsPreChange
&&
3742 connection
->delayChildNotification
&&
3743 getPMRootDomain()->shouldDelayChildNotification(this))
3747 children
= OSArray::withCapacity(8);
3753 children
->setObject( connection
);
3758 if (!delayNotify
&& children
)
3759 children
->setObject( connection
);
3761 notifyChild( connection
);
3767 if (children
&& (children
->getCount() == 0))
3769 children
->release();
3774 assert(fNotifyChildArray
== 0);
3775 fNotifyChildArray
= children
;
3776 MS_PUSH(fMachineState
);
3780 // Block until all non-delayed children have acked their
3781 // notification. Then notify the remaining delayed child
3782 // in the array. This is used to hold off graphics child
3783 // notification while the rest of the system powers up.
3784 // If a hid tickle arrives during this time, the delayed
3785 // children are immediately notified and root domain will
3786 // not clamp power for dark wake.
3788 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3789 PM_LOG2("%s: %d children in delayed array\n",
3790 getName(), children
->getCount());
3794 // Child array created to support strict notification order.
3795 // Notify children in the array one at a time.
3797 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3802 //*********************************************************************************
3803 // [private] notifyChildrenOrdered
3804 //*********************************************************************************
3806 void IOService::notifyChildrenOrdered( void )
3808 PM_ASSERT_IN_GATE();
3809 assert(fNotifyChildArray
);
3810 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3812 // Notify one child, wait for it to ack, then repeat for next child.
3813 // This is a workaround for some drivers with multiple instances at
3814 // the same branch in the power tree, but the driver is slow to power
3815 // up unless the tree ordering is observed. Problem observed only on
3816 // system wake, not on system sleep.
3818 // We have the ability to power off in reverse child index order.
3819 // That works nicely on some machines, but not on all HW configs.
3821 if (fNotifyChildArray
->getCount())
3823 IOPowerConnection
* connection
;
3824 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3825 notifyChild( connection
);
3826 fNotifyChildArray
->removeObject(0);
3830 fNotifyChildArray
->release();
3831 fNotifyChildArray
= 0;
3833 MS_POP(); // pushed by notifyChildren()
3837 //*********************************************************************************
3838 // [private] notifyChildrenDelayed
3839 //*********************************************************************************
3841 void IOService::notifyChildrenDelayed( void )
3843 IOPowerConnection
* connection
;
3845 PM_ASSERT_IN_GATE();
3846 assert(fNotifyChildArray
);
3847 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3849 // Wait after all non-delayed children and interested drivers have ack'ed,
3850 // then notify all delayed children. If notify delay is canceled, child
3851 // acks may be outstanding with PM blocked on fHeadNotePendingAcks != 0.
3852 // But the handling for either case is identical.
3854 for (int i
= 0; ; i
++)
3856 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3860 notifyChild( connection
);
3863 PM_LOG2("%s: notified delayed children\n", getName());
3864 fNotifyChildArray
->release();
3865 fNotifyChildArray
= 0;
3867 MS_POP(); // pushed by notifyChildren()
3870 //*********************************************************************************
3871 // [private] notifyAll
3872 //*********************************************************************************
3874 IOReturn
IOService::notifyAll( uint32_t nextMS
)
3876 // Save the machine state to be restored by notifyInterestedDriversDone()
3878 PM_ASSERT_IN_GATE();
3880 fMachineState
= kIOPM_DriverThreadCallDone
;
3881 fDriverCallReason
= fIsPreChange
?
3882 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3884 if (!notifyInterestedDrivers())
3885 notifyInterestedDriversDone();
3887 return IOPMWillAckLater
;
3890 //*********************************************************************************
3891 // [private, static] pmDriverCallout
3893 // Thread call context
3894 //*********************************************************************************
3896 IOReturn
IOService::actionDriverCalloutDone(
3898 void * arg0
, void * arg1
,
3899 void * arg2
, void * arg3
)
3901 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3903 assert( fDriverCallBusy
);
3904 fDriverCallBusy
= false;
3906 assert(gIOPMWorkQueue
);
3907 gIOPMWorkQueue
->signalWorkAvailable();
3909 return kIOReturnSuccess
;
3912 void IOService::pmDriverCallout( IOService
* from
)
3915 switch (from
->fDriverCallReason
)
3917 case kDriverCallSetPowerState
:
3918 from
->driverSetPowerState();
3921 case kDriverCallInformPreChange
:
3922 case kDriverCallInformPostChange
:
3923 from
->driverInformPowerChange();
3926 case kRootDomainInformPreChange
:
3927 getPMRootDomain()->willNotifyPowerChildren(from
->fHeadNotePowerState
);
3931 panic("IOService::pmDriverCallout bad machine state %x",
3932 from
->fDriverCallReason
);
3935 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3937 /* arg0 */ (void *) from
->pwrMgt
);
3940 //*********************************************************************************
3941 // [private] driverSetPowerState
3943 // Thread call context
3944 //*********************************************************************************
3946 void IOService::driverSetPowerState( void )
3948 IOPMPowerStateIndex powerState
;
3949 DriverCallParam
* param
;
3950 IOPMDriverCallEntry callEntry
;
3953 uint32_t oldPowerState
= getPowerState();
3955 assert( fDriverCallBusy
);
3956 assert( fDriverCallParamPtr
);
3957 assert( fDriverCallParamCount
== 1 );
3959 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3960 powerState
= fHeadNotePowerState
;
3962 if (assertPMDriverCall(&callEntry
))
3964 OUR_PMLog( kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3965 start_spindump_timer("SetState");
3966 clock_get_uptime(&fDriverCallStartTime
);
3967 result
= fControllingDriver
->setPowerState( powerState
, this );
3968 clock_get_uptime(&end
);
3969 stop_spindump_timer();
3970 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3972 deassertPMDriverCall(&callEntry
);
3974 // Record the most recent max power state residency timings.
3975 // Use with DeviceActiveTimestamp to diagnose tickle issues.
3976 if (powerState
== fHighestPowerState
)
3977 fMaxPowerStateEntryTime
= end
;
3978 else if (oldPowerState
== fHighestPowerState
)
3979 fMaxPowerStateExitTime
= end
;
3983 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
3984 fName
, OBFUSCATE(this), fCurrentPowerState
, powerState
, result
);
3988 if ((result
== IOPMAckImplied
) || (result
< 0))
3992 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
3993 absolutetime_to_nanoseconds(end
, &nsec
);
3994 if (nsec
> LOG_SETPOWER_TIMES
) {
3995 getPMRootDomain()->pmStatsRecordApplicationResponse(
3996 gIOPMStatsDriverPSChangeSlow
,
3997 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
4004 result
= kIOPMAckImplied
;
4006 param
->Result
= result
;
4009 //*********************************************************************************
4010 // [private] driverInformPowerChange
4012 // Thread call context
4013 //*********************************************************************************
4015 void IOService::driverInformPowerChange( void )
4017 IOPMinformee
* informee
;
4019 DriverCallParam
* param
;
4020 IOPMDriverCallEntry callEntry
;
4021 IOPMPowerFlags powerFlags
;
4022 IOPMPowerStateIndex powerState
;
4027 assert( fDriverCallBusy
);
4028 assert( fDriverCallParamPtr
);
4029 assert( fDriverCallParamCount
);
4031 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4032 count
= fDriverCallParamCount
;
4034 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4035 powerState
= fHeadNotePowerState
;
4037 for (IOItemCount i
= 0; i
< count
; i
++)
4039 informee
= (IOPMinformee
*) param
->Target
;
4040 driver
= informee
->whatObject
;
4042 if (assertPMDriverCall(&callEntry
, 0, informee
))
4044 if (fDriverCallReason
== kDriverCallInformPreChange
)
4046 OUR_PMLog(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
4047 start_spindump_timer("WillChange");
4048 clock_get_uptime(&informee
->startTime
);
4049 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
4050 clock_get_uptime(&end
);
4051 stop_spindump_timer();
4052 OUR_PMLog((UInt32
)-kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
4056 OUR_PMLog(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
4057 start_spindump_timer("DidChange");
4058 clock_get_uptime(&informee
->startTime
);
4059 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
4060 clock_get_uptime(&end
);
4061 stop_spindump_timer();
4062 OUR_PMLog((UInt32
)-kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
4065 deassertPMDriverCall(&callEntry
);
4068 if ((result
== IOPMAckImplied
) || (result
< 0))
4072 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
4073 absolutetime_to_nanoseconds(end
, &nsec
);
4074 if (nsec
> LOG_SETPOWER_TIMES
) {
4075 getPMRootDomain()->pmStatsRecordApplicationResponse(
4076 gIOPMStatsDriverPSChangeSlow
, driver
->getName(),
4077 fDriverCallReason
, NS_TO_MS(nsec
), driver
->getRegistryEntryID(),
4084 result
= kIOPMAckImplied
;
4086 param
->Result
= result
;
4091 //*********************************************************************************
4092 // [private] notifyChild
4094 // Notify a power domain child of an upcoming power change.
4095 // If the object acknowledges the current change, we return TRUE.
4096 //*********************************************************************************
4098 bool IOService::notifyChild( IOPowerConnection
* theNub
)
4100 IOReturn ret
= IOPMAckImplied
;
4101 unsigned long childPower
;
4102 IOService
* theChild
;
4103 IOPMRequest
* childRequest
;
4104 IOPMPowerChangeFlags requestArg2
;
4107 PM_ASSERT_IN_GATE();
4108 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
4114 // Unless the child handles the notification immediately and returns
4115 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4116 fHeadNotePendingAcks
++;
4117 theNub
->setAwaitingAck(true);
4119 requestArg2
= fHeadNoteChangeFlags
;
4120 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
))
4121 requestArg2
|= kIOPMDomainPowerDrop
;
4123 requestType
= fIsPreChange
?
4124 kIOPMRequestTypePowerDomainWillChange
:
4125 kIOPMRequestTypePowerDomainDidChange
;
4127 childRequest
= acquirePMRequest( theChild
, requestType
);
4131 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4132 childRequest
->fArg1
= (void *) theNub
;
4133 childRequest
->fArg2
= (void *)(uintptr_t) requestArg2
;
4134 theChild
->submitPMRequest( childRequest
);
4135 ret
= IOPMWillAckLater
;
4139 ret
= IOPMAckImplied
;
4140 fHeadNotePendingAcks
--;
4141 theNub
->setAwaitingAck(false);
4142 childPower
= theChild
->currentPowerConsumption();
4143 if ( childPower
== kIOPMUnknown
)
4145 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4147 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
4148 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4152 theChild
->release();
4153 return (IOPMAckImplied
== ret
);
4156 //*********************************************************************************
4157 // [private] notifyControllingDriver
4158 //*********************************************************************************
4160 bool IOService::notifyControllingDriver( void )
4162 DriverCallParam
* param
;
4164 PM_ASSERT_IN_GATE();
4165 assert( fDriverCallParamCount
== 0 );
4166 assert( fControllingDriver
);
4168 if (fInitialSetPowerState
)
4170 fInitialSetPowerState
= false;
4171 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4173 // Driver specified flag to skip the inital setPowerState()
4174 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)
4180 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4183 param
= IONew(DriverCallParam
, 1);
4185 return false; // no memory
4187 fDriverCallParamPtr
= (void *) param
;
4188 fDriverCallParamSlots
= 1;
4191 param
->Target
= fControllingDriver
;
4192 fDriverCallParamCount
= 1;
4195 // Block state machine and wait for callout completion.
4196 assert(!fDriverCallBusy
);
4197 fDriverCallBusy
= true;
4198 thread_call_enter( fDriverCallEntry
);
4203 //*********************************************************************************
4204 // [private] notifyControllingDriverDone
4205 //*********************************************************************************
4207 void IOService::notifyControllingDriverDone( void )
4209 DriverCallParam
* param
;
4212 PM_ASSERT_IN_GATE();
4213 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4215 assert( fDriverCallBusy
== false );
4216 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4218 if (param
&& fDriverCallParamCount
)
4220 assert(fDriverCallParamCount
== 1);
4222 // the return value from setPowerState()
4223 result
= param
->Result
;
4225 if ((result
== IOPMAckImplied
) || (result
< 0))
4229 else if (fDriverTimer
)
4231 assert(fDriverTimer
== -1);
4233 // Driver has not acked, and has returned a positive result.
4234 // Enforce a minimum permissible timeout value.
4235 // Make the min value large enough so timeout is less likely
4236 // to occur if a driver misinterpreted that the return value
4237 // should be in microsecond units. And make it large enough
4238 // to be noticeable if a driver neglects to ack.
4240 if (result
< kMinAckTimeoutTicks
)
4241 result
= kMinAckTimeoutTicks
;
4243 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4245 // else, child has already acked and driver_timer reset to 0.
4247 fDriverCallParamCount
= 0;
4251 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4256 MS_POP(); // pushed by OurChangeSetPowerState()
4257 fIsPreChange
= false;
4260 //*********************************************************************************
4261 // [private] all_done
4263 // A power change is done.
4264 //*********************************************************************************
4266 void IOService::all_done( void )
4268 IOPMPowerStateIndex prevPowerState
;
4269 const IOPMPSEntry
* powerStatePtr
;
4270 IOPMDriverCallEntry callEntry
;
4271 uint32_t prevMachineState
= fMachineState
;
4272 bool actionCalled
= false;
4275 fMachineState
= kIOPM_Finished
;
4277 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4278 ((prevMachineState
== kIOPM_Finished
) ||
4279 (prevMachineState
== kIOPM_SyncFinish
)))
4281 // Sync operation and no power change occurred.
4282 // Do not inform driver and clients about this request completion,
4283 // except for the originator (root domain).
4285 PM_ACTION_2(actionPowerChangeDone
,
4286 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4288 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
4290 powerChangeDone(fCurrentPowerState
);
4292 else if (fAdvisoryTickleUsed
)
4294 // Not root domain and advisory tickle target.
4295 // Re-adjust power after power tree sync at the 'did' pass
4296 // to recompute desire and adjust power state between dark
4297 // and full wake transitions. Root domain is responsible
4298 // for calling setAdvisoryTickleEnable() before starting
4299 // the kIOPMSynchronize power change.
4301 if (!fAdjustPowerScheduled
&&
4302 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
))
4304 IOPMRequest
* request
;
4305 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4308 submitPMRequest( request
);
4309 fAdjustPowerScheduled
= true;
4318 if (fHeadNoteChangeFlags
& kIOPMSelfInitiated
)
4320 // power state changed
4321 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0)
4323 trackSystemSleepPreventers(
4324 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4326 // we changed, tell our parent
4327 requestDomainPower(fHeadNotePowerState
);
4329 // yes, did power raise?
4330 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4332 // yes, inform clients and apps
4333 tellChangeUp (fHeadNotePowerState
);
4335 prevPowerState
= fCurrentPowerState
;
4337 fCurrentPowerState
= fHeadNotePowerState
;
4340 ts
= mach_absolute_time();
4341 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4345 fPMVars
->myCurrentState
= fCurrentPowerState
;
4347 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4348 PM_ACTION_2(actionPowerChangeDone
,
4349 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4350 actionCalled
= true;
4352 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4353 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4354 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4355 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4357 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4359 // Bump tickle generation count once the entire tree is down
4360 gIOPMTickleGeneration
++;
4363 // inform subclass policy-maker
4364 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4365 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4367 powerChangeDone(prevPowerState
);
4368 deassertPMDriverCall(&callEntry
);
4371 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
4373 // changePowerStateWithOverrideTo() was cancelled
4374 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4378 // parent-initiated power change
4379 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
4381 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4382 ParentChangeRootChangeDown();
4384 // power state changed
4385 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0)
4387 trackSystemSleepPreventers(
4388 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4391 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4393 // yes, inform clients and apps
4394 tellChangeUp (fHeadNotePowerState
);
4397 prevPowerState
= fCurrentPowerState
;
4398 fCurrentPowerState
= fHeadNotePowerState
;
4401 ts
= mach_absolute_time();
4402 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4406 fPMVars
->myCurrentState
= fCurrentPowerState
;
4409 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4410 PM_ACTION_2(actionPowerChangeDone
,
4411 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4412 actionCalled
= true;
4414 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4415 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4416 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4417 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4419 // inform subclass policy-maker
4420 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4421 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4423 powerChangeDone(prevPowerState
);
4424 deassertPMDriverCall(&callEntry
);
4429 // When power rises enough to satisfy the tickle's desire for more power,
4430 // the condition preventing idle-timer from dropping power is removed.
4432 if (StateOrder(fCurrentPowerState
) >= StateOrder(fIdleTimerMinPowerState
))
4434 fIdleTimerMinPowerState
= kPowerStateZero
;
4439 PM_ACTION_2(actionPowerChangeDone
,
4440 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4445 // MARK: Power Change Initiated by Driver
4447 //*********************************************************************************
4448 // [private] OurChangeStart
4450 // Begin the processing of a power change initiated by us.
4451 //*********************************************************************************
4453 void IOService::OurChangeStart( void )
4455 PM_ASSERT_IN_GATE();
4456 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4458 // fMaxPowerState is our maximum possible power state based on the current
4459 // power state of our parents. If we are trying to raise power beyond the
4460 // maximum, send an async request for more power to all parents.
4462 if (!IS_PM_ROOT
&& (StateOrder(fMaxPowerState
) < StateOrder(fHeadNotePowerState
)))
4464 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4465 requestDomainPower(fHeadNotePowerState
);
4470 // Redundant power changes skips to the end of the state machine.
4472 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
4477 fInitialPowerChange
= false;
4479 // Change started, but may not complete...
4480 // Can be canceled (power drop) or deferred (power rise).
4482 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4484 // Two separate paths, depending if power is being raised or lowered.
4485 // Lowering power is subject to approval by clients of this service.
4489 fDoNotPowerDown
= false;
4491 // Ask for persmission to drop power state
4492 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4493 fOutOfBandParameter
= kNotifyApps
;
4494 askChangeDown(fHeadNotePowerState
);
4498 // This service is raising power and parents are able to support the
4499 // new power state. However a parent may have already committed to
4500 // drop power, which might force this object to temporarily drop power.
4501 // This results in "oscillations" before the state machines converge
4502 // to a steady state.
4504 // To prevent this, a child must make a power reservation against all
4505 // parents before raising power. If the reservation fails, indicating
4506 // that the child will be unable to sustain the higher power state,
4507 // then the child will signal the parent to adjust power, and the child
4508 // will defer its power change.
4512 // Reserve parent power necessary to achieve fHeadNotePowerState.
4513 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4514 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
)) == 0)
4548 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4553 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4555 if (connection
->parentKnowsState() && connection
->getReadyFlag())
4557 parent
->requestPowerDomainState(
4558 context
->requestPowerFlags
,
4566 //*********************************************************************************
4567 // [private] requestDomainPower
4569 // Called by a power child to broadcast its desired power state to all parents.
4570 // If the child self-initiates a power change, it must call this function to
4571 // allow its parents to adjust power state.
4572 //*********************************************************************************
4574 IOReturn
IOService::requestDomainPower(
4575 IOPMPowerStateIndex ourPowerState
,
4576 IOOptionBits options
)
4578 IOPMPowerFlags requestPowerFlags
;
4579 IOPMPowerStateIndex maxPowerState
;
4580 IOPMRequestDomainPowerContext context
;
4582 PM_ASSERT_IN_GATE();
4583 assert(ourPowerState
< fNumberOfPowerStates
);
4584 if (ourPowerState
>= fNumberOfPowerStates
)
4585 return kIOReturnBadArgument
;
4587 return kIOReturnSuccess
;
4589 // Fetch our input power flags for the requested power state.
4590 // Parent request is stated in terms of required power flags.
4592 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4594 // Disregard the "previous request" for power reservation.
4596 if (((options
& kReserveDomainPower
) == 0) &&
4597 (fPreviousRequestPowerFlags
== requestPowerFlags
))
4599 // skip if domain already knows our requirements
4602 fPreviousRequestPowerFlags
= requestPowerFlags
;
4604 // The results will be collected by fHeadNoteDomainTargetFlags
4605 context
.child
= this;
4606 context
.requestPowerFlags
= requestPowerFlags
;
4607 fHeadNoteDomainTargetFlags
= 0;
4608 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4610 if (options
& kReserveDomainPower
)
4612 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4613 fHeadNoteDomainTargetFlags
);
4615 if (StateOrder(maxPowerState
) < StateOrder(ourPowerState
))
4617 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4619 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4620 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4621 return kIOReturnNoPower
;
4626 return kIOReturnSuccess
;
4629 //*********************************************************************************
4630 // [private] OurSyncStart
4631 //*********************************************************************************
4633 void IOService::OurSyncStart( void )
4635 PM_ASSERT_IN_GATE();
4637 if (fInitialPowerChange
)
4640 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4642 if (fHeadNoteChangeFlags
& kIOPMNotDone
)
4648 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
)
4650 fDoNotPowerDown
= false;
4652 // Ask for permission to drop power state
4653 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4654 fOutOfBandParameter
= kNotifyApps
;
4655 askChangeDown(fHeadNotePowerState
);
4659 // Only inform capability app and clients.
4660 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4664 //*********************************************************************************
4665 // [private] OurChangeTellClientsPowerDown
4667 // All applications and kernel clients have acknowledged our permission to drop
4668 // power. Here we notify them that we will lower the power and wait for acks.
4669 //*********************************************************************************
4671 void IOService::OurChangeTellClientsPowerDown( void )
4674 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4677 fMachineState
= kIOPM_OurChangeTellUserPMPolicyPowerDown
;
4679 tellChangeDown1(fHeadNotePowerState
);
4682 //*********************************************************************************
4683 // [private] OurChangeTellUserPMPolicyPowerDown
4685 // All applications and kernel clients have acknowledged our permission to drop
4686 // power. Here we notify power management policy in user-space and wait for acks
4687 // one last time before we lower power
4688 //*********************************************************************************
4689 void 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 //*********************************************************************************
4704 void IOService::OurChangeTellPriorityClientsPowerDown( void )
4706 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4707 tellChangeDown2(fHeadNotePowerState
);
4710 //*********************************************************************************
4711 // [private] OurChangeTellCapabilityWillChange
4713 // Extra stage for root domain to notify apps and drivers about the
4714 // system capability change when raising power state.
4715 //*********************************************************************************
4717 void IOService::OurChangeTellCapabilityWillChange( void )
4719 if (!IS_ROOT_DOMAIN
)
4720 return OurChangeNotifyInterestedDriversWillChange();
4722 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4725 //*********************************************************************************
4726 // [private] OurChangeNotifyInterestedDriversWillChange
4728 // All applications and kernel clients have acknowledged our power state change.
4729 // Here we notify interested drivers pre-change.
4730 //*********************************************************************************
4732 void IOService::OurChangeNotifyInterestedDriversWillChange( void )
4734 IOPMrootDomain
* rootDomain
;
4735 if ((rootDomain
= getPMRootDomain()) == this)
4739 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4742 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4745 notifyAll( kIOPM_OurChangeSetPowerState
);
4748 //*********************************************************************************
4749 // [private] OurChangeSetPowerState
4751 // Instruct our controlling driver to program the hardware for the power state
4752 // change. Wait for async completions.
4753 //*********************************************************************************
4755 void IOService::OurChangeSetPowerState( void )
4757 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4758 fMachineState
= kIOPM_DriverThreadCallDone
;
4759 fDriverCallReason
= kDriverCallSetPowerState
;
4761 if (notifyControllingDriver() == false)
4762 notifyControllingDriverDone();
4765 //*********************************************************************************
4766 // [private] OurChangeWaitForPowerSettle
4768 // Our controlling driver has completed the power state change we initiated.
4769 // Wait for the driver specified settle time to expire.
4770 //*********************************************************************************
4772 void IOService::OurChangeWaitForPowerSettle( void )
4774 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4778 //*********************************************************************************
4779 // [private] OurChangeNotifyInterestedDriversDidChange
4781 // Power has settled on a power change we initiated. Here we notify
4782 // all our interested drivers post-change.
4783 //*********************************************************************************
4785 void IOService::OurChangeNotifyInterestedDriversDidChange( void )
4787 IOPMrootDomain
* rootDomain
;
4788 if ((rootDomain
= getPMRootDomain()) == this)
4790 rootDomain
->tracePoint( IS_POWER_DROP
?
4791 kIOPMTracePointSleepDidChangeInterests
:
4792 kIOPMTracePointWakeDidChangeInterests
);
4795 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4798 //*********************************************************************************
4799 // [private] OurChangeTellCapabilityDidChange
4801 // For root domain to notify capability power-change.
4802 //*********************************************************************************
4804 void IOService::OurChangeTellCapabilityDidChange( void )
4806 if (!IS_ROOT_DOMAIN
)
4807 return OurChangeFinish();
4809 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4810 kIOPMTracePointSleepCapabilityClients
:
4811 kIOPMTracePointWakeCapabilityClients
);
4813 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4816 //*********************************************************************************
4817 // [private] OurChangeFinish
4819 // Done with this self-induced power state change.
4820 //*********************************************************************************
4822 void IOService::OurChangeFinish( void )
4828 // MARK: Power Change Initiated by Parent
4830 //*********************************************************************************
4831 // [private] ParentChangeStart
4833 // Here we begin the processing of a power change initiated by our parent.
4834 //*********************************************************************************
4836 IOReturn
IOService::ParentChangeStart( void )
4838 PM_ASSERT_IN_GATE();
4839 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4841 // Root power domain has transitioned to its max power state
4842 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4843 (kIOPMDomainDidChange
| kIOPMRootChangeUp
))
4845 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4846 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
4852 // Power domain is forcing us to lower power
4853 if ( StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
) )
4855 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4857 // Tell apps and kernel clients
4858 fInitialPowerChange
= false;
4859 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4860 tellChangeDown1(fHeadNotePowerState
);
4861 return IOPMWillAckLater
;
4864 // Power domain is allowing us to raise power up to fHeadNotePowerState
4865 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4867 if ( StateOrder(fDesiredPowerState
) > StateOrder(fCurrentPowerState
) )
4869 if ( StateOrder(fDesiredPowerState
) < StateOrder(fHeadNotePowerState
) )
4871 // We power up, but not all the way
4872 fHeadNotePowerState
= fDesiredPowerState
;
4873 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4874 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4877 // We don't need to change
4878 fHeadNotePowerState
= fCurrentPowerState
;
4879 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4880 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4884 if ( fHeadNoteChangeFlags
& kIOPMDomainDidChange
)
4886 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4888 PM_ACTION_2(actionPowerChangeStart
,
4889 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4891 // Parent did change up - start our change up
4892 fInitialPowerChange
= false;
4893 ParentChangeTellCapabilityWillChange();
4894 return IOPMWillAckLater
;
4896 else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
)
4898 // No need to change power state, but broadcast change
4900 fMachineState
= kIOPM_SyncNotifyDidChange
;
4901 fDriverCallReason
= kDriverCallInformPreChange
;
4902 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4904 return IOPMWillAckLater
;
4908 // No power state change necessary
4909 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4912 return IOPMAckImplied
;
4915 //******************************************************************************
4916 // [private] ParentChangeRootChangeDown
4918 // Root domain has finished the transition to the system sleep state. And all
4919 // drivers in the power plane should have powered down. Cancel the idle timer,
4920 // and also reset the device desire for those drivers that don't want power
4921 // automatically restored on wake.
4922 //******************************************************************************
4924 void IOService::ParentChangeRootChangeDown( void )
4926 // Always stop the idle timer before root power down
4927 if (fIdleTimerPeriod
&& !fIdleTimerStopped
)
4929 fIdleTimerStopped
= true;
4930 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
4934 if (fResetPowerStateOnWake
)
4936 // Reset device desire down to the lowest power state.
4937 // Advisory tickle desire is intentionally untouched since
4938 // it has no effect until system is promoted to full wake.
4940 if (fDeviceDesire
!= kPowerStateZero
)
4942 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4943 computeDesiredState(kPowerStateZero
, true);
4944 requestDomainPower( fDesiredPowerState
);
4945 PM_LOG1("%s: tickle desire removed\n", fName
);
4948 // Invalidate tickle cache so the next tickle will issue a request
4949 IOLockLock(fActivityLock
);
4950 fDeviceWasActive
= false;
4951 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4952 IOLockUnlock(fActivityLock
);
4954 fIdleTimerMinPowerState
= kPowerStateZero
;
4956 else if (fAdvisoryTickleUsed
)
4958 // Less aggressive mechanism to accelerate idle timer expiration
4959 // before system sleep. May not always allow the driver to wake
4960 // up from system sleep in the min power state.
4964 bool dropTickleDesire
= false;
4966 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
4967 (fIdleTimerMinPowerState
== kPowerStateZero
) &&
4968 (fDeviceDesire
!= kPowerStateZero
))
4970 IOLockLock(fActivityLock
);
4972 if (!fDeviceWasActive
)
4974 // No tickles since the last idle timer expiration.
4975 // Safe to drop the device desire to zero.
4976 dropTickleDesire
= true;
4980 // Was tickled since the last idle timer expiration,
4981 // but not in the last minute.
4982 clock_get_uptime(&now
);
4983 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
4984 absolutetime_to_nanoseconds(now
, &nsec
);
4985 if (nsec
>= kNoTickleCancelWindow
)
4987 dropTickleDesire
= true;
4991 if (dropTickleDesire
)
4993 // Force the next tickle to raise power state
4994 fDeviceWasActive
= false;
4995 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4998 IOLockUnlock(fActivityLock
);
5001 if (dropTickleDesire
)
5003 // Advisory tickle desire is intentionally untouched since
5004 // it has no effect until system is promoted to full wake.
5006 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
5007 computeDesiredState(kPowerStateZero
, true);
5008 PM_LOG1("%s: tickle desire dropped\n", fName
);
5013 //*********************************************************************************
5014 // [private] ParentChangeTellPriorityClientsPowerDown
5016 // All applications and kernel clients have acknowledged our intention to drop
5017 // power. Here we notify "priority" clients that we are lowering power.
5018 //*********************************************************************************
5020 void IOService::ParentChangeTellPriorityClientsPowerDown( void )
5022 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
5023 tellChangeDown2(fHeadNotePowerState
);
5026 //*********************************************************************************
5027 // [private] ParentChangeTellCapabilityWillChange
5029 // All (legacy) applications and kernel clients have acknowledged, extra stage for
5030 // root domain to notify apps and drivers about the system capability change.
5031 //*********************************************************************************
5033 void IOService::ParentChangeTellCapabilityWillChange( void )
5035 if (!IS_ROOT_DOMAIN
)
5036 return ParentChangeNotifyInterestedDriversWillChange();
5038 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
5041 //*********************************************************************************
5042 // [private] ParentChangeNotifyInterestedDriversWillChange
5044 // All applications and kernel clients have acknowledged our power state change.
5045 // Here we notify interested drivers pre-change.
5046 //*********************************************************************************
5048 void IOService::ParentChangeNotifyInterestedDriversWillChange( void )
5050 notifyAll( kIOPM_ParentChangeSetPowerState
);
5053 //*********************************************************************************
5054 // [private] ParentChangeSetPowerState
5056 // Instruct our controlling driver to program the hardware for the power state
5057 // change. Wait for async completions.
5058 //*********************************************************************************
5060 void IOService::ParentChangeSetPowerState( void )
5062 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
5063 fMachineState
= kIOPM_DriverThreadCallDone
;
5064 fDriverCallReason
= kDriverCallSetPowerState
;
5066 if (notifyControllingDriver() == false)
5067 notifyControllingDriverDone();
5070 //*********************************************************************************
5071 // [private] ParentChangeWaitForPowerSettle
5073 // Our controlling driver has completed the power state change initiated by our
5074 // parent. Wait for the driver specified settle time to expire.
5075 //*********************************************************************************
5077 void IOService::ParentChangeWaitForPowerSettle( void )
5079 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
5083 //*********************************************************************************
5084 // [private] ParentChangeNotifyInterestedDriversDidChange
5086 // Power has settled on a power change initiated by our parent. Here we notify
5087 // all our interested drivers post-change.
5088 //*********************************************************************************
5090 void IOService::ParentChangeNotifyInterestedDriversDidChange( void )
5092 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
5095 //*********************************************************************************
5096 // [private] ParentChangeTellCapabilityDidChange
5098 // For root domain to notify capability power-change.
5099 //*********************************************************************************
5101 void IOService::ParentChangeTellCapabilityDidChange( void )
5103 if (!IS_ROOT_DOMAIN
)
5104 return ParentChangeAcknowledgePowerChange();
5106 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
5109 //*********************************************************************************
5110 // [private] ParentAcknowledgePowerChange
5112 // Acknowledge our power parent that our power change is done.
5113 //*********************************************************************************
5115 void IOService::ParentChangeAcknowledgePowerChange( void )
5117 IORegistryEntry
* nub
;
5120 nub
= fHeadNoteParentConnection
;
5123 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
5126 parent
->acknowledgePowerChange((IOService
*)nub
);
5133 // MARK: Ack and Settle timers
5135 //*********************************************************************************
5136 // [private] settleTimerExpired
5138 // Power has settled after our last change. Notify interested parties that
5139 // there is a new power state.
5140 //*********************************************************************************
5142 void 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
)
5161 gIOPMWorkLoop
->runAction(
5162 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5168 //*********************************************************************************
5169 // [private] startSettleTimer
5171 // Calculate a power-settling delay in microseconds and start a timer.
5172 //*********************************************************************************
5174 void 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
)
5198 while ( i
> newOrder
)
5200 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
5201 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleDownTime
;
5207 if ( newOrder
> currentOrder
)
5209 while ( i
< newOrder
)
5211 stateIndex
= fPowerStates
[i
+1].stateOrderToIndex
;
5212 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleUpTime
;
5220 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5221 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5222 if (pending
) release();
5227 //*********************************************************************************
5228 // [private] ackTimerTick
5230 // The acknowledgement timeout periodic timer has ticked.
5231 // If we are awaiting acks for a power change notification,
5232 // we decrement the timer word of each interested driver which hasn't acked.
5233 // If a timer word becomes zero, we pretend the driver aknowledged.
5234 // If we are waiting for the controlling driver to change the power
5235 // state of the hardware, we decrement its timer word, and if it becomes
5236 // zero, we pretend the driver acknowledged.
5238 // Returns true if the timer tick made it possible to advance to the next
5239 // machine state, false otherwise.
5240 //*********************************************************************************
5243 void IOService::ack_timer_ticked ( void )
5247 #endif /* !__LP64__ */
5249 bool IOService::ackTimerTick( void )
5251 IOPMinformee
* nextObject
;
5254 PM_ASSERT_IN_GATE();
5255 switch (fMachineState
) {
5256 case kIOPM_OurChangeWaitForPowerSettle
:
5257 case kIOPM_ParentChangeWaitForPowerSettle
:
5258 // are we waiting for controlling driver to acknowledge?
5259 if ( fDriverTimer
> 0 )
5261 // yes, decrement timer tick
5263 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 (gIOKitDebug
& kIOLogDebugPower
)
5274 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5275 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5279 // Unblock state machine and pretend driver has acked.
5283 // still waiting, set timer again
5289 case kIOPM_NotifyChildrenStart
:
5290 // are we waiting for interested parties to acknowledge?
5291 if ( fHeadNotePendingAcks
!= 0 )
5293 // yes, go through the list of interested drivers
5294 nextObject
= fInterestedDrivers
->firstInList();
5295 // and check each one
5296 while ( nextObject
!= NULL
)
5298 if ( nextObject
->timer
> 0 )
5300 nextObject
->timer
--;
5301 // this one should have acked by now
5302 if ( nextObject
->timer
== 0 )
5304 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5305 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5306 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5307 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5308 nextObject
->whatObject
->getName(),
5309 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5310 OBFUSCATE(nextObject
->whatObject
), fName
, fCurrentPowerState
, fHeadNotePowerState
,
5313 // Pretend driver has acked.
5314 fHeadNotePendingAcks
--;
5317 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5320 // is that the last?
5321 if ( fHeadNotePendingAcks
== 0 )
5323 // yes, we can continue
5326 // no, set timer again
5332 // TODO: aggreggate this
5333 case kIOPM_OurChangeTellClientsPowerDown
:
5334 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
5335 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5336 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5337 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5338 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5339 case kIOPM_SyncTellClientsPowerDown
:
5340 case kIOPM_SyncTellPriorityClientsPowerDown
:
5341 case kIOPM_SyncNotifyWillChange
:
5342 case kIOPM_TellCapabilityChangeDone
:
5343 // apps didn't respond in time
5344 cleanClientResponses(true);
5345 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5346 // tardy equates to approval
5351 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5352 getName(), fMachineState
);
5358 //*********************************************************************************
5359 // [private] start_watchdog_timer
5360 //*********************************************************************************
5361 void IOService::start_watchdog_timer( void )
5363 AbsoluteTime deadline
;
5365 static int timeout
= -1;
5367 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5370 if (thread_call_isactive(fWatchdogTimer
)) return;
5371 if (timeout
== -1) {
5372 PE_parse_boot_argn("swd_timeout", &timeout
, sizeof(timeout
));
5375 timeout
= WATCHDOG_TIMER_PERIOD
;
5378 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5381 pending
= thread_call_enter_delayed(fWatchdogTimer
, deadline
);
5382 if (pending
) release();
5386 //*********************************************************************************
5387 // [private] stop_watchdog_timer
5388 // Returns true if watchdog was enabled and stopped now
5389 //*********************************************************************************
5391 bool IOService::stop_watchdog_timer( void )
5395 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5398 pending
= thread_call_cancel(fWatchdogTimer
);
5399 if (pending
) release();
5404 //*********************************************************************************
5405 // reset_watchdog_timer
5406 //*********************************************************************************
5408 void IOService::reset_watchdog_timer( void )
5410 if (stop_watchdog_timer())
5411 start_watchdog_timer();
5415 //*********************************************************************************
5416 // [static] watchdog_timer_expired
5418 // Inside PM work loop's gate.
5419 //*********************************************************************************
5422 IOService::watchdog_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5424 IOService
* me
= (IOService
*) arg0
;
5427 gIOPMWatchDogThread
= current_thread();
5428 getPMRootDomain()->sleepWakeDebugTrig(true);
5429 gIOPMWatchDogThread
= 0;
5430 thread_call_free(me
->fWatchdogTimer
);
5431 me
->fWatchdogTimer
= 0;
5437 IOWorkLoop
* IOService::getIOPMWorkloop( void )
5439 return gIOPMWorkLoop
;
5444 //*********************************************************************************
5445 // [private] start_ack_timer
5446 //*********************************************************************************
5448 void IOService::start_ack_timer( void )
5450 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5453 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
5455 AbsoluteTime deadline
;
5458 clock_interval_to_deadline(interval
, scale
, &deadline
);
5461 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5462 if (pending
) release();
5464 // Stop watchdog if ack is delayed by more than a sec
5465 if (interval
* scale
> kSecondScale
) {
5466 stop_watchdog_timer();
5470 //*********************************************************************************
5471 // [private] stop_ack_timer
5472 //*********************************************************************************
5474 void IOService::stop_ack_timer( void )
5478 pending
= thread_call_cancel(fAckTimer
);
5479 if (pending
) release();
5481 start_watchdog_timer();
5484 //*********************************************************************************
5485 // [static] actionAckTimerExpired
5487 // Inside PM work loop's gate.
5488 //*********************************************************************************
5491 IOService::actionAckTimerExpired(
5493 void * arg0
, void * arg1
,
5494 void * arg2
, void * arg3
)
5496 IOService
* me
= (IOService
*) target
;
5499 // done will be true if the timer tick unblocks the machine state,
5500 // otherwise no need to signal the work loop.
5502 done
= me
->ackTimerTick();
5503 if (done
&& gIOPMWorkQueue
)
5505 gIOPMWorkQueue
->signalWorkAvailable();
5506 me
->start_watchdog_timer();
5509 return kIOReturnSuccess
;
5512 //*********************************************************************************
5513 // ack_timer_expired
5515 // Thread call function. Holds a retain while the callout is in flight.
5516 //*********************************************************************************
5519 IOService::ack_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5521 IOService
* me
= (IOService
*) arg0
;
5525 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5530 //*********************************************************************************
5531 // [private] start_spindump_timer
5532 //*********************************************************************************
5534 void IOService::start_spindump_timer( const char * delay_type
)
5536 AbsoluteTime deadline
;
5539 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
))
5542 if (gIOSpinDumpKextName
[0] == '\0' &&
5543 !(PE_parse_boot_argn("swd_kext_name", &gIOSpinDumpKextName
,
5544 sizeof(gIOSpinDumpKextName
))))
5549 if (strncmp(gIOSpinDumpKextName
, fName
, sizeof(gIOSpinDumpKextName
)) != 0)
5552 if (gIOSpinDumpDelayType
[0] == '\0' &&
5553 !(PE_parse_boot_argn("swd_delay_type", &gIOSpinDumpDelayType
,
5554 sizeof(gIOSpinDumpDelayType
))))
5556 strncpy(gIOSpinDumpDelayType
, "SetState", sizeof(gIOSpinDumpDelayType
));
5559 if (strncmp(delay_type
, gIOSpinDumpDelayType
, sizeof(gIOSpinDumpDelayType
)) != 0)
5562 if (gIOSpinDumpDelayDuration
== 0 &&
5563 !(PE_parse_boot_argn("swd_delay_duration", &gIOSpinDumpDelayDuration
,
5564 sizeof(gIOSpinDumpDelayDuration
))))
5566 gIOSpinDumpDelayDuration
= 300;
5569 clock_interval_to_deadline(gIOSpinDumpDelayDuration
, kMillisecondScale
, &deadline
);
5572 pending
= thread_call_enter_delayed(fSpinDumpTimer
, deadline
);
5573 if (pending
) release();
5576 //*********************************************************************************
5577 // [private] stop_spindump_timer
5578 //*********************************************************************************
5580 void IOService::stop_spindump_timer( void )
5584 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
))
5587 pending
= thread_call_cancel(fSpinDumpTimer
);
5588 if (pending
) release();
5592 //*********************************************************************************
5593 // [static] actionSpinDumpTimerExpired
5595 // Inside PM work loop's gate.
5596 //*********************************************************************************
5599 IOService::actionSpinDumpTimerExpired(
5601 void * arg0
, void * arg1
,
5602 void * arg2
, void * arg3
)
5604 getPMRootDomain()->takeStackshot(false, false, true);
5606 return kIOReturnSuccess
;
5609 //*********************************************************************************
5610 // spindump_timer_expired
5612 // Thread call function. Holds a retain while the callout is in flight.
5613 //*********************************************************************************
5616 IOService::spindump_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5618 IOService
* me
= (IOService
*) arg0
;
5622 gIOPMWorkLoop
->runAction(&actionSpinDumpTimerExpired
, me
);
5628 // MARK: Client Messaging
5630 //*********************************************************************************
5631 // [private] tellSystemCapabilityChange
5632 //*********************************************************************************
5634 void IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5637 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5638 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5642 // Notify app first on pre-change.
5643 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5647 // Notify kernel clients first on post-change.
5648 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5651 tellClientsWithResponse( fOutOfBandMessage
);
5654 //*********************************************************************************
5655 // [public] askChangeDown
5657 // Ask registered applications and kernel clients if we can change to a lower
5660 // Subclass can override this to send a different message type. Parameter is
5661 // the destination state number.
5663 // Return true if we don't have to wait for acknowledgements
5664 //*********************************************************************************
5666 bool IOService::askChangeDown( unsigned long stateNum
)
5668 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5671 //*********************************************************************************
5672 // [private] tellChangeDown1
5674 // Notify registered applications and kernel clients that we are definitely
5677 // Return true if we don't have to wait for acknowledgements
5678 //*********************************************************************************
5680 bool IOService::tellChangeDown1( unsigned long stateNum
)
5682 fOutOfBandParameter
= kNotifyApps
;
5683 return tellChangeDown(stateNum
);
5686 //*********************************************************************************
5687 // [private] tellChangeDown2
5689 // Notify priority clients that we are definitely dropping power.
5691 // Return true if we don't have to wait for acknowledgements
5692 //*********************************************************************************
5694 bool IOService::tellChangeDown2( unsigned long stateNum
)
5696 fOutOfBandParameter
= kNotifyPriority
;
5697 return tellChangeDown(stateNum
);
5700 //*********************************************************************************
5701 // [public] tellChangeDown
5703 // Notify registered applications and kernel clients that we are definitely
5706 // Subclass can override this to send a different message type. Parameter is
5707 // the destination state number.
5709 // Return true if we don't have to wait for acknowledgements
5710 //*********************************************************************************
5712 bool IOService::tellChangeDown( unsigned long stateNum
)
5714 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5717 //*********************************************************************************
5718 // cleanClientResponses
5720 //*********************************************************************************
5722 static void logAppTimeouts( OSObject
* object
, void * arg
)
5724 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5726 unsigned int clientIndex
;
5730 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
))
5742 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5746 pid
= clientID
->unsigned32BitValue();
5747 proc_name(pid
, name
, sizeof(name
));
5748 clientID
->release();
5751 PM_ERROR(context
->errorLog
, pid
, name
);
5753 // TODO: record message type if possible
5754 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5755 gIOPMStatsApplicationResponseTimedOut
,
5756 name
, 0, (30*1000), pid
, object
);
5762 void IOService::cleanClientResponses( bool logErrors
)
5764 if (logErrors
&& fResponseArray
)
5766 switch ( fOutOfBandParameter
) {
5768 case kNotifyCapabilityChangeApps
:
5769 if (fNotifyClientArray
)
5771 IOPMInterestContext context
;
5773 context
.responseArray
= fResponseArray
;
5774 context
.notifyClients
= fNotifyClientArray
;
5775 context
.serialNumber
= fSerialNumber
;
5776 context
.messageType
= kIOMessageCopyClientID
;
5777 context
.notifyType
= kNotifyApps
;
5778 context
.isPreChange
= fIsPreChange
;
5779 context
.enableTracing
= false;
5781 context
.maxTimeRequested
= 0;
5782 context
.stateNumber
= fHeadNotePowerState
;
5783 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5784 context
.changeFlags
= fHeadNoteChangeFlags
;
5785 context
.errorLog
= "PM notification timeout (pid %d, %s)\n";
5787 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5792 // kNotifyPriority, kNotifyCapabilityChangePriority
5793 // TODO: identify the priority client that has not acked
5794 PM_ERROR("PM priority notification timeout\n");
5795 if (gIOKitDebug
& kIOLogDebugPower
)
5797 panic("PM priority notification timeout");
5805 fResponseArray
->release();
5806 fResponseArray
= NULL
;
5808 if (fNotifyClientArray
)
5810 fNotifyClientArray
->release();
5811 fNotifyClientArray
= NULL
;
5815 //*********************************************************************************
5816 // [protected] tellClientsWithResponse
5818 // Notify registered applications and kernel clients that we are definitely
5821 // Return true if we don't have to wait for acknowledgements
5822 //*********************************************************************************
5824 bool IOService::tellClientsWithResponse( int messageType
)
5826 IOPMInterestContext context
;
5827 bool isRootDomain
= IS_ROOT_DOMAIN
;
5828 uint32_t maxTimeOut
= kMaxTimeRequested
;
5830 PM_ASSERT_IN_GATE();
5831 assert( fResponseArray
== NULL
);
5832 assert( fNotifyClientArray
== NULL
);
5834 if(messageType
== (int)kIOPMMessageLastCallBeforeSleep
)
5835 RD_LOG("tellClientsWithResponse( kIOPMMessageLastCallBeforeSleep, %d )\n",
5836 fOutOfBandParameter
);
5838 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5839 getIOMessageString(messageType
), fOutOfBandParameter
);
5841 fResponseArray
= OSArray::withCapacity( 1 );
5842 if (!fResponseArray
)
5845 fResponseArray
->setCapacityIncrement(8);
5846 if (++fSerialNumber
== 0)
5849 context
.responseArray
= fResponseArray
;
5850 context
.notifyClients
= 0;
5851 context
.serialNumber
= fSerialNumber
;
5852 context
.messageType
= messageType
;
5853 context
.notifyType
= fOutOfBandParameter
;
5854 context
.isPreChange
= fIsPreChange
;
5855 context
.enableTracing
= false;
5857 context
.maxTimeRequested
= 0;
5858 context
.stateNumber
= fHeadNotePowerState
;
5859 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5860 context
.changeFlags
= fHeadNoteChangeFlags
;
5861 context
.messageFilter
= (isRootDomain
) ?
5862 OSMemberFunctionCast(
5865 &IOPMrootDomain::systemMessageFilter
) : 0;
5867 switch ( fOutOfBandParameter
) {
5869 applyToInterested( gIOAppPowerStateInterest
,
5870 pmTellAppWithResponse
, (void *) &context
);
5873 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5874 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
) &&
5875 (context
.messageType
!= kIOPMMessageLastCallBeforeSleep
))
5877 // Notify capability app for tellChangeDown1()
5878 // but not for askChangeDown().
5879 context
.notifyType
= kNotifyCapabilityChangeApps
;
5880 context
.messageType
= kIOMessageSystemCapabilityChange
;
5881 applyToInterested( gIOAppPowerStateInterest
,
5882 pmTellCapabilityAppWithResponse
, (void *) &context
);
5883 context
.notifyType
= fOutOfBandParameter
;
5884 context
.messageType
= messageType
;
5886 if(context
.messageType
== kIOMessageCanSystemSleep
)
5888 maxTimeOut
= kCanSleepMaxTimeReq
;
5889 if(gCanSleepTimeout
)
5891 maxTimeOut
= (gCanSleepTimeout
*us_per_s
);
5894 context
.maxTimeRequested
= maxTimeOut
;
5895 applyToInterested( gIOGeneralInterest
,
5896 pmTellClientWithResponse
, (void *) &context
);
5898 fNotifyClientArray
= context
.notifyClients
;
5901 case kNotifyPriority
:
5902 context
.enableTracing
= isRootDomain
;
5903 applyToInterested( gIOPriorityPowerStateInterest
,
5904 pmTellClientWithResponse
, (void *) &context
);
5908 // Notify capability clients for tellChangeDown2().
5909 context
.notifyType
= kNotifyCapabilityChangePriority
;
5910 context
.messageType
= kIOMessageSystemCapabilityChange
;
5911 applyToInterested( gIOPriorityPowerStateInterest
,
5912 pmTellCapabilityClientWithResponse
, (void *) &context
);
5916 case kNotifyCapabilityChangeApps
:
5917 applyToInterested( gIOAppPowerStateInterest
,
5918 pmTellCapabilityAppWithResponse
, (void *) &context
);
5919 fNotifyClientArray
= context
.notifyClients
;
5920 if(context
.messageType
== kIOMessageCanSystemSleep
)
5922 maxTimeOut
= kCanSleepMaxTimeReq
;
5923 if(gCanSleepTimeout
)
5925 maxTimeOut
= (gCanSleepTimeout
*us_per_s
);
5928 context
.maxTimeRequested
= maxTimeOut
;
5931 case kNotifyCapabilityChangePriority
:
5932 context
.enableTracing
= isRootDomain
;
5933 applyToInterested( gIOPriorityPowerStateInterest
,
5934 pmTellCapabilityClientWithResponse
, (void *) &context
);
5938 // do we have to wait for somebody?
5939 if ( !checkForDone() )
5941 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5942 if (context
.enableTracing
) {
5943 getPMRootDomain()->traceDetail(context
.messageType
, 0, context
.maxTimeRequested
/ 1000);
5945 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5950 // everybody responded
5953 fResponseArray
->release();
5954 fResponseArray
= NULL
;
5956 if (fNotifyClientArray
)
5958 fNotifyClientArray
->release();
5959 fNotifyClientArray
= NULL
;
5965 //*********************************************************************************
5966 // [static private] pmTellAppWithResponse
5968 // We send a message to an application, and we expect a response, so we compute a
5969 // cookie we can identify the response with.
5970 //*********************************************************************************
5972 void IOService::pmTellAppWithResponse( OSObject
* object
, void * arg
)
5974 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5975 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5976 uint32_t msgIndex
, msgRef
, msgType
;
5977 OSNumber
*clientID
= NULL
;
5979 boolean_t proc_suspended
= FALSE
;
5980 OSObject
* waitForReply
= kOSBooleanTrue
;
5981 #if LOG_APP_RESPONSE_TIMES
5985 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5988 if (context
->us
== getPMRootDomain())
5990 if ((clientID
= copyClientIDForNotification(object
, context
)))
5992 uint32_t clientPID
= clientID
->unsigned32BitValue();
5993 clientID
->release();
5994 proc
= proc_find(clientPID
);
5998 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6003 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
6010 if (context
->messageFilter
&&
6011 !context
->messageFilter(context
->us
, object
, context
, 0, &waitForReply
))
6013 if (kIOLogDebugPower
& gIOKitDebug
)
6015 logClientIDForNotification(object
, context
, "DROP App");
6020 // Create client array (for tracking purposes) only if the service
6021 // has app clients. Usually only root domain does.
6022 if (0 == context
->notifyClients
)
6023 context
->notifyClients
= OSArray::withCapacity( 32 );
6025 msgType
= context
->messageType
;
6026 msgIndex
= context
->responseArray
->getCount();
6027 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6029 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6030 if (kIOLogDebugPower
& gIOKitDebug
)
6032 logClientIDForNotification(object
, context
, "MESG App");
6035 if (waitForReply
== kOSBooleanTrue
)
6039 clock_get_uptime(&now
);
6040 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6043 context
->responseArray
->setObject(msgIndex
, num
);
6047 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6052 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6053 if (kIOLogDebugPower
& gIOKitDebug
)
6055 logClientIDForNotification(object
, context
, "App response ignored");
6059 if (context
->notifyClients
)
6060 context
->notifyClients
->setObject(msgIndex
, object
);
6062 context
->us
->messageClient(msgType
, object
, (void *)(uintptr_t) msgRef
);
6065 //*********************************************************************************
6066 // [static private] pmTellClientWithResponse
6068 // We send a message to an in-kernel client, and we expect a response,
6069 // so we compute a cookie we can identify the response with.
6070 //*********************************************************************************
6072 void IOService::pmTellClientWithResponse( OSObject
* object
, void * arg
)
6074 IOPowerStateChangeNotification notify
;
6075 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6076 OSObject
* replied
= kOSBooleanTrue
;
6077 _IOServiceInterestNotifier
* notifier
;
6078 uint32_t msgIndex
, msgRef
, msgType
;
6081 if (context
->messageFilter
&&
6082 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6084 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6085 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6087 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6088 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6089 context
->us
->getName(),
6090 getIOMessageString(context
->messageType
),
6091 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6096 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6097 msgType
= context
->messageType
;
6098 msgIndex
= context
->responseArray
->getCount();
6099 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6101 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6102 if (gIOKitDebug
& kIOLogPower
) {
6103 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6104 if (OSDynamicCast(IOService
, object
)) {
6105 const char *who
= ((IOService
*) object
)->getName();
6106 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6108 else if (notifier
) {
6109 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6112 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6114 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6115 context
->us
->getName(),
6116 getIOMessageString(msgType
),
6117 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6120 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
6121 notify
.returnValue
= 0;
6122 notify
.stateNumber
= context
->stateNumber
;
6123 notify
.stateFlags
= context
->stateFlags
;
6125 if (context
->enableTracing
&& (notifier
!= 0))
6127 getPMRootDomain()->traceDetail(msgType
, msgIndex
, (uintptr_t) notifier
->handler
);
6130 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
6132 if (kIOReturnSuccess
== retCode
)
6134 if (0 == notify
.returnValue
) {
6135 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6137 replied
= kOSBooleanFalse
;
6138 if ( notify
.returnValue
> context
->maxTimeRequested
)
6140 if (notify
.returnValue
> kPriorityClientMaxWait
)
6142 context
->maxTimeRequested
= kPriorityClientMaxWait
;
6143 PM_ERROR("%s: client %p returned %llu for %s\n",
6144 context
->us
->getName(),
6145 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6146 (uint64_t) notify
.returnValue
,
6147 getIOMessageString(msgType
));
6150 context
->maxTimeRequested
= notify
.returnValue
;
6154 // not a client of ours
6155 // so we won't be waiting for response
6156 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6159 context
->responseArray
->setObject(msgIndex
, replied
);
6162 //*********************************************************************************
6163 // [static private] pmTellCapabilityAppWithResponse
6164 //*********************************************************************************
6166 void IOService::pmTellCapabilityAppWithResponse( OSObject
* object
, void * arg
)
6168 IOPMSystemCapabilityChangeParameters msgArg
;
6169 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6170 OSObject
* replied
= kOSBooleanTrue
;
6171 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6172 uint32_t msgIndex
, msgRef
, msgType
;
6173 #if LOG_APP_RESPONSE_TIMES
6177 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
6180 memset(&msgArg
, 0, sizeof(msgArg
));
6181 if (context
->messageFilter
&&
6182 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
))
6187 // Create client array (for tracking purposes) only if the service
6188 // has app clients. Usually only root domain does.
6189 if (0 == context
->notifyClients
)
6190 context
->notifyClients
= OSArray::withCapacity( 32 );
6192 msgType
= context
->messageType
;
6193 msgIndex
= context
->responseArray
->getCount();
6194 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6196 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6197 if (kIOLogDebugPower
& gIOKitDebug
)
6199 // Log client pid/name and client array index.
6200 OSNumber
* clientID
= NULL
;
6201 OSString
* clientIDString
= NULL
;;
6202 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6204 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6207 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
6208 context
->us
->getName(),
6209 msgIndex
, getIOMessageString(msgType
),
6210 (replied
!= kOSBooleanTrue
),
6211 clientIDString
? clientIDString
->getCStringNoCopy() : "");
6212 if (clientID
) clientID
->release();
6213 if (clientIDString
) clientIDString
->release();
6216 msgArg
.notifyRef
= msgRef
;
6217 msgArg
.maxWaitForReply
= 0;
6219 if (replied
== kOSBooleanTrue
)
6221 msgArg
.notifyRef
= 0;
6222 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6223 if (context
->notifyClients
)
6224 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
6230 clock_get_uptime(&now
);
6231 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6234 context
->responseArray
->setObject(msgIndex
, num
);
6238 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6241 if (context
->notifyClients
)
6242 context
->notifyClients
->setObject(msgIndex
, object
);
6245 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6248 //*********************************************************************************
6249 // [static private] pmTellCapabilityClientWithResponse
6250 //*********************************************************************************
6252 void IOService::pmTellCapabilityClientWithResponse(
6253 OSObject
* object
, void * arg
)
6255 IOPMSystemCapabilityChangeParameters msgArg
;
6256 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6257 OSObject
* replied
= kOSBooleanTrue
;
6258 _IOServiceInterestNotifier
* notifier
;
6259 uint32_t msgIndex
, msgRef
, msgType
;
6262 memset(&msgArg
, 0, sizeof(msgArg
));
6263 if (context
->messageFilter
&&
6264 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, 0))
6266 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6267 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6269 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6270 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6271 context
->us
->getName(),
6272 getIOMessageString(context
->messageType
),
6273 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6278 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6279 msgType
= context
->messageType
;
6280 msgIndex
= context
->responseArray
->getCount();
6281 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6283 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6284 if (gIOKitDebug
& kIOLogPower
) {
6285 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6286 if (OSDynamicCast(IOService
, object
)) {
6287 const char *who
= ((IOService
*) object
)->getName();
6288 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6290 else if (notifier
) {
6291 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6294 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6296 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6297 context
->us
->getName(),
6298 getIOMessageString(msgType
),
6299 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6302 msgArg
.notifyRef
= msgRef
;
6303 msgArg
.maxWaitForReply
= 0;
6305 if (context
->enableTracing
&& (notifier
!= 0))
6307 getPMRootDomain()->traceDetail(msgType
, msgIndex
, (uintptr_t) notifier
->handler
);
6310 retCode
= context
->us
->messageClient(
6311 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6313 if ( kIOReturnSuccess
== retCode
)
6315 if ( 0 == msgArg
.maxWaitForReply
)
6317 // client doesn't want time to respond
6318 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6322 replied
= kOSBooleanFalse
;
6323 if ( msgArg
.maxWaitForReply
> context
->maxTimeRequested
)
6325 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
)
6327 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
6328 PM_ERROR("%s: client %p returned %u for %s\n",
6329 context
->us
->getName(),
6330 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6331 msgArg
.maxWaitForReply
,
6332 getIOMessageString(msgType
));
6335 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6341 // not a client of ours
6342 // so we won't be waiting for response
6343 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6346 context
->responseArray
->setObject(msgIndex
, replied
);
6349 //*********************************************************************************
6350 // [public] tellNoChangeDown
6352 // Notify registered applications and kernel clients that we are not
6355 // Subclass can override this to send a different message type. Parameter is
6356 // the aborted destination state number.
6357 //*********************************************************************************
6359 void IOService::tellNoChangeDown( unsigned long )
6361 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6364 //*********************************************************************************
6365 // [public] tellChangeUp
6367 // Notify registered applications and kernel clients that we are raising power.
6369 // Subclass can override this to send a different message type. Parameter is
6370 // the aborted destination state number.
6371 //*********************************************************************************
6373 void IOService::tellChangeUp( unsigned long )
6375 return tellClients( kIOMessageDeviceHasPoweredOn
);
6378 //*********************************************************************************
6379 // [protected] tellClients
6381 // Notify registered applications and kernel clients of something.
6382 //*********************************************************************************
6384 void IOService::tellClients( int messageType
)
6386 IOPMInterestContext context
;
6388 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6390 memset(&context
, 0, sizeof(context
));
6391 context
.messageType
= messageType
;
6392 context
.isPreChange
= fIsPreChange
;
6394 context
.stateNumber
= fHeadNotePowerState
;
6395 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6396 context
.changeFlags
= fHeadNoteChangeFlags
;
6397 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6398 OSMemberFunctionCast(
6401 &IOPMrootDomain::systemMessageFilter
) : 0;
6403 context
.notifyType
= kNotifyPriority
;
6404 applyToInterested( gIOPriorityPowerStateInterest
,
6405 tellKernelClientApplier
, (void *) &context
);
6407 context
.notifyType
= kNotifyApps
;
6408 applyToInterested( gIOAppPowerStateInterest
,
6409 tellAppClientApplier
, (void *) &context
);
6411 applyToInterested( gIOGeneralInterest
,
6412 tellKernelClientApplier
, (void *) &context
);
6415 //*********************************************************************************
6416 // [private] tellKernelClientApplier
6418 // Message a kernel client.
6419 //*********************************************************************************
6421 static void tellKernelClientApplier( OSObject
* object
, void * arg
)
6423 IOPowerStateChangeNotification notify
;
6424 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6426 if (context
->messageFilter
&&
6427 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6429 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6430 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6432 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6433 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6434 context
->us
->getName(),
6435 IOService::getIOMessageString(context
->messageType
),
6436 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6441 notify
.powerRef
= (void *) 0;
6442 notify
.returnValue
= 0;
6443 notify
.stateNumber
= context
->stateNumber
;
6444 notify
.stateFlags
= context
->stateFlags
;
6446 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6448 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6449 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6451 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6452 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6453 context
->us
->getName(),
6454 IOService::getIOMessageString(context
->messageType
),
6455 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6459 static OSNumber
* copyClientIDForNotification(
6461 IOPMInterestContext
*context
)
6463 OSNumber
*clientID
= NULL
;
6464 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6468 static void logClientIDForNotification(
6470 IOPMInterestContext
*context
,
6471 const char *logString
)
6473 OSString
*logClientID
= NULL
;
6474 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6479 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6481 PM_LOG("%s %s %s, %s\n",
6482 context
->us
->getName(), logString
,
6483 IOService::getIOMessageString(context
->messageType
),
6484 logClientID
? logClientID
->getCStringNoCopy() : "");
6487 logClientID
->release();
6491 clientID
->release();
6496 static void tellAppClientApplier( OSObject
* object
, void * arg
)
6498 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6499 OSNumber
* clientID
= NULL
;
6501 boolean_t proc_suspended
= FALSE
;
6503 if (context
->us
== IOService::getPMRootDomain())
6505 if ((clientID
= copyClientIDForNotification(object
, context
)))
6507 uint32_t clientPID
= clientID
->unsigned32BitValue();
6508 clientID
->release();
6509 proc
= proc_find(clientPID
);
6513 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6518 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6525 if (context
->messageFilter
&&
6526 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6528 if (kIOLogDebugPower
& gIOKitDebug
)
6530 logClientIDForNotification(object
, context
, "DROP App");
6535 if (kIOLogDebugPower
& gIOKitDebug
)
6537 logClientIDForNotification(object
, context
, "MESG App");
6540 context
->us
->messageClient(context
->messageType
, object
, 0);
6543 //*********************************************************************************
6544 // [private] checkForDone
6545 //*********************************************************************************
6547 bool IOService::checkForDone( void )
6552 if (fResponseArray
== NULL
) {
6556 for (i
= 0; ; i
++) {
6557 theFlag
= fResponseArray
->getObject(i
);
6559 if (NULL
== theFlag
) {
6563 if (kOSBooleanTrue
!= theFlag
) {
6570 //*********************************************************************************
6571 // [public] responseValid
6572 //*********************************************************************************
6574 bool IOService::responseValid( uint32_t refcon
, int pid
)
6576 UInt16 serialComponent
;
6577 UInt16 ordinalComponent
;
6579 OSObject
*object
= 0;
6581 serialComponent
= (refcon
>> 16) & 0xFFFF;
6582 ordinalComponent
= (refcon
& 0xFFFF);
6584 if ( serialComponent
!= fSerialNumber
)
6589 if ( fResponseArray
== NULL
)
6594 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6601 if (fNotifyClientArray
)
6602 object
= fNotifyClientArray
->getObject(ordinalComponent
);
6605 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
6614 proc_name(pid
, name
, sizeof(name
));
6615 clock_get_uptime(&now
);
6616 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6617 SUB_ABSOLUTETIME(&now
, &start
);
6618 absolutetime_to_nanoseconds(now
, &nsec
);
6620 if (kIOLogDebugPower
& gIOKitDebug
)
6622 PM_LOG("Ack(%u) %u ms\n",
6623 (uint32_t) ordinalComponent
,
6628 if (nsec
> LOG_APP_RESPONSE_TIMES
)
6630 IOLog("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec
),
6634 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
6636 // TODO: populate the messageType argument
6637 getPMRootDomain()->pmStatsRecordApplicationResponse(
6638 gIOPMStatsApplicationResponseSlow
,
6639 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6643 getPMRootDomain()->pmStatsRecordApplicationResponse(
6644 gIOPMStatsApplicationResponsePrompt
,
6645 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6649 theFlag
= kOSBooleanFalse
;
6652 getPMRootDomain()->pmStatsRecordApplicationResponse(
6653 gIOPMStatsApplicationResponsePrompt
,
6654 0, 0, 0, pid
, object
);
6658 if ( kOSBooleanFalse
== theFlag
)
6660 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6666 //*********************************************************************************
6667 // [public] allowPowerChange
6669 // Our power state is about to lower, and we have notified applications
6670 // and kernel clients, and one of them has acknowledged. If this is the last to do
6671 // so, and all acknowledgements are positive, we continue with the power change.
6672 //*********************************************************************************
6674 IOReturn
IOService::allowPowerChange( unsigned long refcon
)
6676 IOPMRequest
* request
;
6681 return kIOReturnSuccess
;
6684 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6686 return kIOReturnNoMemory
;
6688 request
->fArg0
= (void *) refcon
;
6689 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6690 request
->fArg2
= (void *) 0;
6691 submitPMRequest( request
);
6693 return kIOReturnSuccess
;
6697 IOReturn
IOService::serializedAllowPowerChange2( unsigned long refcon
)
6699 // [deprecated] public
6700 return kIOReturnUnsupported
;
6702 #endif /* !__LP64__ */
6704 //*********************************************************************************
6705 // [public] cancelPowerChange
6707 // Our power state is about to lower, and we have notified applications
6708 // and kernel clients, and one of them has vetoed the change. If this is the last
6709 // client to respond, we abandon the power change.
6710 //*********************************************************************************
6712 IOReturn
IOService::cancelPowerChange( unsigned long refcon
)
6714 IOPMRequest
* request
;
6716 pid_t pid
= proc_selfpid();
6721 return kIOReturnSuccess
;
6725 proc_name(pid
, name
, sizeof(name
));
6726 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid
, name
);
6728 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6731 return kIOReturnNoMemory
;
6734 request
->fArg0
= (void *) refcon
;
6735 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6736 request
->fArg2
= (void *) OSString::withCString(name
);
6737 submitPMRequest( request
);
6739 return kIOReturnSuccess
;
6743 IOReturn
IOService::serializedCancelPowerChange2( unsigned long refcon
)
6745 // [deprecated] public
6746 return kIOReturnUnsupported
;
6749 //*********************************************************************************
6750 // PM_Clamp_Timer_Expired
6752 // called when clamp timer expires...set power state to 0.
6753 //*********************************************************************************
6755 void IOService::PM_Clamp_Timer_Expired( void )
6759 //*********************************************************************************
6762 // Set to highest available power state for a minimum of duration milliseconds
6763 //*********************************************************************************
6765 void IOService::clampPowerOn( unsigned long duration
)
6768 #endif /* !__LP64__ */
6770 //*********************************************************************************
6771 // configurePowerStateReport
6773 // Configures the IOStateReport for kPMPowerStateChannel
6774 //*********************************************************************************
6775 IOReturn
IOService::configurePowerStatesReport( IOReportConfigureAction action
, void *result
)
6778 IOReturn rc
= kIOReturnSuccess
;
6784 return kIOReturnUnsupported
;
6786 if (!fNumberOfPowerStates
)
6787 return kIOReturnSuccess
; // For drivers which are in power plane, but haven't called registerPowerDriver()
6792 case kIOReportEnable
:
6798 reportSize
= STATEREPORT_BUFSIZE(fNumberOfPowerStates
);
6799 fReportBuf
= IOMalloc(reportSize
);
6801 rc
= kIOReturnNoMemory
;
6804 memset(fReportBuf
, 0, reportSize
);
6806 STATEREPORT_INIT(fNumberOfPowerStates
, fReportBuf
, reportSize
,
6807 getRegistryEntryID(), kPMPowerStatesChID
, kIOReportCategoryPower
);
6809 for (i
= 0; i
< fNumberOfPowerStates
; i
++) {
6812 if (fPowerStates
[i
].capabilityFlags
& kIOPMPowerOn
)
6813 bits
|= kPMReportPowerOn
;
6814 if (fPowerStates
[i
].capabilityFlags
& kIOPMDeviceUsable
)
6815 bits
|= kPMReportDeviceUsable
;
6816 if (fPowerStates
[i
].capabilityFlags
& kIOPMLowPower
)
6817 bits
|= kPMReportLowPower
;
6819 STATEREPORT_SETSTATEID(fReportBuf
, i
, ((bits
& 0xff) << 8) |
6820 ((StateOrder(fMaxPowerState
) & 0xf) << 4) | (StateOrder(i
) & 0xf));
6822 ts
= mach_absolute_time();
6823 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
6826 case kIOReportDisable
:
6827 if (fReportClientCnt
== 0) {
6828 rc
= kIOReturnBadArgument
;
6831 if (fReportClientCnt
== 1)
6833 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
6839 case kIOReportGetDimensions
:
6841 STATEREPORT_UPDATERES(fReportBuf
, kIOReportGetDimensions
, result
);
6850 //*********************************************************************************
6851 // updatePowerStateReport
6853 // Updates the IOStateReport for kPMPowerStateChannel
6854 //*********************************************************************************
6855 IOReturn
IOService::updatePowerStatesReport( IOReportConfigureAction action
, void *result
, void *destination
)
6860 IOReturn rc
= kIOReturnSuccess
;
6861 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6865 return kIOReturnUnsupported
;
6866 if (!fNumberOfPowerStates
)
6867 return kIOReturnSuccess
;
6869 if ( !result
|| !dest
) return kIOReturnBadArgument
;
6873 case kIOReportCopyChannelData
:
6874 if ( !fReportBuf
) {
6875 rc
= kIOReturnNotOpen
;
6879 ts
= mach_absolute_time();
6880 STATEREPORT_UPDATEPREP(fReportBuf
, ts
, data2cpy
, size2cpy
);
6881 if (size2cpy
> (dest
->getCapacity() - dest
->getLength()) ) {
6882 rc
= kIOReturnOverrun
;
6886 STATEREPORT_UPDATERES(fReportBuf
, kIOReportCopyChannelData
, result
);
6887 dest
->appendBytes(data2cpy
, size2cpy
);
6901 //*********************************************************************************
6902 // configureSimplePowerReport
6904 // Configures the IOSimpleReport for given channel id
6905 //*********************************************************************************
6906 IOReturn
IOService::configureSimplePowerReport(IOReportConfigureAction action
, void *result
)
6909 IOReturn rc
= kIOReturnSuccess
;
6912 return kIOReturnUnsupported
;
6914 if ( !fNumberOfPowerStates
)
6919 case kIOReportEnable
:
6920 case kIOReportDisable
:
6923 case kIOReportGetDimensions
:
6924 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
6932 //*********************************************************************************
6933 // updateSimplePowerReport
6935 // Updates the IOSimpleReport for the given chanel id
6936 //*********************************************************************************
6937 IOReturn
IOService::updateSimplePowerReport( IOReportConfigureAction action
, void *result
, void *destination
)
6941 uint64_t buf
[SIMPLEREPORT_BUFSIZE
/sizeof(uint64_t)+1]; // Force a 8-byte alignment
6942 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6943 IOReturn rc
= kIOReturnSuccess
;
6948 return kIOReturnUnsupported
;
6949 if ( !result
|| !dest
) return kIOReturnBadArgument
;
6951 if ( !fNumberOfPowerStates
)
6956 case kIOReportCopyChannelData
:
6958 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), kPMCurrStateChID
, kIOReportCategoryPower
);
6960 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMPowerOn
)
6961 bits
|= kPMReportPowerOn
;
6962 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMDeviceUsable
)
6963 bits
|= kPMReportDeviceUsable
;
6964 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMLowPower
)
6965 bits
|= kPMReportLowPower
;
6968 SIMPLEREPORT_SETVALUE(buf
, ((bits
& 0xff) << 8) | ((StateOrder(fMaxPowerState
) & 0xf) << 4) |
6969 (StateOrder(fCurrentPowerState
) & 0xf));
6971 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
6972 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
6973 rc
= kIOReturnOverrun
;
6977 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
6978 dest
->appendBytes(data2cpy
, size2cpy
);
6988 return kIOReturnSuccess
;
6995 // MARK: Driver Overrides
6997 //*********************************************************************************
6998 // [public] setPowerState
7000 // Does nothing here. This should be implemented in a subclass driver.
7001 //*********************************************************************************
7003 IOReturn
IOService::setPowerState(
7004 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
7009 //*********************************************************************************
7010 // [public] maxCapabilityForDomainState
7012 // Finds the highest power state in the array whose input power requirement
7013 // is equal to the input parameter. Where a more intelligent decision is
7014 // possible, override this in the subclassed driver.
7015 //*********************************************************************************
7017 IOPMPowerStateIndex
IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags
)
7019 IOPMPowerStateIndex stateIndex
;
7021 if (!fNumberOfPowerStates
)
7022 return kPowerStateZero
;
7024 for ( int order
= fNumberOfPowerStates
- 1; order
>= 0; order
-- )
7026 stateIndex
= fPowerStates
[order
].stateOrderToIndex
;
7028 if ( (flags
& fPowerStates
[stateIndex
].inputPowerFlags
) ==
7029 fPowerStates
[stateIndex
].inputPowerFlags
)
7034 return kPowerStateZero
;
7037 unsigned long IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState
)
7039 return getPowerStateForDomainFlags(domainState
);
7042 //*********************************************************************************
7043 // [public] initialPowerStateForDomainState
7045 // Called to query the power state for the initial power transition.
7046 //*********************************************************************************
7048 unsigned long IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState
)
7050 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
))
7052 // Return lowest power state for any root power domain changes
7053 return kPowerStateZero
;
7056 return getPowerStateForDomainFlags(domainState
);
7059 //*********************************************************************************
7060 // [public] powerStateForDomainState
7062 // This method is not called from PM.
7063 //*********************************************************************************
7065 unsigned long IOService::powerStateForDomainState( IOPMPowerFlags domainState
)
7067 return getPowerStateForDomainFlags(domainState
);
7071 //*********************************************************************************
7072 // [deprecated] didYouWakeSystem
7074 // Does nothing here. This should be implemented in a subclass driver.
7075 //*********************************************************************************
7077 bool IOService::didYouWakeSystem( void )
7081 #endif /* !__LP64__ */
7083 //*********************************************************************************
7084 // [public] powerStateWillChangeTo
7086 // Does nothing here. This should be implemented in a subclass driver.
7087 //*********************************************************************************
7089 IOReturn
IOService::powerStateWillChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7091 return kIOPMAckImplied
;
7094 //*********************************************************************************
7095 // [public] powerStateDidChangeTo
7097 // Does nothing here. This should be implemented in a subclass driver.
7098 //*********************************************************************************
7100 IOReturn
IOService::powerStateDidChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7102 return kIOPMAckImplied
;
7105 //*********************************************************************************
7106 // [protected] powerChangeDone
7108 // Called from PM work loop thread.
7109 // Does nothing here. This should be implemented in a subclass policy-maker.
7110 //*********************************************************************************
7112 void IOService::powerChangeDone( unsigned long )
7117 //*********************************************************************************
7118 // [deprecated] newTemperature
7120 // Does nothing here. This should be implemented in a subclass driver.
7121 //*********************************************************************************
7123 IOReturn
IOService::newTemperature( long currentTemp
, IOService
* whichZone
)
7127 #endif /* !__LP64__ */
7129 //*********************************************************************************
7130 // [public] systemWillShutdown
7132 // System shutdown and restart notification.
7133 //*********************************************************************************
7135 void IOService::systemWillShutdown( IOOptionBits specifier
)
7137 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
7139 rootDomain
->acknowledgeSystemWillShutdown( this );
7143 // MARK: PM State Machine
7145 //*********************************************************************************
7146 // [private static] acquirePMRequest
7147 //*********************************************************************************
7150 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
7151 IOPMRequest
* active
)
7153 IOPMRequest
* request
;
7157 request
= IOPMRequest::create();
7160 request
->init( target
, requestType
);
7163 IOPMRequest
* root
= active
->getRootRequest();
7164 if (root
) request
->attachRootRequest(root
);
7169 PM_ERROR("%s: No memory for PM request type 0x%x\n",
7170 target
->getName(), (uint32_t) requestType
);
7175 //*********************************************************************************
7176 // [private static] releasePMRequest
7177 //*********************************************************************************
7179 void IOService::releasePMRequest( IOPMRequest
* request
)
7188 //*********************************************************************************
7189 // [private static] submitPMRequest
7190 //*********************************************************************************
7192 void IOService::submitPMRequest( IOPMRequest
* request
)
7195 assert( gIOPMReplyQueue
);
7196 assert( gIOPMRequestQueue
);
7198 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7199 (long)request
->getType(), OBFUSCATE(request
),
7200 OBFUSCATE(request
->getTarget()), request
->getTarget()->getName(),
7201 OBFUSCATE(request
->fArg0
),
7202 OBFUSCATE(request
->fArg1
), OBFUSCATE(request
->fArg2
));
7204 if (request
->isReplyType())
7205 gIOPMReplyQueue
->queuePMRequest( request
);
7207 gIOPMRequestQueue
->queuePMRequest( request
);
7210 void IOService::submitPMRequests( IOPMRequest
** requests
, IOItemCount count
)
7213 assert( count
> 0 );
7214 assert( gIOPMRequestQueue
);
7216 for (IOItemCount i
= 0; i
< count
; i
++)
7218 IOPMRequest
* req
= requests
[i
];
7219 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7220 (long)req
->getType(), OBFUSCATE(req
),
7221 OBFUSCATE(req
->getTarget()), req
->getTarget()->getName(),
7222 OBFUSCATE(req
->fArg0
),
7223 OBFUSCATE(req
->fArg1
), OBFUSCATE(req
->fArg2
));
7226 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
7229 //*********************************************************************************
7230 // [private] actionPMRequestQueue
7232 // IOPMRequestQueue::checkForWork() passing a new request to the request target.
7233 //*********************************************************************************
7235 bool IOService::actionPMRequestQueue(
7236 IOPMRequest
* request
,
7237 IOPMRequestQueue
* queue
)
7243 // Work queue will immediately execute the request if the per-service
7244 // request queue is empty. Note pwrMgt is the target's IOServicePM.
7246 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
7250 // Calling PM without PMinit() is not allowed, fail the request.
7251 // Need to signal more when completing attached requests.
7253 PM_LOG("%s: PM not initialized\n", getName());
7254 PM_LOG1("[- %02x] %p [%p %s] !initialized\n",
7255 request
->getType(), OBFUSCATE(request
),
7256 OBFUSCATE(this), getName());
7258 more
= gIOPMCompletionQueue
->queuePMRequest(request
);
7259 if (more
) gIOPMWorkQueue
->incrementProducerCount();
7265 //*********************************************************************************
7266 // [private] actionPMCompletionQueue
7268 // IOPMCompletionQueue::checkForWork() passing a completed request to the
7270 //*********************************************************************************
7272 bool IOService::actionPMCompletionQueue(
7273 IOPMRequest
* request
,
7274 IOPMCompletionQueue
* queue
)
7276 bool more
= (request
->getNextRequest() != 0);
7277 IOPMRequest
* root
= request
->getRootRequest();
7279 if (root
&& (root
!= request
))
7282 gIOPMWorkQueue
->incrementProducerCount();
7284 releasePMRequest( request
);
7288 //*********************************************************************************
7289 // [private] actionPMWorkQueueRetire
7291 // IOPMWorkQueue::checkForWork() passing a retired request to the request target.
7292 //*********************************************************************************
7294 bool IOService::actionPMWorkQueueRetire( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7296 assert(request
&& queue
);
7298 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7299 request
->getType(), OBFUSCATE(request
),
7300 OBFUSCATE(this), getName(),
7301 fMachineState
, gIOPMBusyRequestCount
);
7303 // Catch requests created by idleTimerExpired()
7304 if (request
->getType() == kIOPMRequestTypeActivityTickle
)
7306 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
7308 if ((tickleFlags
& kTickleTypePowerDrop
) && fIdleTimerPeriod
)
7312 else if (tickleFlags
== (kTickleTypeActivity
| kTickleTypePowerRise
))
7314 // Invalidate any idle power drop that got queued while
7315 // processing this request.
7316 fIdleTimerGeneration
++;
7320 // When the completed request is linked, tell work queue there is
7321 // more work pending.
7323 return (gIOPMCompletionQueue
->queuePMRequest( request
));
7326 //*********************************************************************************
7327 // [private] isPMBlocked
7329 // Check if machine state transition is blocked.
7330 //*********************************************************************************
7332 bool IOService::isPMBlocked( IOPMRequest
* request
, int count
)
7337 if (kIOPM_Finished
== fMachineState
)
7340 if (kIOPM_DriverThreadCallDone
== fMachineState
)
7342 // 5 = kDriverCallInformPreChange
7343 // 6 = kDriverCallInformPostChange
7344 // 7 = kDriverCallSetPowerState
7345 // 8 = kRootDomainInformPreChange
7346 if (fDriverCallBusy
)
7347 reason
= 5 + fDriverCallReason
;
7351 // Waiting on driver's setPowerState() timeout.
7357 // Child or interested driver acks pending.
7358 if (fHeadNotePendingAcks
)
7363 // Waiting on apps or priority power interest clients.
7369 // Waiting on settle timer expiration.
7376 fWaitReason
= reason
;
7382 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7383 request
->getType(), OBFUSCATE(request
),
7384 OBFUSCATE(this), getName(),
7385 fMachineState
, reason
);
7394 //*********************************************************************************
7395 // [private] actionPMWorkQueueInvoke
7397 // IOPMWorkQueue::checkForWork() passing a request to the
7398 // request target for execution.
7399 //*********************************************************************************
7401 bool IOService::actionPMWorkQueueInvoke( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7406 assert(request
&& queue
);
7408 while (isPMBlocked(request
, loop
++) == false)
7410 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7411 request
->getType(), OBFUSCATE(request
),
7412 OBFUSCATE(this), getName(), fMachineState
);
7414 gIOPMRequest
= request
;
7415 gIOPMWorkInvokeCount
++;
7417 // Every PM machine states must be handled in one of the cases below.
7419 switch ( fMachineState
)
7421 case kIOPM_Finished
:
7422 start_watchdog_timer();
7424 executePMRequest( request
);
7427 case kIOPM_OurChangeTellClientsPowerDown
:
7428 // Root domain might self cancel due to assertions.
7431 bool cancel
= (bool) fDoNotPowerDown
;
7432 getPMRootDomain()->askChangeDownDone(
7433 &fHeadNoteChangeFlags
, &cancel
);
7434 fDoNotPowerDown
= cancel
;
7437 // askChangeDown() done, was it vetoed?
7438 if (!fDoNotPowerDown
)
7440 // no, we can continue
7441 OurChangeTellClientsPowerDown();
7445 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7446 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7447 if (IS_ROOT_DOMAIN
) {
7448 // RootDomain already sent "WillSleep" to its clients
7449 tellChangeUp(fCurrentPowerState
);
7452 tellNoChangeDown(fHeadNotePowerState
);
7454 // mark the change note un-actioned
7455 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7461 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
7462 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7463 if (fDoNotPowerDown
)
7465 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7466 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7467 if (IS_ROOT_DOMAIN
) {
7468 // RootDomain already sent "WillSleep" to its clients
7469 tellChangeUp(fCurrentPowerState
);
7472 tellNoChangeDown(fHeadNotePowerState
);
7474 // mark the change note un-actioned
7475 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7480 OurChangeTellUserPMPolicyPowerDown();
7483 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
7484 // PMRD: LastCallBeforeSleep notify done
7485 // Non-PMRD: tellChangeDown/kNotifyApps done
7486 if (fDoNotPowerDown
)
7488 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7489 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7490 // no, tell clients we're back in the old state
7491 tellChangeUp(fCurrentPowerState
);
7492 // mark the change note un-actioned
7493 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7499 // yes, we can continue
7500 OurChangeTellPriorityClientsPowerDown();
7504 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
7505 OurChangeNotifyInterestedDriversWillChange();
7508 case kIOPM_OurChangeSetPowerState
:
7509 OurChangeSetPowerState();
7512 case kIOPM_OurChangeWaitForPowerSettle
:
7513 OurChangeWaitForPowerSettle();
7516 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
7517 OurChangeNotifyInterestedDriversDidChange();
7520 case kIOPM_OurChangeTellCapabilityDidChange
:
7521 OurChangeTellCapabilityDidChange();
7524 case kIOPM_OurChangeFinish
:
7528 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
7529 ParentChangeTellPriorityClientsPowerDown();
7532 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
7533 ParentChangeNotifyInterestedDriversWillChange();
7536 case kIOPM_ParentChangeSetPowerState
:
7537 ParentChangeSetPowerState();
7540 case kIOPM_ParentChangeWaitForPowerSettle
:
7541 ParentChangeWaitForPowerSettle();
7544 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7545 ParentChangeNotifyInterestedDriversDidChange();
7548 case kIOPM_ParentChangeTellCapabilityDidChange
:
7549 ParentChangeTellCapabilityDidChange();
7552 case kIOPM_ParentChangeAcknowledgePowerChange
:
7553 ParentChangeAcknowledgePowerChange();
7556 case kIOPM_DriverThreadCallDone
:
7557 switch (fDriverCallReason
)
7559 case kDriverCallInformPreChange
:
7560 case kDriverCallInformPostChange
:
7561 notifyInterestedDriversDone();
7563 case kDriverCallSetPowerState
:
7564 notifyControllingDriverDone();
7566 case kRootDomainInformPreChange
:
7567 notifyRootDomainDone();
7570 panic("%s: bad call reason %x",
7571 getName(), fDriverCallReason
);
7575 case kIOPM_NotifyChildrenOrdered
:
7576 notifyChildrenOrdered();
7579 case kIOPM_NotifyChildrenDelayed
:
7580 notifyChildrenDelayed();
7583 case kIOPM_NotifyChildrenStart
:
7584 // pop notifyAll() state saved by notifyInterestedDriversDone()
7589 case kIOPM_SyncTellClientsPowerDown
:
7590 // Root domain might self cancel due to assertions.
7593 bool cancel
= (bool) fDoNotPowerDown
;
7594 getPMRootDomain()->askChangeDownDone(
7595 &fHeadNoteChangeFlags
, &cancel
);
7596 fDoNotPowerDown
= cancel
;
7598 if (!fDoNotPowerDown
)
7600 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7601 fOutOfBandParameter
= kNotifyApps
;
7602 tellChangeDown(fHeadNotePowerState
);
7606 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7607 // askChangeDown/kNotifyApps
7608 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7609 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7610 tellNoChangeDown(fHeadNotePowerState
);
7611 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7616 case kIOPM_SyncTellPriorityClientsPowerDown
:
7617 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7618 if (!fDoNotPowerDown
)
7620 fMachineState
= kIOPM_SyncNotifyWillChange
;
7621 fOutOfBandParameter
= kNotifyPriority
;
7622 tellChangeDown(fHeadNotePowerState
);
7626 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7627 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7628 tellChangeUp(fCurrentPowerState
);
7629 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7634 case kIOPM_SyncNotifyWillChange
:
7635 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
)
7637 fMachineState
= kIOPM_SyncFinish
;
7640 fMachineState
= kIOPM_SyncNotifyDidChange
;
7641 fDriverCallReason
= kDriverCallInformPreChange
;
7645 case kIOPM_SyncNotifyDidChange
:
7646 fIsPreChange
= false;
7648 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7650 fMachineState
= kIOPM_SyncFinish
;
7654 assert(IS_ROOT_DOMAIN
);
7655 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7658 fDriverCallReason
= kDriverCallInformPostChange
;
7662 case kIOPM_SyncTellCapabilityDidChange
:
7663 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7666 case kIOPM_SyncFinish
:
7667 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7668 ParentChangeAcknowledgePowerChange();
7673 case kIOPM_TellCapabilityChangeDone
:
7676 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
)
7678 MS_POP(); // tellSystemCapabilityChange()
7681 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7685 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
)
7687 MS_POP(); // tellSystemCapabilityChange()
7690 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7692 tellClientsWithResponse( fOutOfBandMessage
);
7696 panic("PMWorkQueueInvoke: unknown machine state %x",
7702 if (fMachineState
== kIOPM_Finished
)
7704 stop_watchdog_timer();
7713 //*********************************************************************************
7714 // [private] executePMRequest
7715 //*********************************************************************************
7717 void IOService::executePMRequest( IOPMRequest
* request
)
7719 assert( kIOPM_Finished
== fMachineState
);
7721 switch (request
->getType())
7723 case kIOPMRequestTypePMStop
:
7724 handlePMstop( request
);
7727 case kIOPMRequestTypeAddPowerChild1
:
7728 addPowerChild1( request
);
7731 case kIOPMRequestTypeAddPowerChild2
:
7732 addPowerChild2( request
);
7735 case kIOPMRequestTypeAddPowerChild3
:
7736 addPowerChild3( request
);
7739 case kIOPMRequestTypeRegisterPowerDriver
:
7740 handleRegisterPowerDriver( request
);
7743 case kIOPMRequestTypeAdjustPowerState
:
7744 fAdjustPowerScheduled
= false;
7748 case kIOPMRequestTypePowerDomainWillChange
:
7749 handlePowerDomainWillChangeTo( request
);
7752 case kIOPMRequestTypePowerDomainDidChange
:
7753 handlePowerDomainDidChangeTo( request
);
7756 case kIOPMRequestTypeRequestPowerState
:
7757 case kIOPMRequestTypeRequestPowerStateOverride
:
7758 handleRequestPowerState( request
);
7761 case kIOPMRequestTypePowerOverrideOnPriv
:
7762 case kIOPMRequestTypePowerOverrideOffPriv
:
7763 handlePowerOverrideChanged( request
);
7766 case kIOPMRequestTypeActivityTickle
:
7767 handleActivityTickle( request
);
7770 case kIOPMRequestTypeSynchronizePowerTree
:
7771 handleSynchronizePowerTree( request
);
7774 case kIOPMRequestTypeSetIdleTimerPeriod
:
7776 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7777 fNextIdleTimerPeriod
= fIdleTimerPeriod
;
7778 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
7783 case kIOPMRequestTypeIgnoreIdleTimer
:
7784 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7787 case kIOPMRequestTypeQuiescePowerTree
:
7788 gIOPMWorkQueue
->finishQuiesceRequest(request
);
7792 panic("executePMRequest: unknown request type %x", request
->getType());
7796 //*********************************************************************************
7797 // [private] actionPMReplyQueue
7799 // IOPMRequestQueue::checkForWork() passing a reply-type request to the
7801 //*********************************************************************************
7803 bool IOService::actionPMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7807 assert( request
&& queue
);
7808 assert( request
->isReplyType() );
7810 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7811 request
->getType(), OBFUSCATE(request
),
7812 OBFUSCATE(this), getName(), fMachineState
);
7814 switch ( request
->getType() )
7816 case kIOPMRequestTypeAllowPowerChange
:
7817 case kIOPMRequestTypeCancelPowerChange
:
7818 // Check if we are expecting this response.
7819 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7820 (int)(uintptr_t) request
->fArg1
))
7822 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
7824 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7825 // flag is set. Only root domain will set this flag.
7826 // However, there is one exception to this rule. User-space PM
7827 // policy may choose to cancel sleep even after all clients have
7828 // been notified that we will lower power.
7830 if ((fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7831 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7832 || ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0))
7834 fDoNotPowerDown
= true;
7836 OSString
* name
= (OSString
*) request
->fArg2
;
7837 getPMRootDomain()->pmStatsRecordApplicationResponse(
7838 gIOPMStatsApplicationResponseCancel
,
7839 name
? name
->getCStringNoCopy() : "", 0,
7840 0, (int)(uintptr_t) request
->fArg1
, 0);
7847 cleanClientResponses(false);
7851 // OSString containing app name in Arg2 must be released.
7852 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
7854 OSObject
* obj
= (OSObject
*) request
->fArg2
;
7855 if (obj
) obj
->release();
7859 case kIOPMRequestTypeAckPowerChange
:
7860 more
= handleAcknowledgePowerChange( request
);
7863 case kIOPMRequestTypeAckSetPowerState
:
7864 if (fDriverTimer
== -1)
7866 // driver acked while setPowerState() call is in-flight.
7867 // take this ack, return value from setPowerState() is irrelevant.
7868 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
7869 (uintptr_t) this, fDriverTimer
);
7872 else if (fDriverTimer
> 0)
7874 // expected ack, stop the timer
7878 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
7879 if (nsec
> LOG_SETPOWER_TIMES
) {
7880 getPMRootDomain()->pmStatsRecordApplicationResponse(
7881 gIOPMStatsDriverPSChangeSlow
,
7882 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
7883 NULL
, fHeadNotePowerState
);
7886 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
7893 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
7897 case kIOPMRequestTypeInterestChanged
:
7898 handleInterestChanged( request
);
7902 case kIOPMRequestTypeIdleCancel
:
7903 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
7904 || (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7905 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7906 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
7907 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
7909 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7910 PM_LOG2("%s: cancel from machine state %d\n",
7911 getName(), fMachineState
);
7912 fDoNotPowerDown
= true;
7913 // Stop waiting for app replys.
7914 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
7915 (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
) ||
7916 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
) ||
7917 (fMachineState
== kIOPM_SyncTellClientsPowerDown
) )
7918 cleanClientResponses(false);
7923 case kIOPMRequestTypeChildNotifyDelayCancel
:
7924 if (fMachineState
== kIOPM_NotifyChildrenDelayed
)
7926 PM_LOG2("%s: delay notify cancelled\n", getName());
7927 notifyChildrenDelayed();
7932 panic("PMReplyQueue: unknown reply type %x", request
->getType());
7935 more
|= gIOPMCompletionQueue
->queuePMRequest(request
);
7937 gIOPMWorkQueue
->incrementProducerCount();
7942 //*********************************************************************************
7943 // [private] assertPMDriverCall / deassertPMDriverCall
7944 //*********************************************************************************
7946 bool IOService::assertPMDriverCall(
7947 IOPMDriverCallEntry
* entry
,
7948 IOOptionBits options
,
7949 IOPMinformee
* inform
)
7951 IOService
* target
= 0;
7959 if (fLockedFlags
.PMStop
)
7964 if (((options
& kIOPMADC_NoInactiveCheck
) == 0) && isInactive())
7971 if (!inform
->active
)
7975 target
= inform
->whatObject
;
7976 if (target
->isInactive())
7982 entry
->thread
= current_thread();
7983 entry
->target
= target
;
7984 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7993 void IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
7995 bool wakeup
= false;
7999 assert( !queue_empty(&fPMDriverCallQueue
) );
8000 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8001 if (fLockedFlags
.PMDriverCallWait
)
8009 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
8012 void IOService::waitForPMDriverCall( IOService
* target
)
8014 const IOPMDriverCallEntry
* entry
;
8015 thread_t thread
= current_thread();
8016 AbsoluteTime deadline
;
8023 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
8025 // Target of interested driver call
8026 if (target
&& (target
!= entry
->target
))
8029 if (entry
->thread
== thread
)
8033 PM_LOG("%s: %s(%s) on PM thread\n",
8034 fName
, __FUNCTION__
, target
? target
->getName() : "");
8035 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
8036 fName
, __FUNCTION__
, target
? target
->getName() : "");
8048 fLockedFlags
.PMDriverCallWait
= true;
8049 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
8050 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
8051 fLockedFlags
.PMDriverCallWait
= false;
8052 if (THREAD_TIMED_OUT
== waitResult
)
8054 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
8061 //*********************************************************************************
8062 // [private] Debug helpers
8063 //*********************************************************************************
8065 const char * IOService::getIOMessageString( uint32_t msg
)
8067 #define MSG_ENTRY(x) {(int) x, #x}
8069 static const IONamedValue msgNames
[] = {
8070 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
8071 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
8072 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
8073 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
8074 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
8075 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
8076 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
8077 MSG_ENTRY( kIOMessageCanSystemSleep
),
8078 MSG_ENTRY( kIOMessageSystemWillSleep
),
8079 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
8080 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
8081 MSG_ENTRY( kIOMessageSystemWillRestart
),
8082 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
8083 MSG_ENTRY( kIOMessageSystemCapabilityChange
),
8084 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep
)
8087 return IOFindNameForValue(msg
, msgNames
);
8092 // MARK: IOPMRequest
8094 //*********************************************************************************
8095 // IOPMRequest Class
8097 // Requests from PM clients, and also used for inter-object messaging within PM.
8098 //*********************************************************************************
8100 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
8102 IOPMRequest
* IOPMRequest::create( void )
8104 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
8105 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
8113 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
8115 if (!IOCommand::init())
8118 fRequestType
= type
;
8124 // Root node and root domain requests does not prevent the power tree from
8125 // becoming quiescent.
8127 fIsQuiesceBlocker
= ((fTarget
!= gIOPMRootNode
) &&
8128 (fTarget
!= IOService::getPMRootDomain()));
8133 void IOPMRequest::reset( void )
8135 assert( fWorkWaitCount
== 0 );
8136 assert( fFreeWaitCount
== 0 );
8138 detachNextRequest();
8139 detachRootRequest();
8141 if (fCompletionAction
&& (fRequestType
== kIOPMRequestTypeQuiescePowerTree
))
8143 // Call the completion on PM work loop context
8144 fCompletionAction(fCompletionTarget
, fCompletionParam
);
8145 fCompletionAction
= 0;
8148 fRequestType
= kIOPMRequestTypeInvalid
;
8157 bool IOPMRequest::attachNextRequest( IOPMRequest
* next
)
8163 // Postpone the execution of the next request after
8165 fRequestNext
= next
;
8166 fRequestNext
->fWorkWaitCount
++;
8167 #if LOG_REQUEST_ATTACH
8168 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8169 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8170 fRequestNext
->fRequestType
,
8171 (uint32_t) fRequestNext
->fWorkWaitCount
,
8172 fTarget
->getName());
8179 bool IOPMRequest::detachNextRequest( void )
8185 assert(fRequestNext
->fWorkWaitCount
);
8186 if (fRequestNext
->fWorkWaitCount
)
8187 fRequestNext
->fWorkWaitCount
--;
8188 #if LOG_REQUEST_ATTACH
8189 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8190 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8191 fRequestNext
->fRequestType
,
8192 (uint32_t) fRequestNext
->fWorkWaitCount
,
8193 fTarget
->getName());
8201 bool IOPMRequest::attachRootRequest( IOPMRequest
* root
)
8207 // Delay the completion of the root request after
8209 fRequestRoot
= root
;
8210 fRequestRoot
->fFreeWaitCount
++;
8211 #if LOG_REQUEST_ATTACH
8212 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8213 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8214 (uint32_t) fRequestRoot
->fType
,
8215 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8216 fTarget
->getName());
8223 bool IOPMRequest::detachRootRequest( void )
8229 assert(fRequestRoot
->fFreeWaitCount
);
8230 if (fRequestRoot
->fFreeWaitCount
)
8231 fRequestRoot
->fFreeWaitCount
--;
8232 #if LOG_REQUEST_ATTACH
8233 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8234 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8235 (uint32_t) fRequestRoot
->fType
,
8236 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8237 fTarget
->getName());
8246 // MARK: IOPMRequestQueue
8248 //*********************************************************************************
8249 // IOPMRequestQueue Class
8251 // Global queues. Queues are created once and never released.
8252 //*********************************************************************************
8254 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
8256 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
8258 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
8259 if (me
&& !me
->init(inOwner
, inAction
))
8267 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
8269 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8272 queue_init(&fQueue
);
8273 fLock
= IOLockAlloc();
8274 return (fLock
!= 0);
8277 void IOPMRequestQueue::free( void )
8284 return IOEventSource::free();
8287 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
8291 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8292 IOLockUnlock(fLock
);
8293 if (workLoop
) signalWorkAvailable();
8297 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
8301 assert(requests
&& count
);
8307 queue_enter(&fQueue
, next
, typeof(next
), fCommandChain
);
8309 IOLockUnlock(fLock
);
8310 if (workLoop
) signalWorkAvailable();
8313 bool IOPMRequestQueue::checkForWork( void )
8315 Action dqAction
= (Action
) action
;
8316 IOPMRequest
* request
;
8318 int dequeueCount
= 0;
8321 IOLockLock( fLock
);
8323 while (!queue_empty(&fQueue
))
8325 if (dequeueCount
++ >= kMaxDequeueCount
)
8327 // Allow other queues a chance to work
8332 queue_remove_first(&fQueue
, request
, typeof(request
), fCommandChain
);
8333 IOLockUnlock(fLock
);
8334 target
= request
->getTarget();
8336 more
|= (*dqAction
)( target
, request
, this );
8337 IOLockLock( fLock
);
8340 IOLockUnlock( fLock
);
8345 // MARK: IOPMWorkQueue
8347 //*********************************************************************************
8348 // IOPMWorkQueue Class
8350 // Queue of IOServicePM objects, each with a queue of IOPMRequest sharing the
8352 //*********************************************************************************
8354 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
8357 IOPMWorkQueue::create( IOService
* inOwner
, Action invoke
, Action retire
)
8359 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
8360 if (me
&& !me
->init(inOwner
, invoke
, retire
))
8368 bool IOPMWorkQueue::init( IOService
* inOwner
, Action invoke
, Action retire
)
8370 if (!invoke
|| !retire
||
8371 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
8374 queue_init(&fWorkQueue
);
8376 fInvokeAction
= invoke
;
8377 fRetireAction
= retire
;
8378 fConsumerCount
= fProducerCount
= 0;
8383 bool IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
8385 queue_head_t
* requestQueue
;
8391 assert( onThread() );
8392 assert( queue_next(&request
->fCommandChain
) ==
8393 queue_prev(&request
->fCommandChain
) );
8395 gIOPMBusyRequestCount
++;
8397 if (request
->isQuiesceType())
8399 if ((request
->getTarget() == gIOPMRootNode
) && !fQuiesceStartTime
)
8401 // Attach new quiesce request to all quiesce blockers in the queue
8402 fQuiesceStartTime
= mach_absolute_time();
8403 attachQuiesceRequest(request
);
8404 fQuiesceRequest
= request
;
8407 else if (fQuiesceRequest
&& request
->isQuiesceBlocker())
8409 // Attach the new quiesce blocker to the blocked quiesce request
8410 request
->attachNextRequest(fQuiesceRequest
);
8413 // Add new request to the tail of the per-service request queue.
8414 // Then immediately check the request queue to minimize latency
8415 // if the queue was empty.
8417 requestQueue
= &pwrMgt
->RequestHead
;
8418 empty
= queue_empty(requestQueue
);
8419 queue_enter(requestQueue
, request
, typeof(request
), fCommandChain
);
8422 more
= checkRequestQueue(requestQueue
, &empty
);
8425 // Request just added is blocked, add its target IOServicePM
8426 // to the work queue.
8427 assert( queue_next(&pwrMgt
->WorkChain
) ==
8428 queue_prev(&pwrMgt
->WorkChain
) );
8430 queue_enter(&fWorkQueue
, pwrMgt
, typeof(pwrMgt
), WorkChain
);
8432 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8433 fQueueLength
, pwrMgt
->Name
, OBFUSCATE(pwrMgt
));
8440 bool IOPMWorkQueue::checkRequestQueue( queue_head_t
* requestQueue
, bool * empty
)
8442 IOPMRequest
* request
;
8447 assert(!queue_empty(requestQueue
));
8449 request
= (typeof(request
)) queue_first(requestQueue
);
8450 if (request
->isWorkBlocked())
8451 break; // request dispatch blocked on attached request
8453 target
= request
->getTarget();
8456 done
= (*fInvokeAction
)( target
, request
, this );
8460 PM_LOG("PM request 0x%x dropped\n", request
->getType());
8464 break; // PM state machine blocked
8466 assert(gIOPMBusyRequestCount
> 0);
8467 if (gIOPMBusyRequestCount
)
8468 gIOPMBusyRequestCount
--;
8470 if (request
== fQuiesceRequest
)
8472 fQuiesceRequest
= 0;
8475 queue_remove_first(requestQueue
, request
, typeof(request
), fCommandChain
);
8476 more
|= (*fRetireAction
)( target
, request
, this );
8477 done
= queue_empty(requestQueue
);
8484 // Retired a request that may unblock a previously visited request
8485 // that is still waiting on the work queue. Must trigger another
8493 bool IOPMWorkQueue::checkForWork( void )
8495 IOServicePM
* entry
;
8500 #if WORK_QUEUE_STATS
8501 fStatCheckForWork
++;
8504 // Iterate over all IOServicePM entries in the work queue,
8505 // and check each entry's request queue.
8507 while (fConsumerCount
!= fProducerCount
)
8509 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8510 fProducerCount
, fConsumerCount
);
8512 fConsumerCount
= fProducerCount
;
8514 #if WORK_QUEUE_STATS
8515 if (queue_empty(&fWorkQueue
))
8521 uint32_t cachedWorkCount
= gIOPMWorkInvokeCount
;
8524 __IGNORE_WCASTALIGN(entry
= (typeof(entry
)) queue_first(&fWorkQueue
));
8525 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
))
8527 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
8529 // Get next entry, points to head if current entry is last.
8530 __IGNORE_WCASTALIGN(next
= (typeof(next
)) queue_next(&entry
->WorkChain
));
8532 // if request queue is empty, remove IOServicePM from work queue.
8535 assert(fQueueLength
);
8536 if (fQueueLength
) fQueueLength
--;
8537 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8538 fQueueLength
, entry
->Name
, OBFUSCATE(entry
));
8539 queue_remove(&fWorkQueue
, entry
, typeof(entry
), WorkChain
);
8544 #if WORK_QUEUE_STATS
8545 if (cachedWorkCount
== gIOPMWorkInvokeCount
)
8553 void IOPMWorkQueue::signalWorkAvailable( void )
8556 IOEventSource::signalWorkAvailable();
8559 void IOPMWorkQueue::incrementProducerCount( void )
8564 void IOPMWorkQueue::attachQuiesceRequest( IOPMRequest
* quiesceRequest
)
8566 IOServicePM
* entry
;
8567 IOPMRequest
* request
;
8569 if (queue_empty(&fWorkQueue
))
8574 queue_iterate(&fWorkQueue
, entry
, typeof(entry
), WorkChain
)
8576 queue_iterate(&entry
->RequestHead
, request
, typeof(request
), fCommandChain
)
8578 // Attach the quiesce request to any request in the queue that
8579 // is not linked to a next request. These requests will block
8580 // the quiesce request.
8582 if (request
->isQuiesceBlocker())
8584 request
->attachNextRequest(quiesceRequest
);
8590 void IOPMWorkQueue::finishQuiesceRequest( IOPMRequest
* quiesceRequest
)
8592 if (fQuiesceRequest
&& (quiesceRequest
== fQuiesceRequest
) &&
8593 (fQuiesceStartTime
!= 0))
8596 fQuiesceFinishTime
= mach_absolute_time();
8601 // MARK: IOPMCompletionQueue
8603 //*********************************************************************************
8604 // IOPMCompletionQueue Class
8605 //*********************************************************************************
8607 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
8609 IOPMCompletionQueue
*
8610 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
8612 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
8613 if (me
&& !me
->init(inOwner
, inAction
))
8621 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
8623 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8626 queue_init(&fQueue
);
8630 bool IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
8635 // unblock dependent request
8636 more
= request
->detachNextRequest();
8637 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8641 bool IOPMCompletionQueue::checkForWork( void )
8643 Action dqAction
= (Action
) action
;
8644 IOPMRequest
* request
;
8649 request
= (typeof(request
)) queue_first(&fQueue
);
8650 while (!queue_end(&fQueue
, (queue_entry_t
) request
))
8652 next
= (typeof(next
)) queue_next(&request
->fCommandChain
);
8653 if (!request
->isFreeBlocked())
8655 queue_remove(&fQueue
, request
, typeof(request
), fCommandChain
);
8656 target
= request
->getTarget();
8658 more
|= (*dqAction
)( target
, request
, this );
8667 // MARK: IOServicePM
8669 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8671 //*********************************************************************************
8674 // Serialize IOServicePM for debugging.
8675 //*********************************************************************************
8678 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8680 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8683 dict
->setObject(key
, num
);
8688 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
) const
8690 OSDictionary
* dict
;
8692 int powerClamp
= -1;
8695 if (IdleTimerPeriod
)
8698 if (PMActions
.parameter
& kPMActionsFlagLimitPower
)
8702 if (PMActions
.parameter
&
8703 (kPMActionsFlagIsDisplayWrangler
| kPMActionsFlagIsGraphicsDevice
))
8707 #if WORK_QUEUE_STATS
8708 if (gIOPMRootNode
== ControllingDriver
)
8713 dict
= OSDictionary::withDictionary(
8714 PowerClients
, PowerClients
->getCount() + dictSize
);
8716 dict
= OSDictionary::withCapacity(dictSize
);
8720 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8721 setPMProperty(dict
, "CapabilityFlags", CurrentCapabilityFlags
);
8722 if (NumberOfPowerStates
)
8723 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
-1);
8724 if (DesiredPowerState
!= CurrentPowerState
)
8725 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8726 if (kIOPM_Finished
!= MachineState
)
8727 setPMProperty(dict
, "MachineState", MachineState
);
8728 if (DeviceOverrideEnabled
)
8729 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8730 if (powerClamp
>= 0)
8731 setPMProperty(dict
, "PowerClamp", powerClamp
);
8733 if (IdleTimerPeriod
)
8739 clock_get_uptime(&now
);
8741 // The idle timer period in milliseconds
8742 setPMProperty(dict
, "IdleTimerPeriod", NextIdleTimerPeriod
* 1000ULL);
8744 // Number of tickles since the last idle timer expiration
8745 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8747 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
8749 // Milliseconds since the last activity tickle
8751 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8752 absolutetime_to_nanoseconds(delta
, &nsecs
);
8753 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
8756 if (!IdleTimerStopped
&& AbsoluteTime_to_scalar(&IdleTimerStartTime
))
8758 // Idle timer elapsed time in milliseconds
8760 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
8761 absolutetime_to_nanoseconds(delta
, &nsecs
);
8762 setPMProperty(dict
, "IdleTimerElapsedTime", NS_TO_MS(nsecs
));
8766 #if WORK_QUEUE_STATS
8767 if (gIOPMRootNode
== Owner
)
8769 setPMProperty(dict
, "WQ-CheckForWork",
8770 gIOPMWorkQueue
->fStatCheckForWork
);
8771 setPMProperty(dict
, "WQ-ScanEntries",
8772 gIOPMWorkQueue
->fStatScanEntries
);
8773 setPMProperty(dict
, "WQ-QueueEmpty",
8774 gIOPMWorkQueue
->fStatQueueEmpty
);
8775 setPMProperty(dict
, "WQ-NoWorkDone",
8776 gIOPMWorkQueue
->fStatNoWorkDone
);
8780 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
)
8782 // Don't report advisory tickle when it has no influence
8783 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
8786 ok
= dict
->serialize(s
);
8790 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
8793 bool IOServicePM::serialize( OSSerialize
* s
) const
8795 IOReturn ret
= kIOReturnNotReady
;
8797 if (gIOPMWatchDogThread
== current_thread())
8799 // Calling without lock as this data is collected for debug purpose, before reboot.
8800 // The workloop is probably already hung in state machine.
8801 ret
= gatedSerialize(s
);
8803 else if (gIOPMWorkLoop
)
8805 ret
= gIOPMWorkLoop
->runAction(
8806 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
8807 (OSObject
*) this, (void *) s
);
8810 return (kIOReturnSuccess
== ret
);
8813 void IOServicePM::pmPrint(
8816 uintptr_t param2
) const
8818 gPlatform
->PMLog(Name
, event
, param1
, param2
);
8821 void IOServicePM::pmTrace(
8824 uintptr_t param2
) const
8826 const char * who
= Name
;
8827 uint64_t regId
= Owner
->getRegistryEntryID();
8830 static const uint32_t sStartStopBitField
[] =
8831 { 0x00000000, 0x00000040 }; // Only Program Hardware so far
8833 // Arcane formula from Hacker's Delight by Warren
8834 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
8835 uint32_t sgnevent
= ((int) event
>> 31);
8836 uint32_t absevent
= sgnevent
^ (event
+ sgnevent
);
8837 uint32_t code
= IODBG_POWER(absevent
);
8839 uint32_t bit
= 1 << (absevent
& 0x1f);
8840 if ((absevent
< (sizeof(sStartStopBitField
) * 8)) &&
8841 (sStartStopBitField
[absevent
>> 5] & bit
))
8843 // Or in the START or END bits, Start = 1 & END = 2
8844 // If sgnevent == 0 then START - 0 => START
8845 // else if sgnevent == -1 then START - -1 => END
8846 code
|= DBG_FUNC_START
- sgnevent
;
8849 // Copy the first characters of the name into an uintptr_t
8850 for (uint32_t i
= 0; (i
< sizeof(uintptr_t) && who
[i
] != 0); i
++)
8852 ((char *) &name
)[sizeof(uintptr_t) - i
- 1] = who
[i
];
8855 IOTimeStampConstant(code
, name
, (uintptr_t) regId
, (uintptr_t)(OBFUSCATE(param1
)), (uintptr_t)(OBFUSCATE(param2
)));