2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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 )
1525 #if LOG_SETPOWER_TIMES
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
), 0, NULL
, fHeadNotePowerState
);
1537 informee
->timer
= 0;
1538 // that's one fewer to worry about
1539 fHeadNotePendingAcks
--;
1541 // this driver has already acked
1542 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1546 // make sure we're expecting this ack
1547 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1549 // that's one fewer to worry about
1550 fHeadNotePendingAcks
--;
1551 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1552 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1555 childPower
= theChild
->currentPowerConsumption();
1556 theChild
->release();
1558 if ( childPower
== kIOPMUnknown
)
1560 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1562 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
1564 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1570 if ( fHeadNotePendingAcks
== 0 ) {
1571 // yes, stop the timer
1573 // and now we can continue
1577 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1582 whichObject
->release();
1587 //*********************************************************************************
1588 // [public] acknowledgeSetPowerState
1590 // After we instructed our controlling driver to change power states,
1591 // it has called to say it has finished doing so.
1592 // We continue to process the power state change.
1593 //*********************************************************************************
1595 IOReturn
IOService::acknowledgeSetPowerState( void )
1597 IOPMRequest
* request
;
1600 return IOPMNotYetInitialized
;
1602 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1604 return kIOReturnNoMemory
;
1606 submitPMRequest( request
);
1607 return kIOReturnSuccess
;
1610 //*********************************************************************************
1611 // [private] adjustPowerState
1612 //*********************************************************************************
1614 void IOService::adjustPowerState( uint32_t clamp
)
1616 PM_ASSERT_IN_GATE();
1617 computeDesiredState(clamp
, false);
1618 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
))
1620 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1622 // Indicate that children desires must be ignored, and do not ask
1623 // apps for permission to drop power. This is used by root domain
1624 // for demand sleep.
1626 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
1627 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1630 /* flags */ changeFlags
,
1631 /* power state */ fDesiredPowerState
,
1632 /* domain flags */ 0,
1634 /* parent flags */ 0);
1638 //*********************************************************************************
1639 // [public] synchronizePowerTree
1640 //*********************************************************************************
1642 IOReturn
IOService::synchronizePowerTree(
1643 IOOptionBits options
,
1644 IOService
* notifyRoot
)
1646 IOPMRequest
* request_c
= 0;
1647 IOPMRequest
* request_s
;
1649 if (this != getPMRootDomain())
1650 return kIOReturnBadArgument
;
1652 return kIOPMNotYetInitialized
;
1654 OUR_PMLog(kPMLogCSynchronizePowerTree
, options
, (notifyRoot
!= 0));
1660 // Cancels don't need to be synchronized.
1661 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1662 if (nr
) submitPMRequest(nr
);
1663 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1664 if (nr
) submitPMRequest(nr
);
1667 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1669 goto error_no_memory
;
1671 if (options
& kIOPMSyncCancelPowerDown
)
1672 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1675 request_c
->attachNextRequest( request_s
);
1676 submitPMRequest(request_c
);
1679 request_s
->fArg0
= (void *)(uintptr_t) options
;
1680 submitPMRequest(request_s
);
1682 return kIOReturnSuccess
;
1685 if (request_c
) releasePMRequest(request_c
);
1686 if (request_s
) releasePMRequest(request_s
);
1687 return kIOReturnNoMemory
;
1690 //*********************************************************************************
1691 // [private] handleSynchronizePowerTree
1692 //*********************************************************************************
1694 void IOService::handleSynchronizePowerTree( IOPMRequest
* request
)
1696 PM_ASSERT_IN_GATE();
1697 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1698 (fCurrentPowerState
== fHighestPowerState
))
1700 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1703 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1704 (options
& kIOPMSyncNoChildNotify
),
1705 /* power state */ fCurrentPowerState
,
1706 /* domain flags */ 0,
1708 /* parent flags */ 0);
1713 //*********************************************************************************
1714 // [deprecated] powerDomainWillChangeTo
1716 // Called by the power-hierarchy parent notifying of a new power state
1717 // in the power domain.
1718 // We enqueue a parent power-change to our queue of power changes.
1719 // This may or may not cause us to change power, depending on what
1720 // kind of change is occuring in the domain.
1721 //*********************************************************************************
1723 IOReturn
IOService::powerDomainWillChangeTo(
1724 IOPMPowerFlags newPowerFlags
,
1725 IOPowerConnection
* whichParent
)
1728 return kIOReturnUnsupported
;
1730 #endif /* !__LP64__ */
1732 //*********************************************************************************
1733 // [private] handlePowerDomainWillChangeTo
1734 //*********************************************************************************
1736 void IOService::handlePowerDomainWillChangeTo( IOPMRequest
* request
)
1738 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1739 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1740 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1741 IOPMPowerChangeFlags myChangeFlags
;
1744 IOPowerConnection
* connection
;
1745 IOPMPowerStateIndex maxPowerState
;
1746 IOPMPowerFlags combinedPowerFlags
;
1747 bool savedParentsKnowState
;
1748 IOReturn result
= IOPMAckImplied
;
1750 PM_ASSERT_IN_GATE();
1751 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1753 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1755 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1759 savedParentsKnowState
= fParentsKnowState
;
1761 // Combine parents' output power flags.
1763 combinedPowerFlags
= 0;
1765 iter
= getParentIterator(gIOPowerPlane
);
1768 while ( (next
= iter
->getNextObject()) )
1770 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1772 if ( connection
== whichParent
)
1773 combinedPowerFlags
|= parentPowerFlags
;
1775 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1781 // If our initial change has yet to occur, then defer the power change
1782 // until after the power domain has completed its power transition.
1784 if ( fControllingDriver
&& !fInitialPowerChange
)
1786 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1787 combinedPowerFlags
);
1789 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1791 // fMaxPowerState set a limit on self-initiated power changes.
1792 // Update it before a parent power drop.
1793 fMaxPowerState
= maxPowerState
;
1796 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1797 // to avoid propagating the root change flags if any service must
1798 // change power state due to root's will-change notification.
1799 // Root does not change power state for kIOPMSynchronize.
1801 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1802 (parentChangeFlags
& kIOPMSynchronize
);
1804 result
= startPowerChange(
1805 /* flags */ myChangeFlags
,
1806 /* power state */ maxPowerState
,
1807 /* domain flags */ combinedPowerFlags
,
1808 /* connection */ whichParent
,
1809 /* parent flags */ parentPowerFlags
);
1812 // If parent is dropping power, immediately update the parent's
1813 // capability flags. Any future merging of parent(s) combined
1814 // power flags should account for this power drop.
1816 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1818 setParentInfo(parentPowerFlags
, whichParent
, true);
1821 // Parent is expecting an ACK from us. If we did not embark on a state
1822 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1823 // still required to issue an ACK to our parent.
1825 if (IOPMAckImplied
== result
)
1828 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1832 parent
->acknowledgePowerChange( whichParent
);
1838 // Drop the retain from notifyChild().
1839 if (whichParent
) whichParent
->release();
1843 //*********************************************************************************
1844 // [deprecated] powerDomainDidChangeTo
1846 // Called by the power-hierarchy parent after the power state of the power domain
1847 // has settled at a new level.
1848 // We enqueue a parent power-change to our queue of power changes.
1849 // This may or may not cause us to change power, depending on what
1850 // kind of change is occuring in the domain.
1851 //*********************************************************************************
1853 IOReturn
IOService::powerDomainDidChangeTo(
1854 IOPMPowerFlags newPowerFlags
,
1855 IOPowerConnection
* whichParent
)
1858 return kIOReturnUnsupported
;
1860 #endif /* !__LP64__ */
1862 //*********************************************************************************
1863 // [private] handlePowerDomainDidChangeTo
1864 //*********************************************************************************
1866 void IOService::handlePowerDomainDidChangeTo( IOPMRequest
* request
)
1868 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1869 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1870 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1871 IOPMPowerChangeFlags myChangeFlags
;
1872 IOPMPowerStateIndex maxPowerState
;
1873 IOPMPowerStateIndex initialDesire
= kPowerStateZero
;
1874 bool computeDesire
= false;
1875 bool desireChanged
= false;
1876 bool savedParentsKnowState
;
1877 IOReturn result
= IOPMAckImplied
;
1879 PM_ASSERT_IN_GATE();
1880 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1882 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1884 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1888 savedParentsKnowState
= fParentsKnowState
;
1890 setParentInfo(parentPowerFlags
, whichParent
, true);
1892 if ( fControllingDriver
)
1894 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1895 fParentsCurrentPowerFlags
);
1897 if ((parentChangeFlags
& kIOPMDomainPowerDrop
) == 0)
1899 // fMaxPowerState set a limit on self-initiated power changes.
1900 // Update it after a parent power rise.
1901 fMaxPowerState
= maxPowerState
;
1904 if (fInitialPowerChange
)
1906 computeDesire
= true;
1907 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1908 fParentsCurrentPowerFlags
);
1910 else if (parentChangeFlags
& kIOPMRootChangeUp
)
1912 if (fAdvisoryTickleUsed
)
1914 // On system wake, re-compute the desired power state since
1915 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1916 // which is an input to computeDesiredState(). This is not
1917 // necessary for a dark wake because powerChangeDone() will
1918 // handle the dark to full wake case, but it does no harm.
1920 desireChanged
= true;
1923 if (fResetPowerStateOnWake
)
1925 // Query the driver for the desired power state on system wake.
1926 // Default implementation returns the lowest power state.
1928 IOPMPowerStateIndex wakePowerState
=
1929 fControllingDriver
->initialPowerStateForDomainState(
1930 kIOPMRootDomainState
| kIOPMPowerOn
);
1932 // fDesiredPowerState was adjusted before going to sleep
1933 // with fDeviceDesire at min.
1935 if (StateOrder(wakePowerState
) > StateOrder(fDesiredPowerState
))
1937 // Must schedule a power adjustment if we changed the
1938 // device desire. That will update the desired domain
1939 // power on the parent power connection and ping the
1940 // power parent if necessary.
1942 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1943 desireChanged
= true;
1948 if (computeDesire
|| desireChanged
)
1949 computeDesiredState(initialDesire
, false);
1951 // Absorb and propagate parent's broadcast flags
1952 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1953 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1955 result
= startPowerChange(
1956 /* flags */ myChangeFlags
,
1957 /* power state */ maxPowerState
,
1958 /* domain flags */ fParentsCurrentPowerFlags
,
1959 /* connection */ whichParent
,
1960 /* parent flags */ 0);
1963 // Parent is expecting an ACK from us. If we did not embark on a state
1964 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1965 // still required to issue an ACK to our parent.
1967 if (IOPMAckImplied
== result
)
1970 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1974 parent
->acknowledgePowerChange( whichParent
);
1979 // If the parent registers its power driver late, then this is the
1980 // first opportunity to tell our parent about our desire. Or if the
1981 // child's desire changed during a parent change notify.
1983 if (fControllingDriver
&&
1984 ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
))
1986 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
1987 getName(), fParentsKnowState
);
1988 requestDomainPower( fDesiredPowerState
);
1992 // Drop the retain from notifyChild().
1993 if (whichParent
) whichParent
->release();
1996 //*********************************************************************************
1997 // [private] setParentInfo
1999 // Set our connection data for one specific parent, and then combine all the parent
2001 //*********************************************************************************
2003 void IOService::setParentInfo(
2004 IOPMPowerFlags newPowerFlags
,
2005 IOPowerConnection
* whichParent
,
2010 IOPowerConnection
* conn
;
2012 PM_ASSERT_IN_GATE();
2014 // set our connection data
2015 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
2016 whichParent
->setParentKnowsState(knowsState
);
2018 // recompute our parent info
2019 fParentsCurrentPowerFlags
= 0;
2020 fParentsKnowState
= true;
2022 iter
= getParentIterator(gIOPowerPlane
);
2025 while ( (next
= iter
->getNextObject()) )
2027 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
2029 fParentsKnowState
&= conn
->parentKnowsState();
2030 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
2037 //******************************************************************************
2038 // [private] trackSystemSleepPreventers
2039 //******************************************************************************
2041 void IOService::trackSystemSleepPreventers(
2042 IOPMPowerStateIndex oldPowerState
,
2043 IOPMPowerStateIndex newPowerState
,
2044 IOPMPowerChangeFlags changeFlags __unused
)
2046 IOPMPowerFlags oldCapability
, newCapability
;
2048 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2049 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2050 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2051 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2053 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)
2055 if (oldCapability
== newCapability
)
2058 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
)
2060 bool enablePrevention
= ((oldCapability
& kIOPMPreventIdleSleep
) == 0);
2061 bool idleCancelAllowed
= getPMRootDomain()->updatePreventIdleSleepList(
2062 this, enablePrevention
);
2063 #if SUPPORT_IDLE_CANCEL
2064 if (idleCancelAllowed
&& enablePrevention
)
2066 IOPMRequest
* cancelRequest
;
2068 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2071 submitPMRequest( cancelRequest
);
2077 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
)
2079 getPMRootDomain()->updatePreventSystemSleepList(this,
2080 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2084 //*********************************************************************************
2085 // [public] requestPowerDomainState
2087 // Called on a power parent when a child's power requirement changes.
2088 //*********************************************************************************
2090 IOReturn
IOService::requestPowerDomainState(
2091 IOPMPowerFlags childRequestPowerFlags
,
2092 IOPowerConnection
* childConnection
,
2093 unsigned long specification
)
2095 IOPMPowerStateIndex order
, powerState
;
2096 IOPMPowerFlags outputPowerFlags
;
2098 IOPMRequest
* subRequest
;
2099 bool adjustPower
= false;
2102 return IOPMNotYetInitialized
;
2104 if (gIOPMWorkLoop
->onThread() == false)
2106 PM_LOG("%s::requestPowerDomainState\n", getName());
2107 return kIOReturnSuccess
;
2110 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2112 if (!isChild(childConnection
, gIOPowerPlane
))
2113 return kIOReturnNotAttached
;
2115 if (!fControllingDriver
|| !fNumberOfPowerStates
)
2116 return kIOReturnNotReady
;
2118 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2121 // Remove flags from child request which we can't possibly supply
2122 childRequestPowerFlags
&= fMergedOutputPowerFlags
;
2124 // Merge in the power flags contributed by this power parent
2125 // at its current or impending power state.
2127 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2128 if (fMachineState
!= kIOPM_Finished
)
2130 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
)
2132 // Use the lower power state when dropping power.
2133 // Must be careful since a power drop can be cancelled
2134 // from the following states:
2135 // - kIOPM_OurChangeTellClientsPowerDown
2136 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2138 // The child must not wait for this parent to raise power
2139 // if the power drop was cancelled. The solution is to cancel
2140 // the power drop if possible, then schedule an adjustment to
2141 // re-evaluate the parent's power state.
2143 // Root domain is excluded to avoid idle sleep issues. And allow
2144 // root domain children to pop up when system is going to sleep.
2146 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2147 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
2149 fDoNotPowerDown
= true; // cancel power drop
2150 adjustPower
= true; // schedule an adjustment
2151 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2152 getName(), fMachineState
, child
->getName());
2156 // Beyond cancellation point, report the impending state.
2158 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2161 else if (IS_POWER_RISE
)
2163 // When raising power, must report the output power flags from
2164 // child's perspective. A child power request may arrive while
2165 // parent is transitioning upwards. If a request arrives after
2166 // setParentInfo() has already recorded the output power flags
2167 // for the next power state, then using the power supplied by
2168 // fCurrentPowerState is incorrect, and might cause the child
2169 // to wait when it should not.
2171 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2174 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2176 // Map child's requested power flags to one of our power state.
2178 for (order
= 0; order
< fNumberOfPowerStates
; order
++)
2180 powerState
= fPowerStates
[order
].stateOrderToIndex
;
2181 if ((fPowerStates
[powerState
].outputPowerFlags
& childRequestPowerFlags
)
2182 == childRequestPowerFlags
)
2185 if (order
>= fNumberOfPowerStates
)
2187 powerState
= kPowerStateZero
;
2190 // Conditions that warrants a power adjustment on this parent.
2191 // Adjust power will also propagate any changes to the child's
2192 // prevent idle/sleep flags towards the root domain.
2194 if (!childConnection
->childHasRequestedPower() ||
2195 (powerState
!= childConnection
->getDesiredDomainState()))
2198 #if ENABLE_DEBUG_LOGS
2201 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2202 getName(), child
->getName(),
2203 !childConnection
->childHasRequestedPower(),
2204 (uint32_t) childConnection
->getDesiredDomainState(),
2205 (uint32_t) powerState
);
2209 // Record the child's desires on the connection.
2210 childConnection
->setChildHasRequestedPower();
2211 childConnection
->setDesiredDomainState( powerState
);
2213 // Schedule a request to re-evaluate all children desires and
2214 // adjust power state. Submit a request if one wasn't pending,
2215 // or if the current request is part of a call tree.
2217 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2218 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest()))
2220 subRequest
= acquirePMRequest(
2221 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2224 submitPMRequest( subRequest
);
2225 fAdjustPowerScheduled
= true;
2229 return kIOReturnSuccess
;
2232 //*********************************************************************************
2233 // [public] temporaryPowerClampOn
2235 // A power domain wants to clamp its power on till it has children which
2236 // will thendetermine the power domain state.
2238 // We enter the highest state until addPowerChild is called.
2239 //*********************************************************************************
2241 IOReturn
IOService::temporaryPowerClampOn( void )
2243 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2246 //*********************************************************************************
2247 // [public] makeUsable
2249 // Some client of our device is asking that we become usable. Although
2250 // this has not come from a subclassed device object, treat it exactly
2251 // as if it had. In this way, subsequent requests for lower power from
2252 // a subclassed device object will pre-empt this request.
2254 // We treat this as a subclass object request to switch to the
2255 // highest power state.
2256 //*********************************************************************************
2258 IOReturn
IOService::makeUsable( void )
2260 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2261 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2264 //*********************************************************************************
2265 // [public] currentCapability
2266 //*********************************************************************************
2268 IOPMPowerFlags
IOService::currentCapability( void )
2271 return IOPMNotPowerManaged
;
2273 return fCurrentCapabilityFlags
;
2276 //*********************************************************************************
2277 // [public] changePowerStateTo
2279 // Called by our power-controlling driver to change power state. The new desired
2280 // power state is computed and compared against the current power state. If those
2281 // power states differ, then a power state change is initiated.
2282 //*********************************************************************************
2284 IOReturn
IOService::changePowerStateTo( unsigned long ordinal
)
2286 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2287 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2290 //*********************************************************************************
2291 // [protected] changePowerStateToPriv
2293 // Called by our driver subclass to change power state. The new desired power
2294 // state is computed and compared against the current power state. If those
2295 // power states differ, then a power state change is initiated.
2296 //*********************************************************************************
2298 IOReturn
IOService::changePowerStateToPriv( unsigned long ordinal
)
2300 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2301 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2304 //*********************************************************************************
2305 // [public] changePowerStateWithOverrideTo
2307 // Called by our driver subclass to change power state. The new desired power
2308 // state is computed and compared against the current power state. If those
2309 // power states differ, then a power state change is initiated.
2310 // Override enforced - Children and Driver desires are ignored.
2311 //*********************************************************************************
2313 IOReturn
IOService::changePowerStateWithOverrideTo( IOPMPowerStateIndex ordinal
,
2314 IOPMRequestTag tag
)
2316 IOPMRequest
* request
;
2319 return kIOPMNotYetInitialized
;
2321 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2323 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2325 return kIOReturnNoMemory
;
2327 gIOPMPowerClientDevice
->retain();
2328 request
->fRequestTag
= tag
;
2329 request
->fArg0
= (void *) ordinal
;
2330 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2334 request
->installCompletionAction( action
, target
, param
);
2337 // Prevent needless downwards power transitions by clamping power
2338 // until the scheduled request is executed.
2340 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
))
2342 fTempClampPowerState
= StateMax(fTempClampPowerState
, ordinal
);
2344 fOverrideMaxPowerState
= ordinal
;
2345 request
->fArg2
= (void *) (uintptr_t) true;
2348 submitPMRequest( request
);
2352 //*********************************************************************************
2353 // [public] changePowerStateForRootDomain
2355 // Adjust the root domain's power desire on the target
2356 //*********************************************************************************
2358 IOReturn
IOService::changePowerStateForRootDomain( IOPMPowerStateIndex ordinal
)
2360 OUR_PMLog(kPMLogChangeStateForRootDomain
, ordinal
, 0);
2361 return requestPowerState( gIOPMPowerClientRootDomain
, ordinal
);
2364 //*********************************************************************************
2365 // [public for PMRD] quiescePowerTree
2367 // For root domain to issue a request to quiesce the power tree.
2368 // Supplied callback invoked upon completion.
2369 //*********************************************************************************
2371 IOReturn
IOService::quiescePowerTree(
2372 void * target
, IOPMCompletionAction action
, void * param
)
2374 IOPMRequest
* request
;
2377 return kIOPMNotYetInitialized
;
2378 if (!target
|| !action
)
2379 return kIOReturnBadArgument
;
2381 OUR_PMLog(kPMLogQuiescePowerTree
, 0, 0);
2383 // Target the root node instead of root domain. This is to avoid blocking
2384 // the quiesce request behind an existing root domain request in the work
2385 // queue. Root parent and root domain requests in the work queue must not
2386 // block the completion of the quiesce request.
2388 request
= acquirePMRequest(gIOPMRootNode
, kIOPMRequestTypeQuiescePowerTree
);
2390 return kIOReturnNoMemory
;
2392 request
->installCompletionAction(target
, action
, param
);
2394 // Submit through the normal request flow. This will make sure any request
2395 // already in the request queue will get pushed over to the work queue for
2396 // execution. Any request submitted after this request may not be serviced.
2398 submitPMRequest( request
);
2399 return kIOReturnSuccess
;
2402 //*********************************************************************************
2403 // [private] requestPowerState
2404 //*********************************************************************************
2406 IOReturn
IOService::requestPowerState(
2407 const OSSymbol
* client
,
2410 IOPMRequest
* request
;
2413 return kIOReturnBadArgument
;
2415 return kIOPMNotYetInitialized
;
2417 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2419 return kIOReturnNoMemory
;
2422 request
->fArg0
= (void *)(uintptr_t) state
;
2423 request
->fArg1
= (void *) client
;
2427 request
->installCompletionAction( action
, target
, param
);
2430 // Prevent needless downwards power transitions by clamping power
2431 // until the scheduled request is executed.
2433 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
))
2435 fTempClampPowerState
= StateMax(fTempClampPowerState
, state
);
2437 request
->fArg2
= (void *) (uintptr_t) true;
2440 submitPMRequest( request
);
2444 //*********************************************************************************
2445 // [private] handleRequestPowerState
2446 //*********************************************************************************
2448 void IOService::handleRequestPowerState( IOPMRequest
* request
)
2450 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2451 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2453 PM_ASSERT_IN_GATE();
2456 assert(fTempClampCount
!= 0);
2457 if (fTempClampCount
) fTempClampCount
--;
2458 if (!fTempClampCount
) fTempClampPowerState
= kPowerStateZero
;
2461 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
))
2462 state
= fHighestPowerState
;
2464 // The power suppression due to changePowerStateWithOverrideTo() expires
2465 // upon the next "device" power request - changePowerStateToPriv().
2467 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2468 (client
== gIOPMPowerClientDevice
))
2469 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2471 if ((state
== kPowerStateZero
) &&
2472 (client
!= gIOPMPowerClientDevice
) &&
2473 (client
!= gIOPMPowerClientDriver
) &&
2474 (client
!= gIOPMPowerClientChildProxy
))
2475 removePowerClient(client
);
2477 updatePowerClient(client
, state
);
2483 //*********************************************************************************
2484 // [private] Helper functions to update/remove power clients.
2485 //*********************************************************************************
2487 void IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2489 IOPMPowerStateIndex oldPowerState
= kPowerStateZero
;
2492 fPowerClients
= OSDictionary::withCapacity(4);
2493 if (fPowerClients
&& client
)
2495 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2498 oldPowerState
= num
->unsigned32BitValue();
2499 num
->setValue(powerState
);
2503 num
= OSNumber::withNumber(powerState
, 32);
2506 fPowerClients
->setObject(client
, num
);
2511 PM_ACTION_3(actionUpdatePowerClient
, client
, oldPowerState
, powerState
);
2515 void IOService::removePowerClient( const OSSymbol
* client
)
2517 if (fPowerClients
&& client
)
2518 fPowerClients
->removeObject(client
);
2521 uint32_t IOService::getPowerStateForClient( const OSSymbol
* client
)
2523 uint32_t powerState
= kPowerStateZero
;
2525 if (fPowerClients
&& client
)
2527 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2528 if (num
) powerState
= num
->unsigned32BitValue();
2533 //*********************************************************************************
2534 // [protected] powerOverrideOnPriv
2535 //*********************************************************************************
2537 IOReturn
IOService::powerOverrideOnPriv( void )
2539 IOPMRequest
* request
;
2542 return IOPMNotYetInitialized
;
2544 if (gIOPMWorkLoop
->inGate())
2546 fDeviceOverrideEnabled
= true;
2550 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2552 return kIOReturnNoMemory
;
2554 submitPMRequest( request
);
2558 //*********************************************************************************
2559 // [protected] powerOverrideOffPriv
2560 //*********************************************************************************
2562 IOReturn
IOService::powerOverrideOffPriv( void )
2564 IOPMRequest
* request
;
2567 return IOPMNotYetInitialized
;
2569 if (gIOPMWorkLoop
->inGate())
2571 fDeviceOverrideEnabled
= false;
2575 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2577 return kIOReturnNoMemory
;
2579 submitPMRequest( request
);
2583 //*********************************************************************************
2584 // [private] handlePowerOverrideChanged
2585 //*********************************************************************************
2587 void IOService::handlePowerOverrideChanged( IOPMRequest
* request
)
2589 PM_ASSERT_IN_GATE();
2590 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
)
2592 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2593 fDeviceOverrideEnabled
= true;
2597 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2598 fDeviceOverrideEnabled
= false;
2604 //*********************************************************************************
2605 // [private] computeDesiredState
2606 //*********************************************************************************
2608 void IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2612 IOPowerConnection
* connection
;
2613 uint32_t desiredState
= kPowerStateZero
;
2614 uint32_t newPowerState
= kPowerStateZero
;
2615 bool hasChildren
= false;
2617 // Desired power state is always 0 without a controlling driver.
2619 if (!fNumberOfPowerStates
)
2621 fDesiredPowerState
= kPowerStateZero
;
2625 // Examine the children's desired power state.
2627 iter
= getChildIterator(gIOPowerPlane
);
2630 while ((next
= iter
->getNextObject()))
2632 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
2634 if (connection
->getReadyFlag() == false)
2636 PM_LOG3("[%s] %s: connection not ready\n",
2637 getName(), __FUNCTION__
);
2640 if (connection
->childHasRequestedPower())
2642 desiredState
= StateMax(connection
->getDesiredDomainState(), desiredState
);
2648 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2650 removePowerClient(gIOPMPowerClientChildren
);
2652 // Iterate through all power clients to determine the min power state.
2654 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2657 const OSSymbol
* client
;
2658 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
2660 // Ignore child and driver when override is in effect.
2661 if ((fDeviceOverrideEnabled
||
2662 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2663 ((client
== gIOPMPowerClientChildren
) ||
2664 (client
== gIOPMPowerClientDriver
)))
2667 // Ignore child proxy when children are present.
2668 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
))
2671 // Advisory tickles are irrelevant unless system is in full wake
2672 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2673 !gIOPMAdvisoryTickleEnabled
)
2676 desiredState
= getPowerStateForClient(client
);
2677 assert(desiredState
< fNumberOfPowerStates
);
2679 desiredState
, client
->getCStringNoCopy());
2681 newPowerState
= StateMax(newPowerState
, desiredState
);
2683 if (client
== gIOPMPowerClientDevice
)
2684 fDeviceDesire
= desiredState
;
2689 // Factor in the temporary power desires.
2691 newPowerState
= StateMax(newPowerState
, localClamp
);
2692 newPowerState
= StateMax(newPowerState
, fTempClampPowerState
);
2694 // Limit check against max power override.
2696 newPowerState
= StateMin(newPowerState
, fOverrideMaxPowerState
);
2698 // Limit check against number of power states.
2700 if (newPowerState
>= fNumberOfPowerStates
)
2701 newPowerState
= fHighestPowerState
;
2703 fDesiredPowerState
= newPowerState
;
2705 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2706 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2707 (uint32_t) fCurrentPowerState
, newPowerState
);
2711 // Restart idle timer if possible when device desire has increased.
2712 // Or if an advisory desire exists.
2714 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
2719 // Invalidate cached tickle power state when desires change, and not
2720 // due to a tickle request. In case the driver has requested a lower
2721 // power state, but the tickle is caching a higher power state which
2722 // will drop future tickles until the cached value is lowered or in-
2723 // validated. The invalidation must occur before the power transition
2724 // to avoid dropping a necessary tickle.
2726 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2727 (fActivityTicklePowerState
!= kInvalidTicklePowerState
))
2729 IOLockLock(fActivityLock
);
2730 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2731 IOLockUnlock(fActivityLock
);
2736 //*********************************************************************************
2737 // [public] currentPowerConsumption
2739 //*********************************************************************************
2741 unsigned long IOService::currentPowerConsumption( void )
2744 return kIOPMUnknown
;
2746 return fCurrentPowerConsumption
;
2749 //*********************************************************************************
2750 // [deprecated] getPMworkloop
2751 //*********************************************************************************
2753 IOWorkLoop
* IOService::getPMworkloop( void )
2755 return gIOPMWorkLoop
;
2760 //*********************************************************************************
2761 // Power Parent/Children Applier
2762 //*********************************************************************************
2765 applyToPowerChildren(
2766 IOService
* service
,
2767 IOServiceApplierFunction applier
,
2769 IOOptionBits options
)
2771 PM_ASSERT_IN_GATE();
2773 IORegistryEntry
* entry
;
2774 IORegistryIterator
* iter
;
2775 IOPowerConnection
* connection
;
2778 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2781 while ((entry
= iter
->getNextObject()))
2783 // Get child of IOPowerConnection objects
2784 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2786 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2789 (*applier
)(child
, context
);
2800 IOService
* service
,
2801 IOServiceApplierFunction applier
,
2803 IOOptionBits options
)
2805 PM_ASSERT_IN_GATE();
2807 IORegistryEntry
* entry
;
2808 IORegistryIterator
* iter
;
2809 IOPowerConnection
* connection
;
2812 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2813 options
| kIORegistryIterateParents
);
2816 while ((entry
= iter
->getNextObject()))
2818 // Get child of IOPowerConnection objects
2819 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2821 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2824 (*applier
)(parent
, context
);
2833 #endif /* NOT_YET */
2836 // MARK: Activity Tickle & Idle Timer
2838 void IOService::setAdvisoryTickleEnable( bool enable
)
2840 gIOPMAdvisoryTickleEnabled
= enable
;
2843 //*********************************************************************************
2844 // [public] activityTickle
2846 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2847 // flag to be set, and the device state checked. If the device has been
2848 // powered down, it is powered up again.
2849 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2850 // should be intercepted by a subclass.
2851 //*********************************************************************************
2853 bool IOService::activityTickle( unsigned long type
, unsigned long stateNumber
)
2855 IOPMRequest
* request
;
2856 bool noPowerChange
= true;
2857 uint32_t tickleFlags
;
2860 return true; // no power change
2862 if ((type
== kIOPMSuperclassPolicy1
) && StateOrder(stateNumber
))
2864 IOLockLock(fActivityLock
);
2866 // Record device activity for the idle timer handler.
2868 fDeviceWasActive
= true;
2869 fActivityTickleCount
++;
2870 clock_get_uptime(&fDeviceActiveTimestamp
);
2872 PM_ACTION_0(actionActivityTickle
);
2874 // Record the last tickle power state.
2875 // This helps to filter out redundant tickles as
2876 // this function may be called from the data path.
2878 if ((fActivityTicklePowerState
== kInvalidTicklePowerState
)
2879 || StateOrder(fActivityTicklePowerState
) < StateOrder(stateNumber
))
2881 fActivityTicklePowerState
= stateNumber
;
2882 noPowerChange
= false;
2884 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2885 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2888 request
->fArg0
= (void *) stateNumber
;
2889 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2890 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2891 submitPMRequest(request
);
2895 IOLockUnlock(fActivityLock
);
2898 else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2899 ((stateNumber
= fDeviceUsablePowerState
) != kPowerStateZero
))
2901 IOLockLock(fActivityLock
);
2903 fAdvisoryTickled
= true;
2905 if (fAdvisoryTicklePowerState
!= stateNumber
)
2907 fAdvisoryTicklePowerState
= stateNumber
;
2908 noPowerChange
= false;
2910 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2911 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2914 request
->fArg0
= (void *) stateNumber
;
2915 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2916 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2917 submitPMRequest(request
);
2921 IOLockUnlock(fActivityLock
);
2924 // Returns false if the activityTickle might cause a transition to a
2925 // higher powered state, true otherwise.
2927 return noPowerChange
;
2930 //*********************************************************************************
2931 // [private] handleActivityTickle
2932 //*********************************************************************************
2934 void IOService::handleActivityTickle( IOPMRequest
* request
)
2936 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2937 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
2938 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
2939 bool adjustPower
= false;
2941 PM_ASSERT_IN_GATE();
2942 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
))
2944 // Drivers that don't want power restored on wake will drop any
2945 // tickles that pre-dates the current system wake. The model is
2946 // that each wake is a fresh start, with power state depressed
2947 // until a new tickle or an explicit power up request from the
2948 // driver. It is possible for the PM work loop to enter the
2949 // system sleep path with tickle requests queued.
2954 if (tickleFlags
& kTickleTypeActivity
)
2956 IOPMPowerStateIndex deviceDesireOrder
= StateOrder(fDeviceDesire
);
2957 uint32_t idleTimerGeneration
= ticklePowerState
; // kTickleTypePowerDrop
2959 if (tickleFlags
& kTickleTypePowerRise
)
2961 if ((StateOrder(ticklePowerState
) > deviceDesireOrder
) &&
2962 (ticklePowerState
< fNumberOfPowerStates
))
2964 fIdleTimerMinPowerState
= ticklePowerState
;
2965 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2969 else if ((deviceDesireOrder
> StateOrder(fIdleTimerMinPowerState
)) &&
2970 (idleTimerGeneration
== fIdleTimerGeneration
))
2972 // Power drop due to idle timer expiration.
2973 // Do not allow idle timer to reduce power below tickle power.
2974 // This prevents the idle timer from decreasing the device desire
2975 // to zero and cancelling the effect of a pre-sleep tickle when
2976 // system wakes up to doze state, while the device is unable to
2977 // raise its power state to satisfy the tickle.
2979 deviceDesireOrder
--;
2980 if (deviceDesireOrder
< fNumberOfPowerStates
)
2982 ticklePowerState
= fPowerStates
[deviceDesireOrder
].stateOrderToIndex
;
2983 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2988 else // advisory tickle
2990 if (tickleFlags
& kTickleTypePowerRise
)
2992 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
2993 (ticklePowerState
< fNumberOfPowerStates
))
2995 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
2996 fHasAdvisoryDesire
= true;
2997 fAdvisoryTickleUsed
= true;
3002 IOLockLock(fActivityLock
);
3003 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3004 IOLockUnlock(fActivityLock
);
3007 else if (fHasAdvisoryDesire
)
3009 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
3010 fHasAdvisoryDesire
= false;
3021 //******************************************************************************
3022 // [public] setIdleTimerPeriod
3024 // A subclass policy-maker is using our standard idleness detection service.
3025 // Start the idle timer. Period is in seconds.
3026 //******************************************************************************
3028 IOReturn
IOService::setIdleTimerPeriod( unsigned long period
)
3031 return IOPMNotYetInitialized
;
3033 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
3035 IOPMRequest
* request
=
3036 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
3038 return kIOReturnNoMemory
;
3040 request
->fArg0
= (void *) period
;
3041 submitPMRequest( request
);
3043 return kIOReturnSuccess
;
3046 IOReturn
IOService::setIgnoreIdleTimer( bool ignore
)
3049 return IOPMNotYetInitialized
;
3051 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
3053 IOPMRequest
* request
=
3054 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
3056 return kIOReturnNoMemory
;
3058 request
->fArg0
= (void *) ignore
;
3059 submitPMRequest( request
);
3061 return kIOReturnSuccess
;
3064 //******************************************************************************
3065 // [public] nextIdleTimeout
3067 // Returns how many "seconds from now" the device should idle into its
3068 // next lowest power state.
3069 //******************************************************************************
3071 SInt32
IOService::nextIdleTimeout(
3072 AbsoluteTime currentTime
,
3073 AbsoluteTime lastActivity
,
3074 unsigned int powerState
)
3081 // Calculate time difference using funky macro from clock.h.
3082 delta
= currentTime
;
3083 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
3085 // Figure it in seconds.
3086 absolutetime_to_nanoseconds(delta
, &delta_ns
);
3087 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
3089 // Be paranoid about delta somehow exceeding timer period.
3090 if (delta_secs
< (int) fIdleTimerPeriod
)
3091 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3093 delay_secs
= (int) fIdleTimerPeriod
;
3095 return (SInt32
)delay_secs
;
3098 //*********************************************************************************
3099 // [public] start_PM_idle_timer
3100 //*********************************************************************************
3102 void IOService::start_PM_idle_timer( void )
3104 static const int maxTimeout
= 100000;
3105 static const int minTimeout
= 1;
3106 AbsoluteTime uptime
, deadline
;
3110 if (!initialized
|| !fIdleTimerPeriod
)
3113 IOLockLock(fActivityLock
);
3115 clock_get_uptime(&uptime
);
3117 // Subclasses may modify idle sleep algorithm
3118 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3120 // Check for out-of range responses
3121 if (idle_in
> maxTimeout
)
3123 // use standard implementation
3124 idle_in
= IOService::nextIdleTimeout(uptime
,
3125 fDeviceActiveTimestamp
,
3126 fCurrentPowerState
);
3127 } else if (idle_in
< minTimeout
) {
3128 idle_in
= fIdleTimerPeriod
;
3131 IOLockUnlock(fActivityLock
);
3133 fNextIdleTimerPeriod
= idle_in
;
3134 fIdleTimerStartTime
= uptime
;
3137 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3138 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3139 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3140 if (pending
) release();
3143 //*********************************************************************************
3144 // [private] restartIdleTimer
3145 //*********************************************************************************
3147 void IOService::restartIdleTimer( void )
3149 if (fDeviceDesire
!= kPowerStateZero
)
3151 fIdleTimerStopped
= false;
3152 fActivityTickleCount
= 0;
3153 start_PM_idle_timer();
3155 else if (fHasAdvisoryDesire
)
3157 fIdleTimerStopped
= false;
3158 start_PM_idle_timer();
3162 fIdleTimerStopped
= true;
3166 //*********************************************************************************
3167 // idle_timer_expired
3168 //*********************************************************************************
3172 thread_call_param_t arg0
, thread_call_param_t arg1
)
3174 IOService
* me
= (IOService
*) arg0
;
3177 gIOPMWorkLoop
->runAction(
3178 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3179 &IOService::idleTimerExpired
),
3185 //*********************************************************************************
3186 // [private] idleTimerExpired
3188 // The idle timer has expired. If there has been activity since the last
3189 // expiration, just restart the timer and return. If there has not been
3190 // activity, switch to the next lower power state and restart the timer.
3191 //*********************************************************************************
3193 void IOService::idleTimerExpired( void )
3195 IOPMRequest
* request
;
3196 bool restartTimer
= true;
3197 uint32_t tickleFlags
;
3199 if ( !initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3200 fLockedFlags
.PMStop
)
3203 fIdleTimerStartTime
= 0;
3205 IOLockLock(fActivityLock
);
3207 // Check for device activity (tickles) over last timer period.
3209 if (fDeviceWasActive
)
3211 // Device was active - do not drop power, restart timer.
3212 fDeviceWasActive
= false;
3214 else if (!fIdleTimerIgnored
)
3216 // No device activity - drop power state by one level.
3217 // Decrement the cached tickle power state when possible.
3218 // This value may be kInvalidTicklePowerState before activityTickle()
3219 // is called, but the power drop request must be issued regardless.
3221 if ((fActivityTicklePowerState
!= kInvalidTicklePowerState
) &&
3222 (fActivityTicklePowerState
!= kPowerStateZero
))
3223 fActivityTicklePowerState
--;
3225 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3226 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3229 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3230 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3231 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3232 submitPMRequest( request
);
3234 // Do not restart timer until after the tickle request has been
3237 restartTimer
= false;
3241 if (fAdvisoryTickled
)
3243 fAdvisoryTickled
= false;
3245 else if (fHasAdvisoryDesire
)
3247 // Want new tickles to turn into pm request after we drop the lock
3248 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3250 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3251 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3254 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3255 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3256 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3257 submitPMRequest( request
);
3259 // Do not restart timer until after the tickle request has been
3262 restartTimer
= false;
3266 IOLockUnlock(fActivityLock
);
3269 start_PM_idle_timer();
3273 //*********************************************************************************
3274 // [deprecated] PM_idle_timer_expiration
3275 //*********************************************************************************
3277 void IOService::PM_idle_timer_expiration( void )
3281 //*********************************************************************************
3282 // [deprecated] command_received
3283 //*********************************************************************************
3285 void IOService::command_received( void *statePtr
, void *, void * , void * )
3288 #endif /* !__LP64__ */
3290 //*********************************************************************************
3291 // [public] setAggressiveness
3293 // Pass on the input parameters to all power domain children. All those which are
3294 // power domains will pass it on to their children, etc.
3295 //*********************************************************************************
3297 IOReturn
IOService::setAggressiveness( unsigned long type
, unsigned long newLevel
)
3299 return kIOReturnSuccess
;
3302 //*********************************************************************************
3303 // [public] getAggressiveness
3305 // Called by the user client.
3306 //*********************************************************************************
3308 IOReturn
IOService::getAggressiveness( unsigned long type
, unsigned long * currentLevel
)
3310 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3313 return kIOReturnNotReady
;
3315 return rootDomain
->getAggressiveness( type
, currentLevel
);
3318 //*********************************************************************************
3319 // [public] getPowerState
3321 //*********************************************************************************
3323 UInt32
IOService::getPowerState( void )
3326 return kPowerStateZero
;
3328 return fCurrentPowerState
;
3332 //*********************************************************************************
3333 // [deprecated] systemWake
3335 // Pass this to all power domain children. All those which are
3336 // power domains will pass it on to their children, etc.
3337 //*********************************************************************************
3339 IOReturn
IOService::systemWake( void )
3343 IOPowerConnection
* connection
;
3344 IOService
* theChild
;
3346 iter
= getChildIterator(gIOPowerPlane
);
3349 while ( (next
= iter
->getNextObject()) )
3351 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
3353 if (connection
->getReadyFlag() == false)
3355 PM_LOG3("[%s] %s: connection not ready\n",
3356 getName(), __FUNCTION__
);
3360 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3363 theChild
->systemWake();
3364 theChild
->release();
3371 if ( fControllingDriver
!= NULL
)
3373 if ( fControllingDriver
->didYouWakeSystem() )
3382 //*********************************************************************************
3383 // [deprecated] temperatureCriticalForZone
3384 //*********************************************************************************
3386 IOReturn
IOService::temperatureCriticalForZone( IOService
* whichZone
)
3388 IOService
* theParent
;
3391 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3393 if ( inPlane(gIOPowerPlane
) && !IS_PM_ROOT
)
3395 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3398 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3402 theParent
->temperatureCriticalForZone(whichZone
);
3403 theParent
->release();
3409 #endif /* !__LP64__ */
3412 // MARK: Power Change (Common)
3414 //*********************************************************************************
3415 // [private] startPowerChange
3417 // All power state changes starts here.
3418 //*********************************************************************************
3420 IOReturn
IOService::startPowerChange(
3421 IOPMPowerChangeFlags changeFlags
,
3422 IOPMPowerStateIndex powerState
,
3423 IOPMPowerFlags domainFlags
,
3424 IOPowerConnection
* parentConnection
,
3425 IOPMPowerFlags parentFlags
)
3427 PM_ASSERT_IN_GATE();
3428 assert( fMachineState
== kIOPM_Finished
);
3429 assert( powerState
< fNumberOfPowerStates
);
3431 if (powerState
>= fNumberOfPowerStates
)
3432 return IOPMAckImplied
;
3434 fIsPreChange
= true;
3435 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3437 if (changeFlags
& kIOPMExpireIdleTimer
)
3439 // Root domain requested removal of tickle influence
3440 if (StateOrder(fDeviceDesire
) > StateOrder(powerState
))
3442 // Reset device desire down to the clamped power state
3443 updatePowerClient(gIOPMPowerClientDevice
, powerState
);
3444 computeDesiredState(kPowerStateZero
, true);
3446 // Invalidate tickle cache so the next tickle will issue a request
3447 IOLockLock(fActivityLock
);
3448 fDeviceWasActive
= false;
3449 fActivityTicklePowerState
= kInvalidTicklePowerState
;
3450 IOLockUnlock(fActivityLock
);
3452 fIdleTimerMinPowerState
= kPowerStateZero
;
3456 // Root domain's override handler may cancel the power change by
3457 // setting the kIOPMNotDone flag.
3459 if (changeFlags
& kIOPMNotDone
)
3460 return IOPMAckImplied
;
3462 // Forks to either Driver or Parent initiated power change paths.
3464 fHeadNoteChangeFlags
= changeFlags
;
3465 fHeadNotePowerState
= powerState
;
3466 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
3467 fHeadNoteParentConnection
= NULL
;
3469 if (changeFlags
& kIOPMSelfInitiated
)
3471 if (changeFlags
& kIOPMSynchronize
)
3479 assert(changeFlags
& kIOPMParentInitiated
);
3480 fHeadNoteDomainFlags
= domainFlags
;
3481 fHeadNoteParentFlags
= parentFlags
;
3482 fHeadNoteParentConnection
= parentConnection
;
3483 return ParentChangeStart();
3487 //*********************************************************************************
3488 // [private] notifyInterestedDrivers
3489 //*********************************************************************************
3491 bool IOService::notifyInterestedDrivers( void )
3493 IOPMinformee
* informee
;
3494 IOPMinformeeList
* list
= fInterestedDrivers
;
3495 DriverCallParam
* param
;
3498 PM_ASSERT_IN_GATE();
3499 assert( fDriverCallParamCount
== 0 );
3500 assert( fHeadNotePendingAcks
== 0 );
3502 fHeadNotePendingAcks
= 0;
3504 count
= list
->numberOfItems();
3506 goto done
; // no interested drivers
3508 // Allocate an array of interested drivers and their return values
3509 // for the callout thread. Everything else is still "owned" by the
3510 // PM work loop, which can run to process acknowledgePowerChange()
3513 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3514 if (count
> fDriverCallParamSlots
)
3516 if (fDriverCallParamSlots
)
3518 assert(fDriverCallParamPtr
);
3519 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3520 fDriverCallParamPtr
= 0;
3521 fDriverCallParamSlots
= 0;
3524 param
= IONew(DriverCallParam
, count
);
3526 goto done
; // no memory
3528 fDriverCallParamPtr
= (void *) param
;
3529 fDriverCallParamSlots
= count
;
3532 informee
= list
->firstInList();
3534 for (IOItemCount i
= 0; i
< count
; i
++)
3536 informee
->timer
= -1;
3537 param
[i
].Target
= informee
;
3539 informee
= list
->nextInList( informee
);
3542 fDriverCallParamCount
= count
;
3543 fHeadNotePendingAcks
= count
;
3545 // Block state machine and wait for callout completion.
3546 assert(!fDriverCallBusy
);
3547 fDriverCallBusy
= true;
3548 thread_call_enter( fDriverCallEntry
);
3552 // Return false if there are no interested drivers or could not schedule
3553 // callout thread due to error.
3557 //*********************************************************************************
3558 // [private] notifyInterestedDriversDone
3559 //*********************************************************************************
3561 void IOService::notifyInterestedDriversDone( void )
3563 IOPMinformee
* informee
;
3565 DriverCallParam
* param
;
3568 PM_ASSERT_IN_GATE();
3569 assert( fDriverCallBusy
== false );
3570 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3572 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3573 count
= fDriverCallParamCount
;
3577 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3579 informee
= (IOPMinformee
*) param
->Target
;
3580 result
= param
->Result
;
3582 if ((result
== IOPMAckImplied
) || (result
< 0))
3584 // Interested driver return IOPMAckImplied.
3585 // If informee timer is zero, it must have de-registered
3586 // interest during the thread callout. That also drops
3587 // the pending ack count.
3589 if (fHeadNotePendingAcks
&& informee
->timer
)
3590 fHeadNotePendingAcks
--;
3592 informee
->timer
= 0;
3594 else if (informee
->timer
)
3596 assert(informee
->timer
== -1);
3598 // Driver has not acked, and has returned a positive result.
3599 // Enforce a minimum permissible timeout value.
3600 // Make the min value large enough so timeout is less likely
3601 // to occur if a driver misinterpreted that the return value
3602 // should be in microsecond units. And make it large enough
3603 // to be noticeable if a driver neglects to ack.
3605 if (result
< kMinAckTimeoutTicks
)
3606 result
= kMinAckTimeoutTicks
;
3608 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3610 // else, child has already acked or driver has removed interest,
3611 // and head_note_pendingAcks decremented.
3612 // informee may have been removed from the interested drivers list,
3613 // thus the informee must be retained across the callout.
3615 informee
->release();
3618 fDriverCallParamCount
= 0;
3620 if ( fHeadNotePendingAcks
)
3622 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3627 MS_POP(); // pop the machine state passed to notifyAll()
3629 // If interest acks are outstanding, block the state machine until
3630 // fHeadNotePendingAcks drops to zero before notifying root domain.
3631 // Otherwise notify root domain directly.
3633 if (!fHeadNotePendingAcks
)
3639 MS_PUSH(fMachineState
);
3640 fMachineState
= kIOPM_NotifyChildrenStart
;
3644 //*********************************************************************************
3645 // [private] notifyRootDomain
3646 //*********************************************************************************
3648 void IOService::notifyRootDomain( void )
3650 assert( fDriverCallBusy
== false );
3652 // Only for root domain in the will-change phase
3653 if (!IS_ROOT_DOMAIN
|| (fMachineState
!= kIOPM_OurChangeSetPowerState
))
3659 MS_PUSH(fMachineState
); // push notifyAll() machine state
3660 fMachineState
= kIOPM_DriverThreadCallDone
;
3662 // Call IOPMrootDomain::willNotifyPowerChildren() on a thread call
3663 // to avoid a deadlock.
3664 fDriverCallReason
= kRootDomainInformPreChange
;
3665 fDriverCallBusy
= true;
3666 thread_call_enter( fDriverCallEntry
);
3669 void IOService::notifyRootDomainDone( void )
3671 assert( fDriverCallBusy
== false );
3672 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3674 MS_POP(); // pop notifyAll() machine state
3678 //*********************************************************************************
3679 // [private] notifyChildren
3680 //*********************************************************************************
3682 void IOService::notifyChildren( void )
3686 IOPowerConnection
* connection
;
3687 OSArray
* children
= 0;
3688 IOPMrootDomain
* rootDomain
;
3689 bool delayNotify
= false;
3691 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3692 (IS_POWER_DROP
== fIsPreChange
) &&
3693 ((rootDomain
= getPMRootDomain()) == this))
3695 rootDomain
->tracePoint( IS_POWER_DROP
?
3696 kIOPMTracePointSleepPowerPlaneDrivers
:
3697 kIOPMTracePointWakePowerPlaneDrivers
);
3700 if (fStrictTreeOrder
)
3701 children
= OSArray::withCapacity(8);
3703 // Sum child power consumption in notifyChild()
3704 fHeadNotePowerArrayEntry
->staticPower
= 0;
3706 iter
= getChildIterator(gIOPowerPlane
);
3709 while ((next
= iter
->getNextObject()))
3711 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3713 if (connection
->getReadyFlag() == false)
3715 PM_LOG3("[%s] %s: connection not ready\n",
3716 getName(), __FUNCTION__
);
3720 // Mechanism to postpone the did-change notification to
3721 // certain power children to order those children last.
3722 // Cannot be used together with strict tree ordering.
3724 if (!fIsPreChange
&&
3725 connection
->delayChildNotification
&&
3726 getPMRootDomain()->shouldDelayChildNotification(this))
3730 children
= OSArray::withCapacity(8);
3736 children
->setObject( connection
);
3741 if (!delayNotify
&& children
)
3742 children
->setObject( connection
);
3744 notifyChild( connection
);
3750 if (children
&& (children
->getCount() == 0))
3752 children
->release();
3757 assert(fNotifyChildArray
== 0);
3758 fNotifyChildArray
= children
;
3759 MS_PUSH(fMachineState
);
3763 // Block until all non-delayed children have acked their
3764 // notification. Then notify the remaining delayed child
3765 // in the array. This is used to hold off graphics child
3766 // notification while the rest of the system powers up.
3767 // If a hid tickle arrives during this time, the delayed
3768 // children are immediately notified and root domain will
3769 // not clamp power for dark wake.
3771 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3772 PM_LOG2("%s: %d children in delayed array\n",
3773 getName(), children
->getCount());
3777 // Child array created to support strict notification order.
3778 // Notify children in the array one at a time.
3780 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3785 //*********************************************************************************
3786 // [private] notifyChildrenOrdered
3787 //*********************************************************************************
3789 void IOService::notifyChildrenOrdered( void )
3791 PM_ASSERT_IN_GATE();
3792 assert(fNotifyChildArray
);
3793 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3795 // Notify one child, wait for it to ack, then repeat for next child.
3796 // This is a workaround for some drivers with multiple instances at
3797 // the same branch in the power tree, but the driver is slow to power
3798 // up unless the tree ordering is observed. Problem observed only on
3799 // system wake, not on system sleep.
3801 // We have the ability to power off in reverse child index order.
3802 // That works nicely on some machines, but not on all HW configs.
3804 if (fNotifyChildArray
->getCount())
3806 IOPowerConnection
* connection
;
3807 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3808 notifyChild( connection
);
3809 fNotifyChildArray
->removeObject(0);
3813 fNotifyChildArray
->release();
3814 fNotifyChildArray
= 0;
3816 MS_POP(); // pushed by notifyChildren()
3820 //*********************************************************************************
3821 // [private] notifyChildrenDelayed
3822 //*********************************************************************************
3824 void IOService::notifyChildrenDelayed( void )
3826 IOPowerConnection
* connection
;
3828 PM_ASSERT_IN_GATE();
3829 assert(fNotifyChildArray
);
3830 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3832 // Wait after all non-delayed children and interested drivers have ack'ed,
3833 // then notify all delayed children. If notify delay is canceled, child
3834 // acks may be outstanding with PM blocked on fHeadNotePendingAcks != 0.
3835 // But the handling for either case is identical.
3837 for (int i
= 0; ; i
++)
3839 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3843 notifyChild( connection
);
3846 PM_LOG2("%s: notified delayed children\n", getName());
3847 fNotifyChildArray
->release();
3848 fNotifyChildArray
= 0;
3850 MS_POP(); // pushed by notifyChildren()
3853 //*********************************************************************************
3854 // [private] notifyAll
3855 //*********************************************************************************
3857 IOReturn
IOService::notifyAll( uint32_t nextMS
)
3859 // Save the machine state to be restored by notifyInterestedDriversDone()
3861 PM_ASSERT_IN_GATE();
3863 fMachineState
= kIOPM_DriverThreadCallDone
;
3864 fDriverCallReason
= fIsPreChange
?
3865 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3867 if (!notifyInterestedDrivers())
3868 notifyInterestedDriversDone();
3870 return IOPMWillAckLater
;
3873 //*********************************************************************************
3874 // [private, static] pmDriverCallout
3876 // Thread call context
3877 //*********************************************************************************
3879 IOReturn
IOService::actionDriverCalloutDone(
3881 void * arg0
, void * arg1
,
3882 void * arg2
, void * arg3
)
3884 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3886 assert( fDriverCallBusy
);
3887 fDriverCallBusy
= false;
3889 assert(gIOPMWorkQueue
);
3890 gIOPMWorkQueue
->signalWorkAvailable();
3892 return kIOReturnSuccess
;
3895 void IOService::pmDriverCallout( IOService
* from
)
3898 switch (from
->fDriverCallReason
)
3900 case kDriverCallSetPowerState
:
3901 from
->driverSetPowerState();
3904 case kDriverCallInformPreChange
:
3905 case kDriverCallInformPostChange
:
3906 from
->driverInformPowerChange();
3909 case kRootDomainInformPreChange
:
3910 getPMRootDomain()->willNotifyPowerChildren(from
->fHeadNotePowerState
);
3914 panic("IOService::pmDriverCallout bad machine state %x",
3915 from
->fDriverCallReason
);
3918 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3920 /* arg0 */ (void *) from
->pwrMgt
);
3923 //*********************************************************************************
3924 // [private] driverSetPowerState
3926 // Thread call context
3927 //*********************************************************************************
3929 void IOService::driverSetPowerState( void )
3931 IOPMPowerStateIndex powerState
;
3932 DriverCallParam
* param
;
3933 IOPMDriverCallEntry callEntry
;
3936 uint32_t oldPowerState
= getPowerState();
3938 assert( fDriverCallBusy
);
3939 assert( fDriverCallParamPtr
);
3940 assert( fDriverCallParamCount
== 1 );
3942 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3943 powerState
= fHeadNotePowerState
;
3945 if (assertPMDriverCall(&callEntry
))
3947 OUR_PMLog( kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3948 start_spindump_timer("SetState");
3949 clock_get_uptime(&fDriverCallStartTime
);
3950 result
= fControllingDriver
->setPowerState( powerState
, this );
3951 clock_get_uptime(&end
);
3952 stop_spindump_timer();
3953 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3955 deassertPMDriverCall(&callEntry
);
3957 // Record the most recent max power state residency timings.
3958 // Use with DeviceActiveTimestamp to diagnose tickle issues.
3959 if (powerState
== fHighestPowerState
)
3960 fMaxPowerStateEntryTime
= end
;
3961 else if (oldPowerState
== fHighestPowerState
)
3962 fMaxPowerStateExitTime
= end
;
3966 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
3967 fName
, OBFUSCATE(this), fCurrentPowerState
, powerState
, result
);
3970 #if LOG_SETPOWER_TIMES
3971 if ((result
== IOPMAckImplied
) || (result
< 0))
3975 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
3976 absolutetime_to_nanoseconds(end
, &nsec
);
3977 if (nsec
> LOG_SETPOWER_TIMES
) {
3978 getPMRootDomain()->pmStatsRecordApplicationResponse(
3979 gIOPMStatsDriverPSChangeSlow
,
3980 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), 0, NULL
, powerState
);
3986 result
= kIOPMAckImplied
;
3988 param
->Result
= result
;
3991 //*********************************************************************************
3992 // [private] driverInformPowerChange
3994 // Thread call context
3995 //*********************************************************************************
3997 void IOService::driverInformPowerChange( void )
3999 IOPMinformee
* informee
;
4001 DriverCallParam
* param
;
4002 IOPMDriverCallEntry callEntry
;
4003 IOPMPowerFlags powerFlags
;
4004 IOPMPowerStateIndex powerState
;
4009 assert( fDriverCallBusy
);
4010 assert( fDriverCallParamPtr
);
4011 assert( fDriverCallParamCount
);
4013 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4014 count
= fDriverCallParamCount
;
4016 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4017 powerState
= fHeadNotePowerState
;
4019 for (IOItemCount i
= 0; i
< count
; i
++)
4021 informee
= (IOPMinformee
*) param
->Target
;
4022 driver
= informee
->whatObject
;
4024 if (assertPMDriverCall(&callEntry
, 0, informee
))
4026 if (fDriverCallReason
== kDriverCallInformPreChange
)
4028 OUR_PMLog(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
4029 start_spindump_timer("WillChange");
4030 clock_get_uptime(&informee
->startTime
);
4031 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
4032 clock_get_uptime(&end
);
4033 stop_spindump_timer();
4034 OUR_PMLog((UInt32
)-kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
4038 OUR_PMLog(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
4039 start_spindump_timer("DidChange");
4040 clock_get_uptime(&informee
->startTime
);
4041 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
4042 clock_get_uptime(&end
);
4043 stop_spindump_timer();
4044 OUR_PMLog((UInt32
)-kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
4047 deassertPMDriverCall(&callEntry
);
4049 #if LOG_SETPOWER_TIMES
4050 if ((result
== IOPMAckImplied
) || (result
< 0))
4054 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
4055 absolutetime_to_nanoseconds(end
, &nsec
);
4056 if (nsec
> LOG_SETPOWER_TIMES
) {
4057 getPMRootDomain()->pmStatsRecordApplicationResponse(
4058 gIOPMStatsDriverPSChangeSlow
, driver
->getName(),
4059 fDriverCallReason
, NS_TO_MS(nsec
), 0, NULL
, powerState
);
4065 result
= kIOPMAckImplied
;
4067 param
->Result
= result
;
4072 //*********************************************************************************
4073 // [private] notifyChild
4075 // Notify a power domain child of an upcoming power change.
4076 // If the object acknowledges the current change, we return TRUE.
4077 //*********************************************************************************
4079 bool IOService::notifyChild( IOPowerConnection
* theNub
)
4081 IOReturn ret
= IOPMAckImplied
;
4082 unsigned long childPower
;
4083 IOService
* theChild
;
4084 IOPMRequest
* childRequest
;
4085 IOPMPowerChangeFlags requestArg2
;
4088 PM_ASSERT_IN_GATE();
4089 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
4095 // Unless the child handles the notification immediately and returns
4096 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4097 fHeadNotePendingAcks
++;
4098 theNub
->setAwaitingAck(true);
4100 requestArg2
= fHeadNoteChangeFlags
;
4101 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
))
4102 requestArg2
|= kIOPMDomainPowerDrop
;
4104 requestType
= fIsPreChange
?
4105 kIOPMRequestTypePowerDomainWillChange
:
4106 kIOPMRequestTypePowerDomainDidChange
;
4108 childRequest
= acquirePMRequest( theChild
, requestType
);
4112 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4113 childRequest
->fArg1
= (void *) theNub
;
4114 childRequest
->fArg2
= (void *)(uintptr_t) requestArg2
;
4115 theChild
->submitPMRequest( childRequest
);
4116 ret
= IOPMWillAckLater
;
4120 ret
= IOPMAckImplied
;
4121 fHeadNotePendingAcks
--;
4122 theNub
->setAwaitingAck(false);
4123 childPower
= theChild
->currentPowerConsumption();
4124 if ( childPower
== kIOPMUnknown
)
4126 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4128 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
4129 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4133 theChild
->release();
4134 return (IOPMAckImplied
== ret
);
4137 //*********************************************************************************
4138 // [private] notifyControllingDriver
4139 //*********************************************************************************
4141 bool IOService::notifyControllingDriver( void )
4143 DriverCallParam
* param
;
4145 PM_ASSERT_IN_GATE();
4146 assert( fDriverCallParamCount
== 0 );
4147 assert( fControllingDriver
);
4149 if (fInitialSetPowerState
)
4151 fInitialSetPowerState
= false;
4152 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4154 // Driver specified flag to skip the inital setPowerState()
4155 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)
4161 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4164 param
= IONew(DriverCallParam
, 1);
4166 return false; // no memory
4168 fDriverCallParamPtr
= (void *) param
;
4169 fDriverCallParamSlots
= 1;
4172 param
->Target
= fControllingDriver
;
4173 fDriverCallParamCount
= 1;
4176 // Block state machine and wait for callout completion.
4177 assert(!fDriverCallBusy
);
4178 fDriverCallBusy
= true;
4179 thread_call_enter( fDriverCallEntry
);
4184 //*********************************************************************************
4185 // [private] notifyControllingDriverDone
4186 //*********************************************************************************
4188 void IOService::notifyControllingDriverDone( void )
4190 DriverCallParam
* param
;
4193 PM_ASSERT_IN_GATE();
4194 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4196 assert( fDriverCallBusy
== false );
4197 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4199 if (param
&& fDriverCallParamCount
)
4201 assert(fDriverCallParamCount
== 1);
4203 // the return value from setPowerState()
4204 result
= param
->Result
;
4206 if ((result
== IOPMAckImplied
) || (result
< 0))
4210 else if (fDriverTimer
)
4212 assert(fDriverTimer
== -1);
4214 // Driver has not acked, and has returned a positive result.
4215 // Enforce a minimum permissible timeout value.
4216 // Make the min value large enough so timeout is less likely
4217 // to occur if a driver misinterpreted that the return value
4218 // should be in microsecond units. And make it large enough
4219 // to be noticeable if a driver neglects to ack.
4221 if (result
< kMinAckTimeoutTicks
)
4222 result
= kMinAckTimeoutTicks
;
4224 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4226 // else, child has already acked and driver_timer reset to 0.
4228 fDriverCallParamCount
= 0;
4232 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4237 MS_POP(); // pushed by OurChangeSetPowerState()
4238 fIsPreChange
= false;
4241 //*********************************************************************************
4242 // [private] all_done
4244 // A power change is done.
4245 //*********************************************************************************
4247 void IOService::all_done( void )
4249 IOPMPowerStateIndex prevPowerState
;
4250 const IOPMPSEntry
* powerStatePtr
;
4251 IOPMDriverCallEntry callEntry
;
4252 uint32_t prevMachineState
= fMachineState
;
4253 bool actionCalled
= false;
4256 fMachineState
= kIOPM_Finished
;
4258 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4259 ((prevMachineState
== kIOPM_Finished
) ||
4260 (prevMachineState
== kIOPM_SyncFinish
)))
4262 // Sync operation and no power change occurred.
4263 // Do not inform driver and clients about this request completion,
4264 // except for the originator (root domain).
4266 PM_ACTION_2(actionPowerChangeDone
,
4267 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4269 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
4271 powerChangeDone(fCurrentPowerState
);
4273 else if (fAdvisoryTickleUsed
)
4275 // Not root domain and advisory tickle target.
4276 // Re-adjust power after power tree sync at the 'did' pass
4277 // to recompute desire and adjust power state between dark
4278 // and full wake transitions. Root domain is responsible
4279 // for calling setAdvisoryTickleEnable() before starting
4280 // the kIOPMSynchronize power change.
4282 if (!fAdjustPowerScheduled
&&
4283 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
))
4285 IOPMRequest
* request
;
4286 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4289 submitPMRequest( request
);
4290 fAdjustPowerScheduled
= true;
4299 if (fHeadNoteChangeFlags
& kIOPMSelfInitiated
)
4301 // power state changed
4302 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0)
4304 trackSystemSleepPreventers(
4305 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4307 // we changed, tell our parent
4308 requestDomainPower(fHeadNotePowerState
);
4310 // yes, did power raise?
4311 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4313 // yes, inform clients and apps
4314 tellChangeUp (fHeadNotePowerState
);
4316 prevPowerState
= fCurrentPowerState
;
4318 fCurrentPowerState
= fHeadNotePowerState
;
4321 ts
= mach_absolute_time();
4322 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4326 fPMVars
->myCurrentState
= fCurrentPowerState
;
4328 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4329 PM_ACTION_2(actionPowerChangeDone
,
4330 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4331 actionCalled
= true;
4333 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4334 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4335 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4336 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4338 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4340 // Bump tickle generation count once the entire tree is down
4341 gIOPMTickleGeneration
++;
4344 // inform subclass policy-maker
4345 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4346 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4348 powerChangeDone(prevPowerState
);
4349 deassertPMDriverCall(&callEntry
);
4352 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
4354 // changePowerStateWithOverrideTo() was cancelled
4355 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4359 // parent-initiated power change
4360 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
4362 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4363 ParentChangeRootChangeDown();
4365 // power state changed
4366 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0)
4368 trackSystemSleepPreventers(
4369 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4372 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4374 // yes, inform clients and apps
4375 tellChangeUp (fHeadNotePowerState
);
4378 prevPowerState
= fCurrentPowerState
;
4379 fCurrentPowerState
= fHeadNotePowerState
;
4382 ts
= mach_absolute_time();
4383 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4387 fPMVars
->myCurrentState
= fCurrentPowerState
;
4390 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4391 PM_ACTION_2(actionPowerChangeDone
,
4392 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4393 actionCalled
= true;
4395 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4396 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4397 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4398 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4400 // inform subclass policy-maker
4401 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4402 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4404 powerChangeDone(prevPowerState
);
4405 deassertPMDriverCall(&callEntry
);
4410 // When power rises enough to satisfy the tickle's desire for more power,
4411 // the condition preventing idle-timer from dropping power is removed.
4413 if (StateOrder(fCurrentPowerState
) >= StateOrder(fIdleTimerMinPowerState
))
4415 fIdleTimerMinPowerState
= kPowerStateZero
;
4420 PM_ACTION_2(actionPowerChangeDone
,
4421 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4426 // MARK: Power Change Initiated by Driver
4428 //*********************************************************************************
4429 // [private] OurChangeStart
4431 // Begin the processing of a power change initiated by us.
4432 //*********************************************************************************
4434 void IOService::OurChangeStart( void )
4436 PM_ASSERT_IN_GATE();
4437 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4439 // fMaxPowerState is our maximum possible power state based on the current
4440 // power state of our parents. If we are trying to raise power beyond the
4441 // maximum, send an async request for more power to all parents.
4443 if (!IS_PM_ROOT
&& (StateOrder(fMaxPowerState
) < StateOrder(fHeadNotePowerState
)))
4445 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4446 requestDomainPower(fHeadNotePowerState
);
4451 // Redundant power changes skips to the end of the state machine.
4453 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
4458 fInitialPowerChange
= false;
4460 // Change started, but may not complete...
4461 // Can be canceled (power drop) or deferred (power rise).
4463 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4465 // Two separate paths, depending if power is being raised or lowered.
4466 // Lowering power is subject to approval by clients of this service.
4470 fDoNotPowerDown
= false;
4472 // Ask for persmission to drop power state
4473 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4474 fOutOfBandParameter
= kNotifyApps
;
4475 askChangeDown(fHeadNotePowerState
);
4479 // This service is raising power and parents are able to support the
4480 // new power state. However a parent may have already committed to
4481 // drop power, which might force this object to temporarily drop power.
4482 // This results in "oscillations" before the state machines converge
4483 // to a steady state.
4485 // To prevent this, a child must make a power reservation against all
4486 // parents before raising power. If the reservation fails, indicating
4487 // that the child will be unable to sustain the higher power state,
4488 // then the child will signal the parent to adjust power, and the child
4489 // will defer its power change.
4493 // Reserve parent power necessary to achieve fHeadNotePowerState.
4494 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4495 if (ret
!= kIOReturnSuccess
)
4497 // Reservation failed, defer power rise.
4498 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4503 OurChangeTellCapabilityWillChange();
4507 //*********************************************************************************
4508 // [private] requestDomainPowerApplier
4510 // Call requestPowerDomainState() on all power parents.
4511 //*********************************************************************************
4513 struct IOPMRequestDomainPowerContext
{
4514 IOService
* child
; // the requesting child
4515 IOPMPowerFlags requestPowerFlags
; // power flags requested by child
4519 requestDomainPowerApplier(
4520 IORegistryEntry
* entry
,
4523 IOPowerConnection
* connection
;
4525 IOPMRequestDomainPowerContext
* context
;
4527 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0)
4529 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4534 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4536 if (connection
->parentKnowsState() && connection
->getReadyFlag())
4538 parent
->requestPowerDomainState(
4539 context
->requestPowerFlags
,
4547 //*********************************************************************************
4548 // [private] requestDomainPower
4550 // Called by a power child to broadcast its desired power state to all parents.
4551 // If the child self-initiates a power change, it must call this function to
4552 // allow its parents to adjust power state.
4553 //*********************************************************************************
4555 IOReturn
IOService::requestDomainPower(
4556 IOPMPowerStateIndex ourPowerState
,
4557 IOOptionBits options
)
4559 IOPMPowerFlags requestPowerFlags
;
4560 IOPMPowerStateIndex maxPowerState
;
4561 IOPMRequestDomainPowerContext context
;
4563 PM_ASSERT_IN_GATE();
4564 assert(ourPowerState
< fNumberOfPowerStates
);
4565 if (ourPowerState
>= fNumberOfPowerStates
)
4566 return kIOReturnBadArgument
;
4568 return kIOReturnSuccess
;
4570 // Fetch our input power flags for the requested power state.
4571 // Parent request is stated in terms of required power flags.
4573 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4575 // Disregard the "previous request" for power reservation.
4577 if (((options
& kReserveDomainPower
) == 0) &&
4578 (fPreviousRequestPowerFlags
== requestPowerFlags
))
4580 // skip if domain already knows our requirements
4583 fPreviousRequestPowerFlags
= requestPowerFlags
;
4585 // The results will be collected by fHeadNoteDomainTargetFlags
4586 context
.child
= this;
4587 context
.requestPowerFlags
= requestPowerFlags
;
4588 fHeadNoteDomainTargetFlags
= 0;
4589 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4591 if (options
& kReserveDomainPower
)
4593 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4594 fHeadNoteDomainTargetFlags
);
4596 if (StateOrder(maxPowerState
) < StateOrder(ourPowerState
))
4598 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4600 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4601 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4602 return kIOReturnNoPower
;
4607 return kIOReturnSuccess
;
4610 //*********************************************************************************
4611 // [private] OurSyncStart
4612 //*********************************************************************************
4614 void IOService::OurSyncStart( void )
4616 PM_ASSERT_IN_GATE();
4618 if (fInitialPowerChange
)
4621 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4623 if (fHeadNoteChangeFlags
& kIOPMNotDone
)
4629 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
)
4631 fDoNotPowerDown
= false;
4633 // Ask for permission to drop power state
4634 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4635 fOutOfBandParameter
= kNotifyApps
;
4636 askChangeDown(fHeadNotePowerState
);
4640 // Only inform capability app and clients.
4641 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4645 //*********************************************************************************
4646 // [private] OurChangeTellClientsPowerDown
4648 // All applications and kernel clients have acknowledged our permission to drop
4649 // power. Here we notify them that we will lower the power and wait for acks.
4650 //*********************************************************************************
4652 void IOService::OurChangeTellClientsPowerDown( void )
4655 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4658 fMachineState
= kIOPM_OurChangeTellUserPMPolicyPowerDown
;
4660 tellChangeDown1(fHeadNotePowerState
);
4663 //*********************************************************************************
4664 // [private] OurChangeTellUserPMPolicyPowerDown
4666 // All applications and kernel clients have acknowledged our permission to drop
4667 // power. Here we notify power management policy in user-space and wait for acks
4668 // one last time before we lower power
4669 //*********************************************************************************
4670 void IOService::OurChangeTellUserPMPolicyPowerDown ( void )
4672 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4673 fOutOfBandParameter
= kNotifyApps
;
4675 tellClientsWithResponse(kIOPMMessageLastCallBeforeSleep
);
4678 //*********************************************************************************
4679 // [private] OurChangeTellPriorityClientsPowerDown
4681 // All applications and kernel clients have acknowledged our intention to drop
4682 // power. Here we notify "priority" clients that we are lowering power.
4683 //*********************************************************************************
4685 void IOService::OurChangeTellPriorityClientsPowerDown( void )
4687 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4688 tellChangeDown2(fHeadNotePowerState
);
4691 //*********************************************************************************
4692 // [private] OurChangeTellCapabilityWillChange
4694 // Extra stage for root domain to notify apps and drivers about the
4695 // system capability change when raising power state.
4696 //*********************************************************************************
4698 void IOService::OurChangeTellCapabilityWillChange( void )
4700 if (!IS_ROOT_DOMAIN
)
4701 return OurChangeNotifyInterestedDriversWillChange();
4703 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4706 //*********************************************************************************
4707 // [private] OurChangeNotifyInterestedDriversWillChange
4709 // All applications and kernel clients have acknowledged our power state change.
4710 // Here we notify interested drivers pre-change.
4711 //*********************************************************************************
4713 void IOService::OurChangeNotifyInterestedDriversWillChange( void )
4715 IOPMrootDomain
* rootDomain
;
4716 if ((rootDomain
= getPMRootDomain()) == this)
4720 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4723 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4726 notifyAll( kIOPM_OurChangeSetPowerState
);
4729 //*********************************************************************************
4730 // [private] OurChangeSetPowerState
4732 // Instruct our controlling driver to program the hardware for the power state
4733 // change. Wait for async completions.
4734 //*********************************************************************************
4736 void IOService::OurChangeSetPowerState( void )
4738 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4739 fMachineState
= kIOPM_DriverThreadCallDone
;
4740 fDriverCallReason
= kDriverCallSetPowerState
;
4742 if (notifyControllingDriver() == false)
4743 notifyControllingDriverDone();
4746 //*********************************************************************************
4747 // [private] OurChangeWaitForPowerSettle
4749 // Our controlling driver has completed the power state change we initiated.
4750 // Wait for the driver specified settle time to expire.
4751 //*********************************************************************************
4753 void IOService::OurChangeWaitForPowerSettle( void )
4755 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4759 //*********************************************************************************
4760 // [private] OurChangeNotifyInterestedDriversDidChange
4762 // Power has settled on a power change we initiated. Here we notify
4763 // all our interested drivers post-change.
4764 //*********************************************************************************
4766 void IOService::OurChangeNotifyInterestedDriversDidChange( void )
4768 IOPMrootDomain
* rootDomain
;
4769 if ((rootDomain
= getPMRootDomain()) == this)
4771 rootDomain
->tracePoint( IS_POWER_DROP
?
4772 kIOPMTracePointSleepDidChangeInterests
:
4773 kIOPMTracePointWakeDidChangeInterests
);
4776 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4779 //*********************************************************************************
4780 // [private] OurChangeTellCapabilityDidChange
4782 // For root domain to notify capability power-change.
4783 //*********************************************************************************
4785 void IOService::OurChangeTellCapabilityDidChange( void )
4787 if (!IS_ROOT_DOMAIN
)
4788 return OurChangeFinish();
4790 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4791 kIOPMTracePointSleepCapabilityClients
:
4792 kIOPMTracePointWakeCapabilityClients
);
4794 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4797 //*********************************************************************************
4798 // [private] OurChangeFinish
4800 // Done with this self-induced power state change.
4801 //*********************************************************************************
4803 void IOService::OurChangeFinish( void )
4809 // MARK: Power Change Initiated by Parent
4811 //*********************************************************************************
4812 // [private] ParentChangeStart
4814 // Here we begin the processing of a power change initiated by our parent.
4815 //*********************************************************************************
4817 IOReturn
IOService::ParentChangeStart( void )
4819 PM_ASSERT_IN_GATE();
4820 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4822 // Root power domain has transitioned to its max power state
4823 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4824 (kIOPMDomainDidChange
| kIOPMRootChangeUp
))
4826 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4827 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
4833 // Power domain is forcing us to lower power
4834 if ( StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
) )
4836 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4838 // Tell apps and kernel clients
4839 fInitialPowerChange
= false;
4840 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4841 tellChangeDown1(fHeadNotePowerState
);
4842 return IOPMWillAckLater
;
4845 // Power domain is allowing us to raise power up to fHeadNotePowerState
4846 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4848 if ( StateOrder(fDesiredPowerState
) > StateOrder(fCurrentPowerState
) )
4850 if ( StateOrder(fDesiredPowerState
) < StateOrder(fHeadNotePowerState
) )
4852 // We power up, but not all the way
4853 fHeadNotePowerState
= fDesiredPowerState
;
4854 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4855 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4858 // We don't need to change
4859 fHeadNotePowerState
= fCurrentPowerState
;
4860 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4861 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4865 if ( fHeadNoteChangeFlags
& kIOPMDomainDidChange
)
4867 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4869 PM_ACTION_2(actionPowerChangeStart
,
4870 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4872 // Parent did change up - start our change up
4873 fInitialPowerChange
= false;
4874 ParentChangeTellCapabilityWillChange();
4875 return IOPMWillAckLater
;
4877 else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
)
4879 // No need to change power state, but broadcast change
4881 fMachineState
= kIOPM_SyncNotifyDidChange
;
4882 fDriverCallReason
= kDriverCallInformPreChange
;
4883 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4885 return IOPMWillAckLater
;
4889 // No power state change necessary
4890 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4893 return IOPMAckImplied
;
4896 //******************************************************************************
4897 // [private] ParentChangeRootChangeDown
4899 // Root domain has finished the transition to the system sleep state. And all
4900 // drivers in the power plane should have powered down. Cancel the idle timer,
4901 // and also reset the device desire for those drivers that don't want power
4902 // automatically restored on wake.
4903 //******************************************************************************
4905 void IOService::ParentChangeRootChangeDown( void )
4907 // Always stop the idle timer before root power down
4908 if (fIdleTimerPeriod
&& !fIdleTimerStopped
)
4910 fIdleTimerStopped
= true;
4911 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
4915 if (fResetPowerStateOnWake
)
4917 // Reset device desire down to the lowest power state.
4918 // Advisory tickle desire is intentionally untouched since
4919 // it has no effect until system is promoted to full wake.
4921 if (fDeviceDesire
!= kPowerStateZero
)
4923 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4924 computeDesiredState(kPowerStateZero
, true);
4925 requestDomainPower( fDesiredPowerState
);
4926 PM_LOG1("%s: tickle desire removed\n", fName
);
4929 // Invalidate tickle cache so the next tickle will issue a request
4930 IOLockLock(fActivityLock
);
4931 fDeviceWasActive
= false;
4932 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4933 IOLockUnlock(fActivityLock
);
4935 fIdleTimerMinPowerState
= kPowerStateZero
;
4937 else if (fAdvisoryTickleUsed
)
4939 // Less aggressive mechanism to accelerate idle timer expiration
4940 // before system sleep. May not always allow the driver to wake
4941 // up from system sleep in the min power state.
4945 bool dropTickleDesire
= false;
4947 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
4948 (fIdleTimerMinPowerState
== kPowerStateZero
) &&
4949 (fDeviceDesire
!= kPowerStateZero
))
4951 IOLockLock(fActivityLock
);
4953 if (!fDeviceWasActive
)
4955 // No tickles since the last idle timer expiration.
4956 // Safe to drop the device desire to zero.
4957 dropTickleDesire
= true;
4961 // Was tickled since the last idle timer expiration,
4962 // but not in the last minute.
4963 clock_get_uptime(&now
);
4964 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
4965 absolutetime_to_nanoseconds(now
, &nsec
);
4966 if (nsec
>= kNoTickleCancelWindow
)
4968 dropTickleDesire
= true;
4972 if (dropTickleDesire
)
4974 // Force the next tickle to raise power state
4975 fDeviceWasActive
= false;
4976 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4979 IOLockUnlock(fActivityLock
);
4982 if (dropTickleDesire
)
4984 // Advisory tickle desire is intentionally untouched since
4985 // it has no effect until system is promoted to full wake.
4987 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4988 computeDesiredState(kPowerStateZero
, true);
4989 PM_LOG1("%s: tickle desire dropped\n", fName
);
4994 //*********************************************************************************
4995 // [private] ParentChangeTellPriorityClientsPowerDown
4997 // All applications and kernel clients have acknowledged our intention to drop
4998 // power. Here we notify "priority" clients that we are lowering power.
4999 //*********************************************************************************
5001 void IOService::ParentChangeTellPriorityClientsPowerDown( void )
5003 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
5004 tellChangeDown2(fHeadNotePowerState
);
5007 //*********************************************************************************
5008 // [private] ParentChangeTellCapabilityWillChange
5010 // All (legacy) applications and kernel clients have acknowledged, extra stage for
5011 // root domain to notify apps and drivers about the system capability change.
5012 //*********************************************************************************
5014 void IOService::ParentChangeTellCapabilityWillChange( void )
5016 if (!IS_ROOT_DOMAIN
)
5017 return ParentChangeNotifyInterestedDriversWillChange();
5019 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
5022 //*********************************************************************************
5023 // [private] ParentChangeNotifyInterestedDriversWillChange
5025 // All applications and kernel clients have acknowledged our power state change.
5026 // Here we notify interested drivers pre-change.
5027 //*********************************************************************************
5029 void IOService::ParentChangeNotifyInterestedDriversWillChange( void )
5031 notifyAll( kIOPM_ParentChangeSetPowerState
);
5034 //*********************************************************************************
5035 // [private] ParentChangeSetPowerState
5037 // Instruct our controlling driver to program the hardware for the power state
5038 // change. Wait for async completions.
5039 //*********************************************************************************
5041 void IOService::ParentChangeSetPowerState( void )
5043 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
5044 fMachineState
= kIOPM_DriverThreadCallDone
;
5045 fDriverCallReason
= kDriverCallSetPowerState
;
5047 if (notifyControllingDriver() == false)
5048 notifyControllingDriverDone();
5051 //*********************************************************************************
5052 // [private] ParentChangeWaitForPowerSettle
5054 // Our controlling driver has completed the power state change initiated by our
5055 // parent. Wait for the driver specified settle time to expire.
5056 //*********************************************************************************
5058 void IOService::ParentChangeWaitForPowerSettle( void )
5060 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
5064 //*********************************************************************************
5065 // [private] ParentChangeNotifyInterestedDriversDidChange
5067 // Power has settled on a power change initiated by our parent. Here we notify
5068 // all our interested drivers post-change.
5069 //*********************************************************************************
5071 void IOService::ParentChangeNotifyInterestedDriversDidChange( void )
5073 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
5076 //*********************************************************************************
5077 // [private] ParentChangeTellCapabilityDidChange
5079 // For root domain to notify capability power-change.
5080 //*********************************************************************************
5082 void IOService::ParentChangeTellCapabilityDidChange( void )
5084 if (!IS_ROOT_DOMAIN
)
5085 return ParentChangeAcknowledgePowerChange();
5087 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
5090 //*********************************************************************************
5091 // [private] ParentAcknowledgePowerChange
5093 // Acknowledge our power parent that our power change is done.
5094 //*********************************************************************************
5096 void IOService::ParentChangeAcknowledgePowerChange( void )
5098 IORegistryEntry
* nub
;
5101 nub
= fHeadNoteParentConnection
;
5104 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
5107 parent
->acknowledgePowerChange((IOService
*)nub
);
5114 // MARK: Ack and Settle timers
5116 //*********************************************************************************
5117 // [private] settleTimerExpired
5119 // Power has settled after our last change. Notify interested parties that
5120 // there is a new power state.
5121 //*********************************************************************************
5123 void IOService::settleTimerExpired( void )
5126 gIOPMWorkQueue
->signalWorkAvailable();
5129 //*********************************************************************************
5130 // settle_timer_expired
5132 // Holds a retain while the settle timer callout is in flight.
5133 //*********************************************************************************
5136 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5138 IOService
* me
= (IOService
*) arg0
;
5140 if (gIOPMWorkLoop
&& gIOPMWorkQueue
)
5142 gIOPMWorkLoop
->runAction(
5143 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5149 //*********************************************************************************
5150 // [private] startSettleTimer
5152 // Calculate a power-settling delay in microseconds and start a timer.
5153 //*********************************************************************************
5155 void IOService::startSettleTimer( void )
5158 // This function is broken and serves no useful purpose since it never
5159 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5160 // yet it starts a delay timer. It appears no driver relies on a delay
5161 // from settleUpTime and settleDownTime in the power state table.
5163 AbsoluteTime deadline
;
5164 IOPMPowerStateIndex stateIndex
;
5165 IOPMPowerStateIndex currentOrder
, newOrder
, i
;
5166 uint32_t settleTime
= 0;
5169 PM_ASSERT_IN_GATE();
5171 currentOrder
= StateOrder(fCurrentPowerState
);
5172 newOrder
= StateOrder(fHeadNotePowerState
);
5177 if ( newOrder
< currentOrder
)
5179 while ( i
> newOrder
)
5181 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
5182 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleDownTime
;
5188 if ( newOrder
> currentOrder
)
5190 while ( i
< newOrder
)
5192 stateIndex
= fPowerStates
[i
+1].stateOrderToIndex
;
5193 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleUpTime
;
5201 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5202 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5203 if (pending
) release();
5208 //*********************************************************************************
5209 // [private] ackTimerTick
5211 // The acknowledgement timeout periodic timer has ticked.
5212 // If we are awaiting acks for a power change notification,
5213 // we decrement the timer word of each interested driver which hasn't acked.
5214 // If a timer word becomes zero, we pretend the driver aknowledged.
5215 // If we are waiting for the controlling driver to change the power
5216 // state of the hardware, we decrement its timer word, and if it becomes
5217 // zero, we pretend the driver acknowledged.
5219 // Returns true if the timer tick made it possible to advance to the next
5220 // machine state, false otherwise.
5221 //*********************************************************************************
5224 void IOService::ack_timer_ticked ( void )
5228 #endif /* !__LP64__ */
5230 bool IOService::ackTimerTick( void )
5232 IOPMinformee
* nextObject
;
5235 PM_ASSERT_IN_GATE();
5236 switch (fMachineState
) {
5237 case kIOPM_OurChangeWaitForPowerSettle
:
5238 case kIOPM_ParentChangeWaitForPowerSettle
:
5239 // are we waiting for controlling driver to acknowledge?
5240 if ( fDriverTimer
> 0 )
5242 // yes, decrement timer tick
5244 if ( fDriverTimer
== 0 )
5246 // controlling driver is tardy
5247 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5248 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
5249 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
5250 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5251 fName
, OBFUSCATE(this), fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5253 if (gIOKitDebug
& kIOLogDebugPower
)
5255 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5256 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5260 // Unblock state machine and pretend driver has acked.
5264 // still waiting, set timer again
5270 case kIOPM_NotifyChildrenStart
:
5271 // are we waiting for interested parties to acknowledge?
5272 if ( fHeadNotePendingAcks
!= 0 )
5274 // yes, go through the list of interested drivers
5275 nextObject
= fInterestedDrivers
->firstInList();
5276 // and check each one
5277 while ( nextObject
!= NULL
)
5279 if ( nextObject
->timer
> 0 )
5281 nextObject
->timer
--;
5282 // this one should have acked by now
5283 if ( nextObject
->timer
== 0 )
5285 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5286 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5287 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5288 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5289 nextObject
->whatObject
->getName(),
5290 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5291 OBFUSCATE(nextObject
->whatObject
), fName
, fCurrentPowerState
, fHeadNotePowerState
,
5294 // Pretend driver has acked.
5295 fHeadNotePendingAcks
--;
5298 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5301 // is that the last?
5302 if ( fHeadNotePendingAcks
== 0 )
5304 // yes, we can continue
5307 // no, set timer again
5313 // TODO: aggreggate this
5314 case kIOPM_OurChangeTellClientsPowerDown
:
5315 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
5316 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5317 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5318 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5319 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5320 case kIOPM_SyncTellClientsPowerDown
:
5321 case kIOPM_SyncTellPriorityClientsPowerDown
:
5322 case kIOPM_SyncNotifyWillChange
:
5323 case kIOPM_TellCapabilityChangeDone
:
5324 // apps didn't respond in time
5325 cleanClientResponses(true);
5326 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5327 // tardy equates to approval
5332 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5333 getName(), fMachineState
);
5339 //*********************************************************************************
5340 // [private] start_watchdog_timer
5341 //*********************************************************************************
5342 void IOService::start_watchdog_timer( void )
5344 AbsoluteTime deadline
;
5346 static int timeout
= -1;
5348 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5351 if (thread_call_isactive(fWatchdogTimer
)) return;
5352 if (timeout
== -1) {
5353 PE_parse_boot_argn("swd_timeout", &timeout
, sizeof(timeout
));
5356 timeout
= WATCHDOG_TIMER_PERIOD
;
5359 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5362 pending
= thread_call_enter_delayed(fWatchdogTimer
, deadline
);
5363 if (pending
) release();
5367 //*********************************************************************************
5368 // [private] stop_watchdog_timer
5369 // Returns true if watchdog was enabled and stopped now
5370 //*********************************************************************************
5372 bool IOService::stop_watchdog_timer( void )
5376 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5379 pending
= thread_call_cancel(fWatchdogTimer
);
5380 if (pending
) release();
5385 //*********************************************************************************
5386 // reset_watchdog_timer
5387 //*********************************************************************************
5389 void IOService::reset_watchdog_timer( void )
5391 if (stop_watchdog_timer())
5392 start_watchdog_timer();
5396 //*********************************************************************************
5397 // [static] watchdog_timer_expired
5399 // Inside PM work loop's gate.
5400 //*********************************************************************************
5403 IOService::watchdog_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5405 IOService
* me
= (IOService
*) arg0
;
5408 gIOPMWatchDogThread
= current_thread();
5409 getPMRootDomain()->sleepWakeDebugTrig(true);
5410 gIOPMWatchDogThread
= 0;
5411 thread_call_free(me
->fWatchdogTimer
);
5412 me
->fWatchdogTimer
= 0;
5418 //*********************************************************************************
5419 // [private] start_ack_timer
5420 //*********************************************************************************
5422 void IOService::start_ack_timer( void )
5424 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5427 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
5429 AbsoluteTime deadline
;
5432 clock_interval_to_deadline(interval
, scale
, &deadline
);
5435 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5436 if (pending
) release();
5438 // Stop watchdog if ack is delayed by more than a sec
5439 if (interval
* scale
> kSecondScale
) {
5440 stop_watchdog_timer();
5444 //*********************************************************************************
5445 // [private] stop_ack_timer
5446 //*********************************************************************************
5448 void IOService::stop_ack_timer( void )
5452 pending
= thread_call_cancel(fAckTimer
);
5453 if (pending
) release();
5455 start_watchdog_timer();
5458 //*********************************************************************************
5459 // [static] actionAckTimerExpired
5461 // Inside PM work loop's gate.
5462 //*********************************************************************************
5465 IOService::actionAckTimerExpired(
5467 void * arg0
, void * arg1
,
5468 void * arg2
, void * arg3
)
5470 IOService
* me
= (IOService
*) target
;
5473 // done will be true if the timer tick unblocks the machine state,
5474 // otherwise no need to signal the work loop.
5476 done
= me
->ackTimerTick();
5477 if (done
&& gIOPMWorkQueue
)
5479 gIOPMWorkQueue
->signalWorkAvailable();
5480 me
->start_watchdog_timer();
5483 return kIOReturnSuccess
;
5486 //*********************************************************************************
5487 // ack_timer_expired
5489 // Thread call function. Holds a retain while the callout is in flight.
5490 //*********************************************************************************
5493 IOService::ack_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5495 IOService
* me
= (IOService
*) arg0
;
5499 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5504 //*********************************************************************************
5505 // [private] start_spindump_timer
5506 //*********************************************************************************
5508 void IOService::start_spindump_timer( const char * delay_type
)
5510 AbsoluteTime deadline
;
5513 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
))
5516 if (gIOSpinDumpKextName
[0] == '\0' &&
5517 !(PE_parse_boot_argn("swd_kext_name", &gIOSpinDumpKextName
,
5518 sizeof(gIOSpinDumpKextName
))))
5523 if (strncmp(gIOSpinDumpKextName
, fName
, sizeof(gIOSpinDumpKextName
)) != 0)
5526 if (gIOSpinDumpDelayType
[0] == '\0' &&
5527 !(PE_parse_boot_argn("swd_delay_type", &gIOSpinDumpDelayType
,
5528 sizeof(gIOSpinDumpDelayType
))))
5530 strncpy(gIOSpinDumpDelayType
, "SetState", sizeof(gIOSpinDumpDelayType
));
5533 if (strncmp(delay_type
, gIOSpinDumpDelayType
, sizeof(gIOSpinDumpDelayType
)) != 0)
5536 if (gIOSpinDumpDelayDuration
== 0 &&
5537 !(PE_parse_boot_argn("swd_delay_duration", &gIOSpinDumpDelayDuration
,
5538 sizeof(gIOSpinDumpDelayDuration
))))
5540 gIOSpinDumpDelayDuration
= 300;
5543 clock_interval_to_deadline(gIOSpinDumpDelayDuration
, kMillisecondScale
, &deadline
);
5546 pending
= thread_call_enter_delayed(fSpinDumpTimer
, deadline
);
5547 if (pending
) release();
5550 //*********************************************************************************
5551 // [private] stop_spindump_timer
5552 //*********************************************************************************
5554 void IOService::stop_spindump_timer( void )
5558 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
))
5561 pending
= thread_call_cancel(fSpinDumpTimer
);
5562 if (pending
) release();
5566 //*********************************************************************************
5567 // [static] actionSpinDumpTimerExpired
5569 // Inside PM work loop's gate.
5570 //*********************************************************************************
5573 IOService::actionSpinDumpTimerExpired(
5575 void * arg0
, void * arg1
,
5576 void * arg2
, void * arg3
)
5578 getPMRootDomain()->takeStackshot(false, false, true);
5580 return kIOReturnSuccess
;
5583 //*********************************************************************************
5584 // spindump_timer_expired
5586 // Thread call function. Holds a retain while the callout is in flight.
5587 //*********************************************************************************
5590 IOService::spindump_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5592 IOService
* me
= (IOService
*) arg0
;
5596 gIOPMWorkLoop
->runAction(&actionSpinDumpTimerExpired
, me
);
5602 // MARK: Client Messaging
5604 //*********************************************************************************
5605 // [private] tellSystemCapabilityChange
5606 //*********************************************************************************
5608 void IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5611 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5612 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5616 // Notify app first on pre-change.
5617 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5621 // Notify kernel clients first on post-change.
5622 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5625 tellClientsWithResponse( fOutOfBandMessage
);
5628 //*********************************************************************************
5629 // [public] askChangeDown
5631 // Ask registered applications and kernel clients if we can change to a lower
5634 // Subclass can override this to send a different message type. Parameter is
5635 // the destination state number.
5637 // Return true if we don't have to wait for acknowledgements
5638 //*********************************************************************************
5640 bool IOService::askChangeDown( unsigned long stateNum
)
5642 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5645 //*********************************************************************************
5646 // [private] tellChangeDown1
5648 // Notify registered applications and kernel clients that we are definitely
5651 // Return true if we don't have to wait for acknowledgements
5652 //*********************************************************************************
5654 bool IOService::tellChangeDown1( unsigned long stateNum
)
5656 fOutOfBandParameter
= kNotifyApps
;
5657 return tellChangeDown(stateNum
);
5660 //*********************************************************************************
5661 // [private] tellChangeDown2
5663 // Notify priority clients that we are definitely dropping power.
5665 // Return true if we don't have to wait for acknowledgements
5666 //*********************************************************************************
5668 bool IOService::tellChangeDown2( unsigned long stateNum
)
5670 fOutOfBandParameter
= kNotifyPriority
;
5671 return tellChangeDown(stateNum
);
5674 //*********************************************************************************
5675 // [public] tellChangeDown
5677 // Notify registered applications and kernel clients that we are definitely
5680 // Subclass can override this to send a different message type. Parameter is
5681 // the destination state number.
5683 // Return true if we don't have to wait for acknowledgements
5684 //*********************************************************************************
5686 bool IOService::tellChangeDown( unsigned long stateNum
)
5688 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5691 //*********************************************************************************
5692 // cleanClientResponses
5694 //*********************************************************************************
5696 static void logAppTimeouts( OSObject
* object
, void * arg
)
5698 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5700 unsigned int clientIndex
;
5704 if (OSDynamicCast(_IOServiceInterestNotifier
, object
))
5706 // Discover the 'counter' value or index assigned to this client
5707 // when it was notified, by searching for the array index of the
5708 // client in an array holding the cached interested clients.
5710 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5712 if ((clientIndex
!= (unsigned int) -1) &&
5713 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5714 (flag
!= kOSBooleanTrue
))
5716 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5720 pid
= clientID
->unsigned32BitValue();
5721 proc_name(pid
, name
, sizeof(name
));
5722 clientID
->release();
5725 PM_ERROR(context
->errorLog
, pid
, name
);
5727 // TODO: record message type if possible
5728 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5729 gIOPMStatsApplicationResponseTimedOut
,
5730 name
, 0, (30*1000), pid
, object
);
5736 void IOService::cleanClientResponses( bool logErrors
)
5738 if (logErrors
&& fResponseArray
)
5740 switch ( fOutOfBandParameter
) {
5742 case kNotifyCapabilityChangeApps
:
5743 if (fNotifyClientArray
)
5745 IOPMInterestContext context
;
5747 context
.responseArray
= fResponseArray
;
5748 context
.notifyClients
= fNotifyClientArray
;
5749 context
.serialNumber
= fSerialNumber
;
5750 context
.messageType
= kIOMessageCopyClientID
;
5751 context
.notifyType
= kNotifyApps
;
5752 context
.isPreChange
= fIsPreChange
;
5753 context
.enableTracing
= false;
5755 context
.maxTimeRequested
= 0;
5756 context
.stateNumber
= fHeadNotePowerState
;
5757 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5758 context
.changeFlags
= fHeadNoteChangeFlags
;
5759 context
.errorLog
= "PM notification timeout (pid %d, %s)\n";
5761 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5766 // kNotifyPriority, kNotifyCapabilityChangePriority
5767 // TODO: identify the priority client that has not acked
5768 PM_ERROR("PM priority notification timeout\n");
5769 if (gIOKitDebug
& kIOLogDebugPower
)
5771 panic("PM priority notification timeout");
5779 fResponseArray
->release();
5780 fResponseArray
= NULL
;
5782 if (fNotifyClientArray
)
5784 fNotifyClientArray
->release();
5785 fNotifyClientArray
= NULL
;
5789 //*********************************************************************************
5790 // [protected] tellClientsWithResponse
5792 // Notify registered applications and kernel clients that we are definitely
5795 // Return true if we don't have to wait for acknowledgements
5796 //*********************************************************************************
5798 bool IOService::tellClientsWithResponse( int messageType
)
5800 IOPMInterestContext context
;
5801 bool isRootDomain
= IS_ROOT_DOMAIN
;
5802 uint32_t maxTimeOut
= kMaxTimeRequested
;
5804 PM_ASSERT_IN_GATE();
5805 assert( fResponseArray
== NULL
);
5806 assert( fNotifyClientArray
== NULL
);
5808 if(messageType
== (int)kIOPMMessageLastCallBeforeSleep
)
5809 RD_LOG("tellClientsWithResponse( kIOPMMessageLastCallBeforeSleep, %d )\n",
5810 fOutOfBandParameter
);
5812 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5813 getIOMessageString(messageType
), fOutOfBandParameter
);
5815 fResponseArray
= OSArray::withCapacity( 1 );
5816 if (!fResponseArray
)
5819 fResponseArray
->setCapacityIncrement(8);
5820 if (++fSerialNumber
== 0)
5823 context
.responseArray
= fResponseArray
;
5824 context
.notifyClients
= 0;
5825 context
.serialNumber
= fSerialNumber
;
5826 context
.messageType
= messageType
;
5827 context
.notifyType
= fOutOfBandParameter
;
5828 context
.isPreChange
= fIsPreChange
;
5829 context
.enableTracing
= false;
5831 context
.maxTimeRequested
= 0;
5832 context
.stateNumber
= fHeadNotePowerState
;
5833 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5834 context
.changeFlags
= fHeadNoteChangeFlags
;
5835 context
.messageFilter
= (isRootDomain
) ?
5836 OSMemberFunctionCast(
5839 &IOPMrootDomain::systemMessageFilter
) : 0;
5841 switch ( fOutOfBandParameter
) {
5843 applyToInterested( gIOAppPowerStateInterest
,
5844 pmTellAppWithResponse
, (void *) &context
);
5847 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5848 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
) &&
5849 (context
.messageType
!= kIOPMMessageLastCallBeforeSleep
))
5851 // Notify capability app for tellChangeDown1()
5852 // but not for askChangeDown().
5853 context
.notifyType
= kNotifyCapabilityChangeApps
;
5854 context
.messageType
= kIOMessageSystemCapabilityChange
;
5855 applyToInterested( gIOAppPowerStateInterest
,
5856 pmTellCapabilityAppWithResponse
, (void *) &context
);
5857 context
.notifyType
= fOutOfBandParameter
;
5858 context
.messageType
= messageType
;
5860 if(context
.messageType
== kIOMessageCanSystemSleep
)
5862 maxTimeOut
= kCanSleepMaxTimeReq
;
5863 if(gCanSleepTimeout
)
5865 maxTimeOut
= (gCanSleepTimeout
*us_per_s
);
5868 context
.maxTimeRequested
= maxTimeOut
;
5869 applyToInterested( gIOGeneralInterest
,
5870 pmTellClientWithResponse
, (void *) &context
);
5872 fNotifyClientArray
= context
.notifyClients
;
5875 case kNotifyPriority
:
5876 context
.enableTracing
= isRootDomain
;
5877 applyToInterested( gIOPriorityPowerStateInterest
,
5878 pmTellClientWithResponse
, (void *) &context
);
5882 // Notify capability clients for tellChangeDown2().
5883 context
.notifyType
= kNotifyCapabilityChangePriority
;
5884 context
.messageType
= kIOMessageSystemCapabilityChange
;
5885 applyToInterested( gIOPriorityPowerStateInterest
,
5886 pmTellCapabilityClientWithResponse
, (void *) &context
);
5890 case kNotifyCapabilityChangeApps
:
5891 applyToInterested( gIOAppPowerStateInterest
,
5892 pmTellCapabilityAppWithResponse
, (void *) &context
);
5893 fNotifyClientArray
= context
.notifyClients
;
5894 if(context
.messageType
== kIOMessageCanSystemSleep
)
5896 maxTimeOut
= kCanSleepMaxTimeReq
;
5897 if(gCanSleepTimeout
)
5899 maxTimeOut
= (gCanSleepTimeout
*us_per_s
);
5902 context
.maxTimeRequested
= maxTimeOut
;
5905 case kNotifyCapabilityChangePriority
:
5906 applyToInterested( gIOPriorityPowerStateInterest
,
5907 pmTellCapabilityClientWithResponse
, (void *) &context
);
5911 // do we have to wait for somebody?
5912 if ( !checkForDone() )
5914 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5915 if (context
.enableTracing
)
5916 getPMRootDomain()->traceDetail( context
.maxTimeRequested
/ 1000 );
5917 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5922 // everybody responded
5925 fResponseArray
->release();
5926 fResponseArray
= NULL
;
5928 if (fNotifyClientArray
)
5930 fNotifyClientArray
->release();
5931 fNotifyClientArray
= NULL
;
5937 //*********************************************************************************
5938 // [static private] pmTellAppWithResponse
5940 // We send a message to an application, and we expect a response, so we compute a
5941 // cookie we can identify the response with.
5942 //*********************************************************************************
5944 void IOService::pmTellAppWithResponse( OSObject
* object
, void * arg
)
5946 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5947 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5948 uint32_t msgIndex
, msgRef
, msgType
;
5949 OSNumber
*clientID
= NULL
;
5951 boolean_t proc_suspended
= FALSE
;
5952 OSObject
* waitForReply
= kOSBooleanTrue
;
5953 #if LOG_APP_RESPONSE_TIMES
5957 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5960 if (context
->us
== getPMRootDomain())
5962 if ((clientID
= copyClientIDForNotification(object
, context
)))
5964 uint32_t clientPID
= clientID
->unsigned32BitValue();
5965 clientID
->release();
5966 proc
= proc_find(clientPID
);
5970 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
5975 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
5982 if (context
->messageFilter
&&
5983 !context
->messageFilter(context
->us
, object
, context
, 0, &waitForReply
))
5985 if (kIOLogDebugPower
& gIOKitDebug
)
5987 logClientIDForNotification(object
, context
, "DROP App");
5992 // Create client array (for tracking purposes) only if the service
5993 // has app clients. Usually only root domain does.
5994 if (0 == context
->notifyClients
)
5995 context
->notifyClients
= OSArray::withCapacity( 32 );
5997 msgType
= context
->messageType
;
5998 msgIndex
= context
->responseArray
->getCount();
5999 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6001 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6002 if (kIOLogDebugPower
& gIOKitDebug
)
6004 logClientIDForNotification(object
, context
, "MESG App");
6007 if (waitForReply
== kOSBooleanTrue
)
6009 #if LOG_APP_RESPONSE_TIMES
6011 clock_get_uptime(&now
);
6012 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6015 context
->responseArray
->setObject(msgIndex
, num
);
6020 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6024 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6025 if (kIOLogDebugPower
& gIOKitDebug
)
6027 logClientIDForNotification(object
, context
, "App response ignored");
6031 if (context
->notifyClients
)
6032 context
->notifyClients
->setObject(msgIndex
, object
);
6034 context
->us
->messageClient(msgType
, object
, (void *)(uintptr_t) msgRef
);
6037 //*********************************************************************************
6038 // [static private] pmTellClientWithResponse
6040 // We send a message to an in-kernel client, and we expect a response,
6041 // so we compute a cookie we can identify the response with.
6042 //*********************************************************************************
6044 void IOService::pmTellClientWithResponse( OSObject
* object
, void * arg
)
6046 IOPowerStateChangeNotification notify
;
6047 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6048 OSObject
* replied
= kOSBooleanTrue
;
6049 _IOServiceInterestNotifier
* notifier
;
6050 uint32_t msgIndex
, msgRef
, msgType
;
6053 if (context
->messageFilter
&&
6054 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6056 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6057 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6059 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6060 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6061 context
->us
->getName(),
6062 getIOMessageString(context
->messageType
),
6063 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6068 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6069 msgType
= context
->messageType
;
6070 msgIndex
= context
->responseArray
->getCount();
6071 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6073 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6074 if (gIOKitDebug
& kIOLogPower
) {
6075 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6076 if (OSDynamicCast(IOService
, object
)) {
6077 const char *who
= ((IOService
*) object
)->getName();
6078 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6080 else if (notifier
) {
6081 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6084 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6086 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6087 context
->us
->getName(),
6088 getIOMessageString(msgType
),
6089 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6092 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
6093 notify
.returnValue
= 0;
6094 notify
.stateNumber
= context
->stateNumber
;
6095 notify
.stateFlags
= context
->stateFlags
;
6097 if (context
->enableTracing
&& (notifier
!= 0))
6099 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
6100 ((msgType
& 0xfff) << 12) |
6101 (((uintptr_t) notifier
->handler
) & 0xfff);
6102 getPMRootDomain()->traceDetail( detail
);
6105 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
6107 if (kIOReturnSuccess
== retCode
)
6109 if (0 == notify
.returnValue
) {
6110 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6112 replied
= kOSBooleanFalse
;
6113 if ( notify
.returnValue
> context
->maxTimeRequested
)
6115 if (notify
.returnValue
> kPriorityClientMaxWait
)
6117 context
->maxTimeRequested
= kPriorityClientMaxWait
;
6118 PM_ERROR("%s: client %p returned %llu for %s\n",
6119 context
->us
->getName(),
6120 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6121 (uint64_t) notify
.returnValue
,
6122 getIOMessageString(msgType
));
6125 context
->maxTimeRequested
= notify
.returnValue
;
6129 // not a client of ours
6130 // so we won't be waiting for response
6131 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6134 context
->responseArray
->setObject(msgIndex
, replied
);
6137 //*********************************************************************************
6138 // [static private] pmTellCapabilityAppWithResponse
6139 //*********************************************************************************
6141 void IOService::pmTellCapabilityAppWithResponse( OSObject
* object
, void * arg
)
6143 IOPMSystemCapabilityChangeParameters msgArg
;
6144 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6145 OSObject
* replied
= kOSBooleanTrue
;
6146 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6147 uint32_t msgIndex
, msgRef
, msgType
;
6148 #if LOG_APP_RESPONSE_TIMES
6152 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
6155 memset(&msgArg
, 0, sizeof(msgArg
));
6156 if (context
->messageFilter
&&
6157 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
))
6162 // Create client array (for tracking purposes) only if the service
6163 // has app clients. Usually only root domain does.
6164 if (0 == context
->notifyClients
)
6165 context
->notifyClients
= OSArray::withCapacity( 32 );
6167 msgType
= context
->messageType
;
6168 msgIndex
= context
->responseArray
->getCount();
6169 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6171 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6172 if (kIOLogDebugPower
& gIOKitDebug
)
6174 // Log client pid/name and client array index.
6175 OSNumber
* clientID
= NULL
;
6176 OSString
* clientIDString
= NULL
;;
6177 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6179 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6182 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
6183 context
->us
->getName(),
6184 msgIndex
, getIOMessageString(msgType
),
6185 (replied
!= kOSBooleanTrue
),
6186 clientIDString
? clientIDString
->getCStringNoCopy() : "");
6187 if (clientID
) clientID
->release();
6188 if (clientIDString
) clientIDString
->release();
6191 msgArg
.notifyRef
= msgRef
;
6192 msgArg
.maxWaitForReply
= 0;
6194 if (replied
== kOSBooleanTrue
)
6196 msgArg
.notifyRef
= 0;
6197 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6198 if (context
->notifyClients
)
6199 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
6203 #if LOG_APP_RESPONSE_TIMES
6205 clock_get_uptime(&now
);
6206 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6209 context
->responseArray
->setObject(msgIndex
, num
);
6214 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6216 if (context
->notifyClients
)
6217 context
->notifyClients
->setObject(msgIndex
, object
);
6220 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6223 //*********************************************************************************
6224 // [static private] pmTellCapabilityClientWithResponse
6225 //*********************************************************************************
6227 void IOService::pmTellCapabilityClientWithResponse(
6228 OSObject
* object
, void * arg
)
6230 IOPMSystemCapabilityChangeParameters msgArg
;
6231 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6232 OSObject
* replied
= kOSBooleanTrue
;
6233 _IOServiceInterestNotifier
* notifier
;
6234 uint32_t msgIndex
, msgRef
, msgType
;
6237 memset(&msgArg
, 0, sizeof(msgArg
));
6238 if (context
->messageFilter
&&
6239 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, 0))
6241 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6242 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6244 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6245 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6246 context
->us
->getName(),
6247 getIOMessageString(context
->messageType
),
6248 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6253 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6254 msgType
= context
->messageType
;
6255 msgIndex
= context
->responseArray
->getCount();
6256 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6258 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6259 if (gIOKitDebug
& kIOLogPower
) {
6260 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6261 if (OSDynamicCast(IOService
, object
)) {
6262 const char *who
= ((IOService
*) object
)->getName();
6263 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6265 else if (notifier
) {
6266 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6269 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6271 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6272 context
->us
->getName(),
6273 getIOMessageString(msgType
),
6274 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6277 msgArg
.notifyRef
= msgRef
;
6278 msgArg
.maxWaitForReply
= 0;
6280 if (context
->enableTracing
&& (notifier
!= 0))
6282 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
6283 ((msgType
& 0xfff) << 12) |
6284 (((uintptr_t) notifier
->handler
) & 0xfff);
6285 getPMRootDomain()->traceDetail( detail
);
6288 retCode
= context
->us
->messageClient(
6289 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6291 if ( kIOReturnSuccess
== retCode
)
6293 if ( 0 == msgArg
.maxWaitForReply
)
6295 // client doesn't want time to respond
6296 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6300 replied
= kOSBooleanFalse
;
6301 if ( msgArg
.maxWaitForReply
> context
->maxTimeRequested
)
6303 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
)
6305 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
6306 PM_ERROR("%s: client %p returned %u for %s\n",
6307 context
->us
->getName(),
6308 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6309 msgArg
.maxWaitForReply
,
6310 getIOMessageString(msgType
));
6313 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6319 // not a client of ours
6320 // so we won't be waiting for response
6321 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6324 context
->responseArray
->setObject(msgIndex
, replied
);
6327 //*********************************************************************************
6328 // [public] tellNoChangeDown
6330 // Notify registered applications and kernel clients that we are not
6333 // Subclass can override this to send a different message type. Parameter is
6334 // the aborted destination state number.
6335 //*********************************************************************************
6337 void IOService::tellNoChangeDown( unsigned long )
6339 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6342 //*********************************************************************************
6343 // [public] tellChangeUp
6345 // Notify registered applications and kernel clients that we are raising power.
6347 // Subclass can override this to send a different message type. Parameter is
6348 // the aborted destination state number.
6349 //*********************************************************************************
6351 void IOService::tellChangeUp( unsigned long )
6353 return tellClients( kIOMessageDeviceHasPoweredOn
);
6356 //*********************************************************************************
6357 // [protected] tellClients
6359 // Notify registered applications and kernel clients of something.
6360 //*********************************************************************************
6362 void IOService::tellClients( int messageType
)
6364 IOPMInterestContext context
;
6366 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6368 memset(&context
, 0, sizeof(context
));
6369 context
.messageType
= messageType
;
6370 context
.isPreChange
= fIsPreChange
;
6372 context
.stateNumber
= fHeadNotePowerState
;
6373 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6374 context
.changeFlags
= fHeadNoteChangeFlags
;
6375 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6376 OSMemberFunctionCast(
6379 &IOPMrootDomain::systemMessageFilter
) : 0;
6381 context
.notifyType
= kNotifyPriority
;
6382 applyToInterested( gIOPriorityPowerStateInterest
,
6383 tellKernelClientApplier
, (void *) &context
);
6385 context
.notifyType
= kNotifyApps
;
6386 applyToInterested( gIOAppPowerStateInterest
,
6387 tellAppClientApplier
, (void *) &context
);
6389 applyToInterested( gIOGeneralInterest
,
6390 tellKernelClientApplier
, (void *) &context
);
6393 //*********************************************************************************
6394 // [private] tellKernelClientApplier
6396 // Message a kernel client.
6397 //*********************************************************************************
6399 static void tellKernelClientApplier( OSObject
* object
, void * arg
)
6401 IOPowerStateChangeNotification notify
;
6402 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6404 if (context
->messageFilter
&&
6405 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6407 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6408 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6410 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6411 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6412 context
->us
->getName(),
6413 IOService::getIOMessageString(context
->messageType
),
6414 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6419 notify
.powerRef
= (void *) 0;
6420 notify
.returnValue
= 0;
6421 notify
.stateNumber
= context
->stateNumber
;
6422 notify
.stateFlags
= context
->stateFlags
;
6424 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6426 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6427 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6429 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6430 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6431 context
->us
->getName(),
6432 IOService::getIOMessageString(context
->messageType
),
6433 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6437 static OSNumber
* copyClientIDForNotification(
6439 IOPMInterestContext
*context
)
6441 OSNumber
*clientID
= NULL
;
6442 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6446 static void logClientIDForNotification(
6448 IOPMInterestContext
*context
,
6449 const char *logString
)
6451 OSString
*logClientID
= NULL
;
6452 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6457 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6459 PM_LOG("%s %s %s, %s\n",
6460 context
->us
->getName(), logString
,
6461 IOService::getIOMessageString(context
->messageType
),
6462 logClientID
? logClientID
->getCStringNoCopy() : "");
6465 logClientID
->release();
6469 clientID
->release();
6474 static void tellAppClientApplier( OSObject
* object
, void * arg
)
6476 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6477 OSNumber
* clientID
= NULL
;
6479 boolean_t proc_suspended
= FALSE
;
6481 if (context
->us
== IOService::getPMRootDomain())
6483 if ((clientID
= copyClientIDForNotification(object
, context
)))
6485 uint32_t clientPID
= clientID
->unsigned32BitValue();
6486 clientID
->release();
6487 proc
= proc_find(clientPID
);
6491 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6496 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6503 if (context
->messageFilter
&&
6504 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6506 if (kIOLogDebugPower
& gIOKitDebug
)
6508 logClientIDForNotification(object
, context
, "DROP App");
6513 if (kIOLogDebugPower
& gIOKitDebug
)
6515 logClientIDForNotification(object
, context
, "MESG App");
6518 context
->us
->messageClient(context
->messageType
, object
, 0);
6521 //*********************************************************************************
6522 // [private] checkForDone
6523 //*********************************************************************************
6525 bool IOService::checkForDone( void )
6530 if (fResponseArray
== NULL
) {
6534 for (i
= 0; ; i
++) {
6535 theFlag
= fResponseArray
->getObject(i
);
6537 if (NULL
== theFlag
) {
6541 if (kOSBooleanTrue
!= theFlag
) {
6548 //*********************************************************************************
6549 // [public] responseValid
6550 //*********************************************************************************
6552 bool IOService::responseValid( uint32_t refcon
, int pid
)
6554 UInt16 serialComponent
;
6555 UInt16 ordinalComponent
;
6557 OSObject
*object
= 0;
6559 serialComponent
= (refcon
>> 16) & 0xFFFF;
6560 ordinalComponent
= (refcon
& 0xFFFF);
6562 if ( serialComponent
!= fSerialNumber
)
6567 if ( fResponseArray
== NULL
)
6572 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6579 if (fNotifyClientArray
)
6580 object
= fNotifyClientArray
->getObject(ordinalComponent
);
6583 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
6585 #if LOG_APP_RESPONSE_TIMES
6592 proc_name(pid
, name
, sizeof(name
));
6593 clock_get_uptime(&now
);
6594 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6595 SUB_ABSOLUTETIME(&now
, &start
);
6596 absolutetime_to_nanoseconds(now
, &nsec
);
6598 if (kIOLogDebugPower
& gIOKitDebug
)
6600 PM_LOG("Ack(%u) %u ms\n",
6601 (uint32_t) ordinalComponent
,
6606 if (nsec
> LOG_APP_RESPONSE_TIMES
)
6608 IOLog("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec
),
6612 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
6614 // TODO: populate the messageType argument
6615 getPMRootDomain()->pmStatsRecordApplicationResponse(
6616 gIOPMStatsApplicationResponseSlow
,
6617 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6621 getPMRootDomain()->pmStatsRecordApplicationResponse(
6622 gIOPMStatsApplicationResponsePrompt
,
6623 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6627 theFlag
= kOSBooleanFalse
;
6630 getPMRootDomain()->pmStatsRecordApplicationResponse(
6631 gIOPMStatsApplicationResponsePrompt
,
6632 0, 0, 0, pid
, object
);
6636 if ( kOSBooleanFalse
== theFlag
)
6638 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6644 //*********************************************************************************
6645 // [public] allowPowerChange
6647 // Our power state is about to lower, and we have notified applications
6648 // and kernel clients, and one of them has acknowledged. If this is the last to do
6649 // so, and all acknowledgements are positive, we continue with the power change.
6650 //*********************************************************************************
6652 IOReturn
IOService::allowPowerChange( unsigned long refcon
)
6654 IOPMRequest
* request
;
6659 return kIOReturnSuccess
;
6662 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6664 return kIOReturnNoMemory
;
6666 request
->fArg0
= (void *) refcon
;
6667 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6668 request
->fArg2
= (void *) 0;
6669 submitPMRequest( request
);
6671 return kIOReturnSuccess
;
6675 IOReturn
IOService::serializedAllowPowerChange2( unsigned long refcon
)
6677 // [deprecated] public
6678 return kIOReturnUnsupported
;
6680 #endif /* !__LP64__ */
6682 //*********************************************************************************
6683 // [public] cancelPowerChange
6685 // Our power state is about to lower, and we have notified applications
6686 // and kernel clients, and one of them has vetoed the change. If this is the last
6687 // client to respond, we abandon the power change.
6688 //*********************************************************************************
6690 IOReturn
IOService::cancelPowerChange( unsigned long refcon
)
6692 IOPMRequest
* request
;
6694 pid_t pid
= proc_selfpid();
6699 return kIOReturnSuccess
;
6703 proc_name(pid
, name
, sizeof(name
));
6704 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid
, name
);
6706 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6709 return kIOReturnNoMemory
;
6712 request
->fArg0
= (void *) refcon
;
6713 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6714 request
->fArg2
= (void *) OSString::withCString(name
);
6715 submitPMRequest( request
);
6717 return kIOReturnSuccess
;
6721 IOReturn
IOService::serializedCancelPowerChange2( unsigned long refcon
)
6723 // [deprecated] public
6724 return kIOReturnUnsupported
;
6727 //*********************************************************************************
6728 // PM_Clamp_Timer_Expired
6730 // called when clamp timer expires...set power state to 0.
6731 //*********************************************************************************
6733 void IOService::PM_Clamp_Timer_Expired( void )
6737 //*********************************************************************************
6740 // Set to highest available power state for a minimum of duration milliseconds
6741 //*********************************************************************************
6743 void IOService::clampPowerOn( unsigned long duration
)
6746 #endif /* !__LP64__ */
6748 //*********************************************************************************
6749 // configurePowerStateReport
6751 // Configures the IOStateReport for kPMPowerStateChannel
6752 //*********************************************************************************
6753 IOReturn
IOService::configurePowerStatesReport( IOReportConfigureAction action
, void *result
)
6756 IOReturn rc
= kIOReturnSuccess
;
6762 return kIOReturnUnsupported
;
6764 if (!fNumberOfPowerStates
)
6765 return kIOReturnSuccess
; // For drivers which are in power plane, but haven't called registerPowerDriver()
6770 case kIOReportEnable
:
6776 reportSize
= STATEREPORT_BUFSIZE(fNumberOfPowerStates
);
6777 fReportBuf
= IOMalloc(reportSize
);
6779 rc
= kIOReturnNoMemory
;
6782 memset(fReportBuf
, 0, reportSize
);
6784 STATEREPORT_INIT(fNumberOfPowerStates
, fReportBuf
, reportSize
,
6785 getRegistryEntryID(), kPMPowerStatesChID
, kIOReportCategoryPower
);
6787 for (i
= 0; i
< fNumberOfPowerStates
; i
++) {
6790 if (fPowerStates
[i
].capabilityFlags
& kIOPMPowerOn
)
6791 bits
|= kPMReportPowerOn
;
6792 if (fPowerStates
[i
].capabilityFlags
& kIOPMDeviceUsable
)
6793 bits
|= kPMReportDeviceUsable
;
6794 if (fPowerStates
[i
].capabilityFlags
& kIOPMLowPower
)
6795 bits
|= kPMReportLowPower
;
6797 STATEREPORT_SETSTATEID(fReportBuf
, i
, ((bits
& 0xff) << 8) |
6798 ((StateOrder(fMaxPowerState
) & 0xf) << 4) | (StateOrder(i
) & 0xf));
6800 ts
= mach_absolute_time();
6801 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
6804 case kIOReportDisable
:
6805 if (fReportClientCnt
== 0) {
6806 rc
= kIOReturnBadArgument
;
6809 if (fReportClientCnt
== 1)
6811 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
6817 case kIOReportGetDimensions
:
6819 STATEREPORT_UPDATERES(fReportBuf
, kIOReportGetDimensions
, result
);
6828 //*********************************************************************************
6829 // updatePowerStateReport
6831 // Updates the IOStateReport for kPMPowerStateChannel
6832 //*********************************************************************************
6833 IOReturn
IOService::updatePowerStatesReport( IOReportConfigureAction action
, void *result
, void *destination
)
6838 IOReturn rc
= kIOReturnSuccess
;
6839 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6843 return kIOReturnUnsupported
;
6844 if (!fNumberOfPowerStates
)
6845 return kIOReturnSuccess
;
6847 if ( !result
|| !dest
) return kIOReturnBadArgument
;
6851 case kIOReportCopyChannelData
:
6852 if ( !fReportBuf
) {
6853 rc
= kIOReturnNotOpen
;
6857 ts
= mach_absolute_time();
6858 STATEREPORT_UPDATEPREP(fReportBuf
, ts
, data2cpy
, size2cpy
);
6859 if (size2cpy
> (dest
->getCapacity() - dest
->getLength()) ) {
6860 rc
= kIOReturnOverrun
;
6864 STATEREPORT_UPDATERES(fReportBuf
, kIOReportCopyChannelData
, result
);
6865 dest
->appendBytes(data2cpy
, size2cpy
);
6878 //*********************************************************************************
6879 // configureSimplePowerReport
6881 // Configures the IOSimpleReport for given channel id
6882 //*********************************************************************************
6883 IOReturn
IOService::configureSimplePowerReport(IOReportConfigureAction action
, void *result
)
6886 IOReturn rc
= kIOReturnSuccess
;
6889 return kIOReturnUnsupported
;
6891 if ( !fNumberOfPowerStates
)
6896 case kIOReportEnable
:
6897 case kIOReportDisable
:
6900 case kIOReportGetDimensions
:
6901 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
6909 //*********************************************************************************
6910 // updateSimplePowerReport
6912 // Updates the IOSimpleReport for the given chanel id
6913 //*********************************************************************************
6914 IOReturn
IOService::updateSimplePowerReport( IOReportConfigureAction action
, void *result
, void *destination
)
6918 uint64_t buf
[SIMPLEREPORT_BUFSIZE
/sizeof(uint64_t)+1]; // Force a 8-byte alignment
6919 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6920 IOReturn rc
= kIOReturnSuccess
;
6925 return kIOReturnUnsupported
;
6926 if ( !result
|| !dest
) return kIOReturnBadArgument
;
6928 if ( !fNumberOfPowerStates
)
6933 case kIOReportCopyChannelData
:
6935 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), kPMCurrStateChID
, kIOReportCategoryPower
);
6937 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMPowerOn
)
6938 bits
|= kPMReportPowerOn
;
6939 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMDeviceUsable
)
6940 bits
|= kPMReportDeviceUsable
;
6941 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMLowPower
)
6942 bits
|= kPMReportLowPower
;
6945 SIMPLEREPORT_SETVALUE(buf
, ((bits
& 0xff) << 8) | ((StateOrder(fMaxPowerState
) & 0xf) << 4) |
6946 (StateOrder(fCurrentPowerState
) & 0xf));
6948 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
6949 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
6950 rc
= kIOReturnOverrun
;
6954 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
6955 dest
->appendBytes(data2cpy
, size2cpy
);
6964 return kIOReturnSuccess
;
6971 // MARK: Driver Overrides
6973 //*********************************************************************************
6974 // [public] setPowerState
6976 // Does nothing here. This should be implemented in a subclass driver.
6977 //*********************************************************************************
6979 IOReturn
IOService::setPowerState(
6980 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
6985 //*********************************************************************************
6986 // [public] maxCapabilityForDomainState
6988 // Finds the highest power state in the array whose input power requirement
6989 // is equal to the input parameter. Where a more intelligent decision is
6990 // possible, override this in the subclassed driver.
6991 //*********************************************************************************
6993 IOPMPowerStateIndex
IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags
)
6995 IOPMPowerStateIndex stateIndex
;
6997 if (!fNumberOfPowerStates
)
6998 return kPowerStateZero
;
7000 for ( int order
= fNumberOfPowerStates
- 1; order
>= 0; order
-- )
7002 stateIndex
= fPowerStates
[order
].stateOrderToIndex
;
7004 if ( (flags
& fPowerStates
[stateIndex
].inputPowerFlags
) ==
7005 fPowerStates
[stateIndex
].inputPowerFlags
)
7010 return kPowerStateZero
;
7013 unsigned long IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState
)
7015 return getPowerStateForDomainFlags(domainState
);
7018 //*********************************************************************************
7019 // [public] initialPowerStateForDomainState
7021 // Called to query the power state for the initial power transition.
7022 //*********************************************************************************
7024 unsigned long IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState
)
7026 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
))
7028 // Return lowest power state for any root power domain changes
7029 return kPowerStateZero
;
7032 return getPowerStateForDomainFlags(domainState
);
7035 //*********************************************************************************
7036 // [public] powerStateForDomainState
7038 // This method is not called from PM.
7039 //*********************************************************************************
7041 unsigned long IOService::powerStateForDomainState( IOPMPowerFlags domainState
)
7043 return getPowerStateForDomainFlags(domainState
);
7047 //*********************************************************************************
7048 // [deprecated] didYouWakeSystem
7050 // Does nothing here. This should be implemented in a subclass driver.
7051 //*********************************************************************************
7053 bool IOService::didYouWakeSystem( void )
7057 #endif /* !__LP64__ */
7059 //*********************************************************************************
7060 // [public] powerStateWillChangeTo
7062 // Does nothing here. This should be implemented in a subclass driver.
7063 //*********************************************************************************
7065 IOReturn
IOService::powerStateWillChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7067 return kIOPMAckImplied
;
7070 //*********************************************************************************
7071 // [public] powerStateDidChangeTo
7073 // Does nothing here. This should be implemented in a subclass driver.
7074 //*********************************************************************************
7076 IOReturn
IOService::powerStateDidChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7078 return kIOPMAckImplied
;
7081 //*********************************************************************************
7082 // [protected] powerChangeDone
7084 // Called from PM work loop thread.
7085 // Does nothing here. This should be implemented in a subclass policy-maker.
7086 //*********************************************************************************
7088 void IOService::powerChangeDone( unsigned long )
7093 //*********************************************************************************
7094 // [deprecated] newTemperature
7096 // Does nothing here. This should be implemented in a subclass driver.
7097 //*********************************************************************************
7099 IOReturn
IOService::newTemperature( long currentTemp
, IOService
* whichZone
)
7103 #endif /* !__LP64__ */
7105 //*********************************************************************************
7106 // [public] systemWillShutdown
7108 // System shutdown and restart notification.
7109 //*********************************************************************************
7111 void IOService::systemWillShutdown( IOOptionBits specifier
)
7113 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
7115 rootDomain
->acknowledgeSystemWillShutdown( this );
7119 // MARK: PM State Machine
7121 //*********************************************************************************
7122 // [private static] acquirePMRequest
7123 //*********************************************************************************
7126 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
7127 IOPMRequest
* active
)
7129 IOPMRequest
* request
;
7133 request
= IOPMRequest::create();
7136 request
->init( target
, requestType
);
7139 IOPMRequest
* root
= active
->getRootRequest();
7140 if (root
) request
->attachRootRequest(root
);
7145 PM_ERROR("%s: No memory for PM request type 0x%x\n",
7146 target
->getName(), (uint32_t) requestType
);
7151 //*********************************************************************************
7152 // [private static] releasePMRequest
7153 //*********************************************************************************
7155 void IOService::releasePMRequest( IOPMRequest
* request
)
7164 //*********************************************************************************
7165 // [private static] submitPMRequest
7166 //*********************************************************************************
7168 void IOService::submitPMRequest( IOPMRequest
* request
)
7171 assert( gIOPMReplyQueue
);
7172 assert( gIOPMRequestQueue
);
7174 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7175 (long)request
->getType(), OBFUSCATE(request
),
7176 OBFUSCATE(request
->getTarget()), request
->getTarget()->getName(),
7177 OBFUSCATE(request
->fArg0
),
7178 OBFUSCATE(request
->fArg1
), OBFUSCATE(request
->fArg2
));
7180 if (request
->isReplyType())
7181 gIOPMReplyQueue
->queuePMRequest( request
);
7183 gIOPMRequestQueue
->queuePMRequest( request
);
7186 void IOService::submitPMRequests( IOPMRequest
** requests
, IOItemCount count
)
7189 assert( count
> 0 );
7190 assert( gIOPMRequestQueue
);
7192 for (IOItemCount i
= 0; i
< count
; i
++)
7194 IOPMRequest
* req
= requests
[i
];
7195 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7196 (long)req
->getType(), OBFUSCATE(req
),
7197 OBFUSCATE(req
->getTarget()), req
->getTarget()->getName(),
7198 OBFUSCATE(req
->fArg0
),
7199 OBFUSCATE(req
->fArg1
), OBFUSCATE(req
->fArg2
));
7202 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
7205 //*********************************************************************************
7206 // [private] actionPMRequestQueue
7208 // IOPMRequestQueue::checkForWork() passing a new request to the request target.
7209 //*********************************************************************************
7211 bool IOService::actionPMRequestQueue(
7212 IOPMRequest
* request
,
7213 IOPMRequestQueue
* queue
)
7219 // Work queue will immediately execute the request if the per-service
7220 // request queue is empty. Note pwrMgt is the target's IOServicePM.
7222 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
7226 // Calling PM without PMinit() is not allowed, fail the request.
7227 // Need to signal more when completing attached requests.
7229 PM_LOG("%s: PM not initialized\n", getName());
7230 PM_LOG1("[- %02x] %p [%p %s] !initialized\n",
7231 request
->getType(), OBFUSCATE(request
),
7232 OBFUSCATE(this), getName());
7234 more
= gIOPMCompletionQueue
->queuePMRequest(request
);
7235 if (more
) gIOPMWorkQueue
->incrementProducerCount();
7241 //*********************************************************************************
7242 // [private] actionPMCompletionQueue
7244 // IOPMCompletionQueue::checkForWork() passing a completed request to the
7246 //*********************************************************************************
7248 bool IOService::actionPMCompletionQueue(
7249 IOPMRequest
* request
,
7250 IOPMCompletionQueue
* queue
)
7252 bool more
= (request
->getNextRequest() != 0);
7253 IOPMRequest
* root
= request
->getRootRequest();
7255 if (root
&& (root
!= request
))
7258 gIOPMWorkQueue
->incrementProducerCount();
7260 releasePMRequest( request
);
7264 //*********************************************************************************
7265 // [private] actionPMWorkQueueRetire
7267 // IOPMWorkQueue::checkForWork() passing a retired request to the request target.
7268 //*********************************************************************************
7270 bool IOService::actionPMWorkQueueRetire( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7272 assert(request
&& queue
);
7274 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7275 request
->getType(), OBFUSCATE(request
),
7276 OBFUSCATE(this), getName(),
7277 fMachineState
, gIOPMBusyRequestCount
);
7279 // Catch requests created by idleTimerExpired()
7280 if (request
->getType() == kIOPMRequestTypeActivityTickle
)
7282 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
7284 if ((tickleFlags
& kTickleTypePowerDrop
) && fIdleTimerPeriod
)
7288 else if (tickleFlags
== (kTickleTypeActivity
| kTickleTypePowerRise
))
7290 // Invalidate any idle power drop that got queued while
7291 // processing this request.
7292 fIdleTimerGeneration
++;
7296 // When the completed request is linked, tell work queue there is
7297 // more work pending.
7299 return (gIOPMCompletionQueue
->queuePMRequest( request
));
7302 //*********************************************************************************
7303 // [private] isPMBlocked
7305 // Check if machine state transition is blocked.
7306 //*********************************************************************************
7308 bool IOService::isPMBlocked( IOPMRequest
* request
, int count
)
7313 if (kIOPM_Finished
== fMachineState
)
7316 if (kIOPM_DriverThreadCallDone
== fMachineState
)
7318 // 5 = kDriverCallInformPreChange
7319 // 6 = kDriverCallInformPostChange
7320 // 7 = kDriverCallSetPowerState
7321 // 8 = kRootDomainInformPreChange
7322 if (fDriverCallBusy
)
7323 reason
= 5 + fDriverCallReason
;
7327 // Waiting on driver's setPowerState() timeout.
7333 // Child or interested driver acks pending.
7334 if (fHeadNotePendingAcks
)
7339 // Waiting on apps or priority power interest clients.
7345 // Waiting on settle timer expiration.
7352 fWaitReason
= reason
;
7358 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7359 request
->getType(), OBFUSCATE(request
),
7360 OBFUSCATE(this), getName(),
7361 fMachineState
, reason
);
7370 //*********************************************************************************
7371 // [private] actionPMWorkQueueInvoke
7373 // IOPMWorkQueue::checkForWork() passing a request to the
7374 // request target for execution.
7375 //*********************************************************************************
7377 bool IOService::actionPMWorkQueueInvoke( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7382 assert(request
&& queue
);
7384 while (isPMBlocked(request
, loop
++) == false)
7386 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7387 request
->getType(), OBFUSCATE(request
),
7388 OBFUSCATE(this), getName(), fMachineState
);
7390 gIOPMRequest
= request
;
7391 gIOPMWorkInvokeCount
++;
7393 // Every PM machine states must be handled in one of the cases below.
7395 switch ( fMachineState
)
7397 case kIOPM_Finished
:
7398 start_watchdog_timer();
7400 executePMRequest( request
);
7403 case kIOPM_OurChangeTellClientsPowerDown
:
7404 // Root domain might self cancel due to assertions.
7407 bool cancel
= (bool) fDoNotPowerDown
;
7408 getPMRootDomain()->askChangeDownDone(
7409 &fHeadNoteChangeFlags
, &cancel
);
7410 fDoNotPowerDown
= cancel
;
7413 // askChangeDown() done, was it vetoed?
7414 if (!fDoNotPowerDown
)
7416 // no, we can continue
7417 OurChangeTellClientsPowerDown();
7421 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7422 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7423 // yes, rescind the warning
7424 tellNoChangeDown(fHeadNotePowerState
);
7425 // mark the change note un-actioned
7426 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7432 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
7433 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7434 if (fDoNotPowerDown
)
7436 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7437 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7438 // yes, rescind the warning
7439 tellNoChangeDown(fHeadNotePowerState
);
7440 // mark the change note un-actioned
7441 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7446 OurChangeTellUserPMPolicyPowerDown();
7449 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
7450 // PMRD: LastCallBeforeSleep notify done
7451 // Non-PMRD: tellChangeDown/kNotifyApps done
7452 if (fDoNotPowerDown
)
7454 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7455 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7456 // no, tell clients we're back in the old state
7457 tellChangeUp(fCurrentPowerState
);
7458 // mark the change note un-actioned
7459 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7465 // yes, we can continue
7466 OurChangeTellPriorityClientsPowerDown();
7470 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
7471 OurChangeNotifyInterestedDriversWillChange();
7474 case kIOPM_OurChangeSetPowerState
:
7475 OurChangeSetPowerState();
7478 case kIOPM_OurChangeWaitForPowerSettle
:
7479 OurChangeWaitForPowerSettle();
7482 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
7483 OurChangeNotifyInterestedDriversDidChange();
7486 case kIOPM_OurChangeTellCapabilityDidChange
:
7487 OurChangeTellCapabilityDidChange();
7490 case kIOPM_OurChangeFinish
:
7494 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
7495 ParentChangeTellPriorityClientsPowerDown();
7498 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
7499 ParentChangeNotifyInterestedDriversWillChange();
7502 case kIOPM_ParentChangeSetPowerState
:
7503 ParentChangeSetPowerState();
7506 case kIOPM_ParentChangeWaitForPowerSettle
:
7507 ParentChangeWaitForPowerSettle();
7510 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7511 ParentChangeNotifyInterestedDriversDidChange();
7514 case kIOPM_ParentChangeTellCapabilityDidChange
:
7515 ParentChangeTellCapabilityDidChange();
7518 case kIOPM_ParentChangeAcknowledgePowerChange
:
7519 ParentChangeAcknowledgePowerChange();
7522 case kIOPM_DriverThreadCallDone
:
7523 switch (fDriverCallReason
)
7525 case kDriverCallInformPreChange
:
7526 case kDriverCallInformPostChange
:
7527 notifyInterestedDriversDone();
7529 case kDriverCallSetPowerState
:
7530 notifyControllingDriverDone();
7532 case kRootDomainInformPreChange
:
7533 notifyRootDomainDone();
7536 panic("%s: bad call reason %x",
7537 getName(), fDriverCallReason
);
7541 case kIOPM_NotifyChildrenOrdered
:
7542 notifyChildrenOrdered();
7545 case kIOPM_NotifyChildrenDelayed
:
7546 notifyChildrenDelayed();
7549 case kIOPM_NotifyChildrenStart
:
7550 // pop notifyAll() state saved by notifyInterestedDriversDone()
7555 case kIOPM_SyncTellClientsPowerDown
:
7556 // Root domain might self cancel due to assertions.
7559 bool cancel
= (bool) fDoNotPowerDown
;
7560 getPMRootDomain()->askChangeDownDone(
7561 &fHeadNoteChangeFlags
, &cancel
);
7562 fDoNotPowerDown
= cancel
;
7564 if (!fDoNotPowerDown
)
7566 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7567 fOutOfBandParameter
= kNotifyApps
;
7568 tellChangeDown(fHeadNotePowerState
);
7572 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7573 // askChangeDown/kNotifyApps
7574 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7575 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7576 tellNoChangeDown(fHeadNotePowerState
);
7577 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7582 case kIOPM_SyncTellPriorityClientsPowerDown
:
7583 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7584 if (!fDoNotPowerDown
)
7586 fMachineState
= kIOPM_SyncNotifyWillChange
;
7587 fOutOfBandParameter
= kNotifyPriority
;
7588 tellChangeDown(fHeadNotePowerState
);
7592 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7593 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7594 tellChangeUp(fCurrentPowerState
);
7595 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7600 case kIOPM_SyncNotifyWillChange
:
7601 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
)
7603 fMachineState
= kIOPM_SyncFinish
;
7606 fMachineState
= kIOPM_SyncNotifyDidChange
;
7607 fDriverCallReason
= kDriverCallInformPreChange
;
7611 case kIOPM_SyncNotifyDidChange
:
7612 fIsPreChange
= false;
7614 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7616 fMachineState
= kIOPM_SyncFinish
;
7620 assert(IS_ROOT_DOMAIN
);
7621 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7624 fDriverCallReason
= kDriverCallInformPostChange
;
7628 case kIOPM_SyncTellCapabilityDidChange
:
7629 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7632 case kIOPM_SyncFinish
:
7633 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7634 ParentChangeAcknowledgePowerChange();
7639 case kIOPM_TellCapabilityChangeDone
:
7642 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
)
7644 MS_POP(); // tellSystemCapabilityChange()
7647 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7651 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
)
7653 MS_POP(); // tellSystemCapabilityChange()
7656 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7658 tellClientsWithResponse( fOutOfBandMessage
);
7662 panic("PMWorkQueueInvoke: unknown machine state %x",
7668 if (fMachineState
== kIOPM_Finished
)
7670 stop_watchdog_timer();
7679 //*********************************************************************************
7680 // [private] executePMRequest
7681 //*********************************************************************************
7683 void IOService::executePMRequest( IOPMRequest
* request
)
7685 assert( kIOPM_Finished
== fMachineState
);
7687 switch (request
->getType())
7689 case kIOPMRequestTypePMStop
:
7690 handlePMstop( request
);
7693 case kIOPMRequestTypeAddPowerChild1
:
7694 addPowerChild1( request
);
7697 case kIOPMRequestTypeAddPowerChild2
:
7698 addPowerChild2( request
);
7701 case kIOPMRequestTypeAddPowerChild3
:
7702 addPowerChild3( request
);
7705 case kIOPMRequestTypeRegisterPowerDriver
:
7706 handleRegisterPowerDriver( request
);
7709 case kIOPMRequestTypeAdjustPowerState
:
7710 fAdjustPowerScheduled
= false;
7714 case kIOPMRequestTypePowerDomainWillChange
:
7715 handlePowerDomainWillChangeTo( request
);
7718 case kIOPMRequestTypePowerDomainDidChange
:
7719 handlePowerDomainDidChangeTo( request
);
7722 case kIOPMRequestTypeRequestPowerState
:
7723 case kIOPMRequestTypeRequestPowerStateOverride
:
7724 handleRequestPowerState( request
);
7727 case kIOPMRequestTypePowerOverrideOnPriv
:
7728 case kIOPMRequestTypePowerOverrideOffPriv
:
7729 handlePowerOverrideChanged( request
);
7732 case kIOPMRequestTypeActivityTickle
:
7733 handleActivityTickle( request
);
7736 case kIOPMRequestTypeSynchronizePowerTree
:
7737 handleSynchronizePowerTree( request
);
7740 case kIOPMRequestTypeSetIdleTimerPeriod
:
7742 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7743 fNextIdleTimerPeriod
= fIdleTimerPeriod
;
7744 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
7749 case kIOPMRequestTypeIgnoreIdleTimer
:
7750 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7753 case kIOPMRequestTypeQuiescePowerTree
:
7754 gIOPMWorkQueue
->finishQuiesceRequest(request
);
7758 panic("executePMRequest: unknown request type %x", request
->getType());
7762 //*********************************************************************************
7763 // [private] actionPMReplyQueue
7765 // IOPMRequestQueue::checkForWork() passing a reply-type request to the
7767 //*********************************************************************************
7769 bool IOService::actionPMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7773 assert( request
&& queue
);
7774 assert( request
->isReplyType() );
7776 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7777 request
->getType(), OBFUSCATE(request
),
7778 OBFUSCATE(this), getName(), fMachineState
);
7780 switch ( request
->getType() )
7782 case kIOPMRequestTypeAllowPowerChange
:
7783 case kIOPMRequestTypeCancelPowerChange
:
7784 // Check if we are expecting this response.
7785 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7786 (int)(uintptr_t) request
->fArg1
))
7788 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
7790 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7791 // flag is set. Only root domain will set this flag.
7792 // However, there is one exception to this rule. User-space PM
7793 // policy may choose to cancel sleep even after all clients have
7794 // been notified that we will lower power.
7796 if ((fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7797 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7798 || ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0))
7800 fDoNotPowerDown
= true;
7802 OSString
* name
= (OSString
*) request
->fArg2
;
7803 getPMRootDomain()->pmStatsRecordApplicationResponse(
7804 gIOPMStatsApplicationResponseCancel
,
7805 name
? name
->getCStringNoCopy() : "", 0,
7806 0, (int)(uintptr_t) request
->fArg1
, 0);
7813 cleanClientResponses(false);
7817 // OSString containing app name in Arg2 must be released.
7818 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
7820 OSObject
* obj
= (OSObject
*) request
->fArg2
;
7821 if (obj
) obj
->release();
7825 case kIOPMRequestTypeAckPowerChange
:
7826 more
= handleAcknowledgePowerChange( request
);
7829 case kIOPMRequestTypeAckSetPowerState
:
7830 if (fDriverTimer
== -1)
7832 // driver acked while setPowerState() call is in-flight.
7833 // take this ack, return value from setPowerState() is irrelevant.
7834 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
7835 (uintptr_t) this, fDriverTimer
);
7838 else if (fDriverTimer
> 0)
7840 // expected ack, stop the timer
7843 #if LOG_SETPOWER_TIMES
7844 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
7845 if (nsec
> LOG_SETPOWER_TIMES
) {
7846 getPMRootDomain()->pmStatsRecordApplicationResponse(
7847 gIOPMStatsDriverPSChangeSlow
,
7848 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), 0, NULL
, fHeadNotePowerState
);
7851 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
7858 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
7862 case kIOPMRequestTypeInterestChanged
:
7863 handleInterestChanged( request
);
7867 case kIOPMRequestTypeIdleCancel
:
7868 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
7869 || (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7870 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7871 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
7872 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
7874 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7875 PM_LOG2("%s: cancel from machine state %d\n",
7876 getName(), fMachineState
);
7877 fDoNotPowerDown
= true;
7878 // Stop waiting for app replys.
7879 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
7880 (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
) ||
7881 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
) ||
7882 (fMachineState
== kIOPM_SyncTellClientsPowerDown
) )
7883 cleanClientResponses(false);
7888 case kIOPMRequestTypeChildNotifyDelayCancel
:
7889 if (fMachineState
== kIOPM_NotifyChildrenDelayed
)
7891 PM_LOG2("%s: delay notify cancelled\n", getName());
7892 notifyChildrenDelayed();
7897 panic("PMReplyQueue: unknown reply type %x", request
->getType());
7900 more
|= gIOPMCompletionQueue
->queuePMRequest(request
);
7902 gIOPMWorkQueue
->incrementProducerCount();
7907 //*********************************************************************************
7908 // [private] assertPMDriverCall / deassertPMDriverCall
7909 //*********************************************************************************
7911 bool IOService::assertPMDriverCall(
7912 IOPMDriverCallEntry
* entry
,
7913 IOOptionBits options
,
7914 IOPMinformee
* inform
)
7916 IOService
* target
= 0;
7924 if (fLockedFlags
.PMStop
)
7929 if (((options
& kIOPMADC_NoInactiveCheck
) == 0) && isInactive())
7936 if (!inform
->active
)
7940 target
= inform
->whatObject
;
7941 if (target
->isInactive())
7947 entry
->thread
= current_thread();
7948 entry
->target
= target
;
7949 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7958 void IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
7960 bool wakeup
= false;
7964 assert( !queue_empty(&fPMDriverCallQueue
) );
7965 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7966 if (fLockedFlags
.PMDriverCallWait
)
7974 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
7977 void IOService::waitForPMDriverCall( IOService
* target
)
7979 const IOPMDriverCallEntry
* entry
;
7980 thread_t thread
= current_thread();
7981 AbsoluteTime deadline
;
7988 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
7990 // Target of interested driver call
7991 if (target
&& (target
!= entry
->target
))
7994 if (entry
->thread
== thread
)
7998 PM_LOG("%s: %s(%s) on PM thread\n",
7999 fName
, __FUNCTION__
, target
? target
->getName() : "");
8000 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
8001 fName
, __FUNCTION__
, target
? target
->getName() : "");
8013 fLockedFlags
.PMDriverCallWait
= true;
8014 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
8015 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
8016 fLockedFlags
.PMDriverCallWait
= false;
8017 if (THREAD_TIMED_OUT
== waitResult
)
8019 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
8026 //*********************************************************************************
8027 // [private] Debug helpers
8028 //*********************************************************************************
8030 const char * IOService::getIOMessageString( uint32_t msg
)
8032 #define MSG_ENTRY(x) {(int) x, #x}
8034 static const IONamedValue msgNames
[] = {
8035 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
8036 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
8037 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
8038 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
8039 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
8040 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
8041 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
8042 MSG_ENTRY( kIOMessageCanSystemSleep
),
8043 MSG_ENTRY( kIOMessageSystemWillSleep
),
8044 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
8045 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
8046 MSG_ENTRY( kIOMessageSystemWillRestart
),
8047 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
8048 MSG_ENTRY( kIOMessageSystemCapabilityChange
),
8049 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep
)
8052 return IOFindNameForValue(msg
, msgNames
);
8057 // MARK: IOPMRequest
8059 //*********************************************************************************
8060 // IOPMRequest Class
8062 // Requests from PM clients, and also used for inter-object messaging within PM.
8063 //*********************************************************************************
8065 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
8067 IOPMRequest
* IOPMRequest::create( void )
8069 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
8070 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
8078 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
8080 if (!IOCommand::init())
8083 fRequestType
= type
;
8089 // Root node and root domain requests does not prevent the power tree from
8090 // becoming quiescent.
8092 fIsQuiesceBlocker
= ((fTarget
!= gIOPMRootNode
) &&
8093 (fTarget
!= IOService::getPMRootDomain()));
8098 void IOPMRequest::reset( void )
8100 assert( fWorkWaitCount
== 0 );
8101 assert( fFreeWaitCount
== 0 );
8103 detachNextRequest();
8104 detachRootRequest();
8106 if (fCompletionAction
&& (fRequestType
== kIOPMRequestTypeQuiescePowerTree
))
8108 // Call the completion on PM work loop context
8109 fCompletionAction(fCompletionTarget
, fCompletionParam
);
8110 fCompletionAction
= 0;
8113 fRequestType
= kIOPMRequestTypeInvalid
;
8122 bool IOPMRequest::attachNextRequest( IOPMRequest
* next
)
8128 // Postpone the execution of the next request after
8130 fRequestNext
= next
;
8131 fRequestNext
->fWorkWaitCount
++;
8132 #if LOG_REQUEST_ATTACH
8133 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8134 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8135 fRequestNext
->fRequestType
,
8136 (uint32_t) fRequestNext
->fWorkWaitCount
,
8137 fTarget
->getName());
8144 bool IOPMRequest::detachNextRequest( void )
8150 assert(fRequestNext
->fWorkWaitCount
);
8151 if (fRequestNext
->fWorkWaitCount
)
8152 fRequestNext
->fWorkWaitCount
--;
8153 #if LOG_REQUEST_ATTACH
8154 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8155 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8156 fRequestNext
->fRequestType
,
8157 (uint32_t) fRequestNext
->fWorkWaitCount
,
8158 fTarget
->getName());
8166 bool IOPMRequest::attachRootRequest( IOPMRequest
* root
)
8172 // Delay the completion of the root request after
8174 fRequestRoot
= root
;
8175 fRequestRoot
->fFreeWaitCount
++;
8176 #if LOG_REQUEST_ATTACH
8177 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8178 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8179 (uint32_t) fRequestRoot
->fType
,
8180 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8181 fTarget
->getName());
8188 bool IOPMRequest::detachRootRequest( void )
8194 assert(fRequestRoot
->fFreeWaitCount
);
8195 if (fRequestRoot
->fFreeWaitCount
)
8196 fRequestRoot
->fFreeWaitCount
--;
8197 #if LOG_REQUEST_ATTACH
8198 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8199 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8200 (uint32_t) fRequestRoot
->fType
,
8201 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8202 fTarget
->getName());
8211 // MARK: IOPMRequestQueue
8213 //*********************************************************************************
8214 // IOPMRequestQueue Class
8216 // Global queues. Queues are created once and never released.
8217 //*********************************************************************************
8219 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
8221 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
8223 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
8224 if (me
&& !me
->init(inOwner
, inAction
))
8232 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
8234 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8237 queue_init(&fQueue
);
8238 fLock
= IOLockAlloc();
8239 return (fLock
!= 0);
8242 void IOPMRequestQueue::free( void )
8249 return IOEventSource::free();
8252 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
8256 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8257 IOLockUnlock(fLock
);
8258 if (workLoop
) signalWorkAvailable();
8262 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
8266 assert(requests
&& count
);
8272 queue_enter(&fQueue
, next
, typeof(next
), fCommandChain
);
8274 IOLockUnlock(fLock
);
8275 if (workLoop
) signalWorkAvailable();
8278 bool IOPMRequestQueue::checkForWork( void )
8280 Action dqAction
= (Action
) action
;
8281 IOPMRequest
* request
;
8283 int dequeueCount
= 0;
8286 IOLockLock( fLock
);
8288 while (!queue_empty(&fQueue
))
8290 if (dequeueCount
++ >= kMaxDequeueCount
)
8292 // Allow other queues a chance to work
8297 queue_remove_first(&fQueue
, request
, typeof(request
), fCommandChain
);
8298 IOLockUnlock(fLock
);
8299 target
= request
->getTarget();
8301 more
|= (*dqAction
)( target
, request
, this );
8302 IOLockLock( fLock
);
8305 IOLockUnlock( fLock
);
8310 // MARK: IOPMWorkQueue
8312 //*********************************************************************************
8313 // IOPMWorkQueue Class
8315 // Queue of IOServicePM objects, each with a queue of IOPMRequest sharing the
8317 //*********************************************************************************
8319 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
8322 IOPMWorkQueue::create( IOService
* inOwner
, Action invoke
, Action retire
)
8324 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
8325 if (me
&& !me
->init(inOwner
, invoke
, retire
))
8333 bool IOPMWorkQueue::init( IOService
* inOwner
, Action invoke
, Action retire
)
8335 if (!invoke
|| !retire
||
8336 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
8339 queue_init(&fWorkQueue
);
8341 fInvokeAction
= invoke
;
8342 fRetireAction
= retire
;
8343 fConsumerCount
= fProducerCount
= 0;
8348 bool IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
8350 queue_head_t
* requestQueue
;
8356 assert( onThread() );
8357 assert( queue_next(&request
->fCommandChain
) ==
8358 queue_prev(&request
->fCommandChain
) );
8360 gIOPMBusyRequestCount
++;
8362 if (request
->isQuiesceType())
8364 if ((request
->getTarget() == gIOPMRootNode
) && !fQuiesceStartTime
)
8366 // Attach new quiesce request to all quiesce blockers in the queue
8367 fQuiesceStartTime
= mach_absolute_time();
8368 attachQuiesceRequest(request
);
8369 fQuiesceRequest
= request
;
8372 else if (fQuiesceRequest
&& request
->isQuiesceBlocker())
8374 // Attach the new quiesce blocker to the blocked quiesce request
8375 request
->attachNextRequest(fQuiesceRequest
);
8378 // Add new request to the tail of the per-service request queue.
8379 // Then immediately check the request queue to minimize latency
8380 // if the queue was empty.
8382 requestQueue
= &pwrMgt
->RequestHead
;
8383 empty
= queue_empty(requestQueue
);
8384 queue_enter(requestQueue
, request
, typeof(request
), fCommandChain
);
8387 more
= checkRequestQueue(requestQueue
, &empty
);
8390 // Request just added is blocked, add its target IOServicePM
8391 // to the work queue.
8392 assert( queue_next(&pwrMgt
->WorkChain
) ==
8393 queue_prev(&pwrMgt
->WorkChain
) );
8395 queue_enter(&fWorkQueue
, pwrMgt
, typeof(pwrMgt
), WorkChain
);
8397 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8398 fQueueLength
, pwrMgt
->Name
, OBFUSCATE(pwrMgt
));
8405 bool IOPMWorkQueue::checkRequestQueue( queue_head_t
* requestQueue
, bool * empty
)
8407 IOPMRequest
* request
;
8412 assert(!queue_empty(requestQueue
));
8414 request
= (typeof(request
)) queue_first(requestQueue
);
8415 if (request
->isWorkBlocked())
8416 break; // request dispatch blocked on attached request
8418 target
= request
->getTarget();
8421 done
= (*fInvokeAction
)( target
, request
, this );
8425 PM_LOG("PM request 0x%x dropped\n", request
->getType());
8429 break; // PM state machine blocked
8431 assert(gIOPMBusyRequestCount
> 0);
8432 if (gIOPMBusyRequestCount
)
8433 gIOPMBusyRequestCount
--;
8435 if (request
== fQuiesceRequest
)
8437 fQuiesceRequest
= 0;
8440 queue_remove_first(requestQueue
, request
, typeof(request
), fCommandChain
);
8441 more
|= (*fRetireAction
)( target
, request
, this );
8442 done
= queue_empty(requestQueue
);
8449 // Retired a request that may unblock a previously visited request
8450 // that is still waiting on the work queue. Must trigger another
8458 bool IOPMWorkQueue::checkForWork( void )
8460 IOServicePM
* entry
;
8465 #if WORK_QUEUE_STATS
8466 fStatCheckForWork
++;
8469 // Iterate over all IOServicePM entries in the work queue,
8470 // and check each entry's request queue.
8472 while (fConsumerCount
!= fProducerCount
)
8474 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8475 fProducerCount
, fConsumerCount
);
8477 fConsumerCount
= fProducerCount
;
8479 #if WORK_QUEUE_STATS
8480 if (queue_empty(&fWorkQueue
))
8486 uint32_t cachedWorkCount
= gIOPMWorkInvokeCount
;
8489 __IGNORE_WCASTALIGN(entry
= (typeof(entry
)) queue_first(&fWorkQueue
));
8490 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
))
8492 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
8494 // Get next entry, points to head if current entry is last.
8495 __IGNORE_WCASTALIGN(next
= (typeof(next
)) queue_next(&entry
->WorkChain
));
8497 // if request queue is empty, remove IOServicePM from work queue.
8500 assert(fQueueLength
);
8501 if (fQueueLength
) fQueueLength
--;
8502 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8503 fQueueLength
, entry
->Name
, OBFUSCATE(entry
));
8504 queue_remove(&fWorkQueue
, entry
, typeof(entry
), WorkChain
);
8509 #if WORK_QUEUE_STATS
8510 if (cachedWorkCount
== gIOPMWorkInvokeCount
)
8518 void IOPMWorkQueue::signalWorkAvailable( void )
8521 IOEventSource::signalWorkAvailable();
8524 void IOPMWorkQueue::incrementProducerCount( void )
8529 void IOPMWorkQueue::attachQuiesceRequest( IOPMRequest
* quiesceRequest
)
8531 IOServicePM
* entry
;
8532 IOPMRequest
* request
;
8534 if (queue_empty(&fWorkQueue
))
8539 queue_iterate(&fWorkQueue
, entry
, typeof(entry
), WorkChain
)
8541 queue_iterate(&entry
->RequestHead
, request
, typeof(request
), fCommandChain
)
8543 // Attach the quiesce request to any request in the queue that
8544 // is not linked to a next request. These requests will block
8545 // the quiesce request.
8547 if (request
->isQuiesceBlocker())
8549 request
->attachNextRequest(quiesceRequest
);
8555 void IOPMWorkQueue::finishQuiesceRequest( IOPMRequest
* quiesceRequest
)
8557 if (fQuiesceRequest
&& (quiesceRequest
== fQuiesceRequest
) &&
8558 (fQuiesceStartTime
!= 0))
8561 fQuiesceFinishTime
= mach_absolute_time();
8566 // MARK: IOPMCompletionQueue
8568 //*********************************************************************************
8569 // IOPMCompletionQueue Class
8570 //*********************************************************************************
8572 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
8574 IOPMCompletionQueue
*
8575 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
8577 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
8578 if (me
&& !me
->init(inOwner
, inAction
))
8586 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
8588 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8591 queue_init(&fQueue
);
8595 bool IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
8600 // unblock dependent request
8601 more
= request
->detachNextRequest();
8602 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8606 bool IOPMCompletionQueue::checkForWork( void )
8608 Action dqAction
= (Action
) action
;
8609 IOPMRequest
* request
;
8614 request
= (typeof(request
)) queue_first(&fQueue
);
8615 while (!queue_end(&fQueue
, (queue_entry_t
) request
))
8617 next
= (typeof(next
)) queue_next(&request
->fCommandChain
);
8618 if (!request
->isFreeBlocked())
8620 queue_remove(&fQueue
, request
, typeof(request
), fCommandChain
);
8621 target
= request
->getTarget();
8623 more
|= (*dqAction
)( target
, request
, this );
8632 // MARK: IOServicePM
8634 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8636 //*********************************************************************************
8639 // Serialize IOServicePM for debugging.
8640 //*********************************************************************************
8643 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8645 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8648 dict
->setObject(key
, num
);
8653 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
) const
8655 OSDictionary
* dict
;
8657 int powerClamp
= -1;
8660 if (IdleTimerPeriod
)
8663 if (PMActions
.parameter
& kPMActionsFlagLimitPower
)
8667 if (PMActions
.parameter
&
8668 (kPMActionsFlagIsDisplayWrangler
| kPMActionsFlagIsGraphicsDevice
))
8672 #if WORK_QUEUE_STATS
8673 if (gIOPMRootNode
== ControllingDriver
)
8678 dict
= OSDictionary::withDictionary(
8679 PowerClients
, PowerClients
->getCount() + dictSize
);
8681 dict
= OSDictionary::withCapacity(dictSize
);
8685 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8686 setPMProperty(dict
, "CapabilityFlags", CurrentCapabilityFlags
);
8687 if (NumberOfPowerStates
)
8688 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
-1);
8689 if (DesiredPowerState
!= CurrentPowerState
)
8690 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8691 if (kIOPM_Finished
!= MachineState
)
8692 setPMProperty(dict
, "MachineState", MachineState
);
8693 if (DeviceOverrideEnabled
)
8694 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8695 if (powerClamp
>= 0)
8696 setPMProperty(dict
, "PowerClamp", powerClamp
);
8698 if (IdleTimerPeriod
)
8704 clock_get_uptime(&now
);
8706 // The idle timer period in milliseconds
8707 setPMProperty(dict
, "IdleTimerPeriod", NextIdleTimerPeriod
* 1000ULL);
8709 // Number of tickles since the last idle timer expiration
8710 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8712 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
8714 // Milliseconds since the last activity tickle
8716 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8717 absolutetime_to_nanoseconds(delta
, &nsecs
);
8718 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
8721 if (!IdleTimerStopped
&& AbsoluteTime_to_scalar(&IdleTimerStartTime
))
8723 // Idle timer elapsed time in milliseconds
8725 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
8726 absolutetime_to_nanoseconds(delta
, &nsecs
);
8727 setPMProperty(dict
, "IdleTimerElapsedTime", NS_TO_MS(nsecs
));
8731 #if WORK_QUEUE_STATS
8732 if (gIOPMRootNode
== Owner
)
8734 setPMProperty(dict
, "WQ-CheckForWork",
8735 gIOPMWorkQueue
->fStatCheckForWork
);
8736 setPMProperty(dict
, "WQ-ScanEntries",
8737 gIOPMWorkQueue
->fStatScanEntries
);
8738 setPMProperty(dict
, "WQ-QueueEmpty",
8739 gIOPMWorkQueue
->fStatQueueEmpty
);
8740 setPMProperty(dict
, "WQ-NoWorkDone",
8741 gIOPMWorkQueue
->fStatNoWorkDone
);
8745 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
)
8747 // Don't report advisory tickle when it has no influence
8748 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
8751 ok
= dict
->serialize(s
);
8755 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
8758 bool IOServicePM::serialize( OSSerialize
* s
) const
8760 IOReturn ret
= kIOReturnNotReady
;
8762 if (gIOPMWatchDogThread
== current_thread())
8764 // Calling without lock as this data is collected for debug purpose, before reboot.
8765 // The workloop is probably already hung in state machine.
8766 ret
= gatedSerialize(s
);
8768 else if (gIOPMWorkLoop
)
8770 ret
= gIOPMWorkLoop
->runAction(
8771 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
8772 (OSObject
*) this, (void *) s
);
8775 return (kIOReturnSuccess
== ret
);
8778 void IOServicePM::pmPrint(
8781 uintptr_t param2
) const
8783 gPlatform
->PMLog(Name
, event
, param1
, param2
);
8786 void IOServicePM::pmTrace(
8789 uintptr_t param2
) const
8791 const char * who
= Name
;
8792 uint64_t regId
= Owner
->getRegistryEntryID();
8795 static const uint32_t sStartStopBitField
[] =
8796 { 0x00000000, 0x00000040 }; // Only Program Hardware so far
8798 // Arcane formula from Hacker's Delight by Warren
8799 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
8800 uint32_t sgnevent
= ((int) event
>> 31);
8801 uint32_t absevent
= sgnevent
^ (event
+ sgnevent
);
8802 uint32_t code
= IODBG_POWER(absevent
);
8804 uint32_t bit
= 1 << (absevent
& 0x1f);
8805 if ((absevent
< (sizeof(sStartStopBitField
) * 8)) &&
8806 (sStartStopBitField
[absevent
>> 5] & bit
))
8808 // Or in the START or END bits, Start = 1 & END = 2
8809 // If sgnevent == 0 then START - 0 => START
8810 // else if sgnevent == -1 then START - -1 => END
8811 code
|= DBG_FUNC_START
- sgnevent
;
8814 // Copy the first characters of the name into an uintptr_t
8815 for (uint32_t i
= 0; (i
< sizeof(uintptr_t) && who
[i
] != 0); i
++)
8817 ((char *) &name
)[sizeof(uintptr_t) - i
- 1] = who
[i
];
8820 IOTimeStampConstant(code
, name
, (uintptr_t) regId
, param1
, param2
);