2 * Copyright (c) 1998-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/assert.h>
30 #include <IOKit/IOKitDebug.h>
31 #include <IOKit/IOLib.h>
32 #include <IOKit/IOMessage.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IOEventSource.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/IOCommand.h>
38 #include <IOKit/IOTimeStamp.h>
39 #include <IOKit/IOReportMacros.h>
41 #include <IOKit/pwr_mgt/IOPMlog.h>
42 #include <IOKit/pwr_mgt/IOPMinformee.h>
43 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
44 #include <IOKit/pwr_mgt/IOPowerConnection.h>
45 #include <IOKit/pwr_mgt/RootDomain.h>
46 #include <IOKit/pwr_mgt/IOPMPrivate.h>
49 #include <sys/proc_internal.h>
50 #include <sys/sysctl.h>
51 #include <libkern/OSDebug.h>
52 #include <kern/thread.h>
54 // Required for notification instrumentation
55 #include "IOServicePrivate.h"
56 #include "IOServicePMPrivate.h"
57 #include "IOKitKernelInternal.h"
60 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
61 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
62 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
63 static void tellAppClientApplier(OSObject
* object
, void * arg
);
65 static uint64_t computeTimeDeltaNS( const AbsoluteTime
* start
)
70 clock_get_uptime(&now
);
71 SUB_ABSOLUTETIME(&now
, start
);
72 absolutetime_to_nanoseconds(now
, &nsec
);
77 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
80 //******************************************************************************
82 //******************************************************************************
84 static bool gIOPMInitialized
= false;
85 static uint32_t gIOPMBusyRequestCount
= 0;
86 static uint32_t gIOPMWorkInvokeCount
= 0;
87 static uint32_t gIOPMTickleGeneration
= 0;
88 static IOWorkLoop
* gIOPMWorkLoop
= 0;
89 static IOPMRequestQueue
* gIOPMRequestQueue
= 0;
90 static IOPMRequestQueue
* gIOPMReplyQueue
= 0;
91 static IOPMWorkQueue
* gIOPMWorkQueue
= 0;
92 static IOPMCompletionQueue
* gIOPMCompletionQueue
= 0;
93 static IOPMRequest
* gIOPMRequest
= 0;
94 static IOService
* gIOPMRootNode
= 0;
95 static IOPlatformExpert
* gPlatform
= 0;
97 static char gIOSpinDumpKextName
[128];
98 static char gIOSpinDumpDelayType
[16];
99 static uint32_t gIOSpinDumpDelayDuration
= 0;
101 static SYSCTL_STRING(_debug
, OID_AUTO
, swd_kext_name
,
102 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
103 &gIOSpinDumpKextName
, sizeof(gIOSpinDumpKextName
), "");
104 static SYSCTL_STRING(_debug
, OID_AUTO
, swd_delay_type
,
105 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
106 &gIOSpinDumpDelayType
, sizeof(gIOSpinDumpDelayType
), "");
107 static SYSCTL_INT(_debug
, OID_AUTO
, swd_delay_duration
,
108 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
109 &gIOSpinDumpDelayDuration
, 0, "");
111 const OSSymbol
* gIOPMPowerClientDevice
= 0;
112 const OSSymbol
* gIOPMPowerClientDriver
= 0;
113 const OSSymbol
* gIOPMPowerClientChildProxy
= 0;
114 const OSSymbol
* gIOPMPowerClientChildren
= 0;
115 const OSSymbol
* gIOPMPowerClientRootDomain
= 0;
117 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= 0;
118 static bool gIOPMAdvisoryTickleEnabled
= true;
119 static thread_t gIOPMWatchDogThread
= NULL
;
120 uint32_t gCanSleepTimeout
= 0;
122 static uint32_t getPMRequestType( void )
124 uint32_t type
= kIOPMRequestTypeInvalid
;
126 type
= gIOPMRequest
->getType();
130 static IOPMRequestTag
getPMRequestTag( void )
132 IOPMRequestTag tag
= 0;
134 (gIOPMRequest
->getType() == kIOPMRequestTypeRequestPowerStateOverride
))
136 tag
= gIOPMRequest
->fRequestTag
;
141 SYSCTL_UINT(_kern
, OID_AUTO
, pmtimeout
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &gCanSleepTimeout
, 0, "Power Management Timeout");
143 //******************************************************************************
145 //******************************************************************************
147 #define PM_ERROR(x...) do { kprintf(x);IOLog(x); \
149 #define PM_LOG(x...) do { kprintf(x); } while (false)
151 #define PM_LOG1(x...) do { \
152 if (kIOLogDebugPower & gIOKitDebug) \
153 kprintf(x); } while (false)
155 #define PM_LOG2(x...) do { \
156 if (kIOLogDebugPower & gIOKitDebug) \
157 kprintf(x); } while (false)
160 #define PM_LOG3(x...) do { kprintf(x); } while (false)
162 #define PM_LOG3(x...)
165 #define RD_LOG(x...) do { \
166 if ((kIOLogPMRootDomain & gIOKitDebug) && \
167 (getPMRootDomain() == this)) { \
168 kprintf("PMRD: " x); \
170 #define PM_ASSERT_IN_GATE(x) \
172 assert(gIOPMWorkLoop->inGate()); \
175 #define PM_LOCK() IOLockLock(fPMLock)
176 #define PM_UNLOCK() IOLockUnlock(fPMLock)
177 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
178 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
180 #define us_per_s 1000000
181 #define ns_per_us 1000
182 #define k30Seconds (30*us_per_s)
183 #define k5Seconds ( 5*us_per_s)
185 #define kCanSleepMaxTimeReq k5Seconds
187 #define kCanSleepMaxTimeReq k30Seconds
189 #define kMaxTimeRequested k30Seconds
190 #define kMinAckTimeoutTicks (10*1000000)
191 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
192 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
193 #define kPwrMgtKey "IOPowerManagement"
195 #define OUR_PMLog(t, a, b) do { \
197 if (gIOKitDebug & kIOLogPower) \
198 pwrMgt->pmPrint(t, a, b); \
199 if (gIOKitTrace & kIOTracePowerMgmt) \
200 pwrMgt->pmTrace(t, DBG_FUNC_NONE, a, b); \
204 #define OUR_PMLogFuncStart(t, a, b) do { \
206 if (gIOKitDebug & kIOLogPower) \
207 pwrMgt->pmPrint(t, a, b); \
208 if (gIOKitTrace & kIOTracePowerMgmt) \
209 pwrMgt->pmTrace(t, DBG_FUNC_START, a, b); \
213 #define OUR_PMLogFuncEnd(t, a, b) do { \
215 if (gIOKitDebug & kIOLogPower) \
216 pwrMgt->pmPrint(-t, a, b); \
217 if (gIOKitTrace & kIOTracePowerMgmt) \
218 pwrMgt->pmTrace(t, DBG_FUNC_END, a, b); \
222 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
223 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
225 #define SUPPORT_IDLE_CANCEL 1
227 #define kIOPMPowerStateMax 0xFFFFFFFF
228 #define kInvalidTicklePowerState kIOPMPowerStateMax
230 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
232 #define IS_PM_ROOT (this == gIOPMRootNode)
233 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
234 #define IS_POWER_DROP (StateOrder(fHeadNotePowerState) < StateOrder(fCurrentPowerState))
235 #define IS_POWER_RISE (StateOrder(fHeadNotePowerState) > StateOrder(fCurrentPowerState))
237 // log setPowerStates longer than (ns):
238 #if defined(__i386__) || defined(__x86_64__)
239 #define LOG_SETPOWER_TIMES (300ULL * 1000ULL * 1000ULL)
241 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
243 // log app responses longer than (ns):
244 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
245 // use message tracer to log messages longer than (ns):
246 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
248 // log kext responses longer than (ns):
249 #define LOG_KEXT_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
252 kReserveDomainPower
= 1
256 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
257 assert(kIOPM_BadMachineState != n); \
258 fSavedMachineState = n; } while (false)
261 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
262 fMachineState = fSavedMachineState; \
263 fSavedMachineState = kIOPM_BadMachineState; } while (false)
265 #define PM_ACTION_0(a) \
266 do { if (fPMActions.a) { \
267 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
270 #define PM_ACTION_2(a, x, y) \
271 do { if (fPMActions.a) { \
272 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, \
273 getPMRequestTag()); } \
276 #define PM_ACTION_3(a, x, y, z) \
277 do { if (fPMActions.a) { \
278 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, z); } \
281 static OSNumber
* copyClientIDForNotification(
283 IOPMInterestContext
*context
);
285 static void logClientIDForNotification(
287 IOPMInterestContext
*context
,
288 const char *logString
);
290 //*********************************************************************************
293 // Check kgmacros after modifying machine states.
294 //*********************************************************************************
299 kIOPM_OurChangeTellClientsPowerDown
= 1,
300 kIOPM_OurChangeTellUserPMPolicyPowerDown
= 2,
301 kIOPM_OurChangeTellPriorityClientsPowerDown
= 3,
302 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 4,
303 kIOPM_OurChangeSetPowerState
= 5,
304 kIOPM_OurChangeWaitForPowerSettle
= 6,
305 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 7,
306 kIOPM_OurChangeTellCapabilityDidChange
= 8,
307 kIOPM_OurChangeFinish
= 9,
309 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
310 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
311 kIOPM_ParentChangeSetPowerState
= 12,
312 kIOPM_ParentChangeWaitForPowerSettle
= 13,
313 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
314 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
315 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
317 kIOPM_NotifyChildrenStart
= 17,
318 kIOPM_NotifyChildrenOrdered
= 18,
319 kIOPM_NotifyChildrenDelayed
= 19,
320 kIOPM_SyncTellClientsPowerDown
= 20,
321 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
322 kIOPM_SyncNotifyWillChange
= 22,
323 kIOPM_SyncNotifyDidChange
= 23,
324 kIOPM_SyncTellCapabilityDidChange
= 24,
325 kIOPM_SyncFinish
= 25,
326 kIOPM_TellCapabilityChangeDone
= 26,
327 kIOPM_DriverThreadCallDone
= 27,
329 kIOPM_BadMachineState
= 0xFFFFFFFF
332 //*********************************************************************************
335 // Initialize power management.
336 //*********************************************************************************
338 void IOService::PMinit( void )
342 if ( !gIOPMInitialized
)
344 gPlatform
= getPlatform();
345 gIOPMWorkLoop
= IOWorkLoop::workLoop();
348 gIOPMRequestQueue
= IOPMRequestQueue::create(
349 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
350 this, &IOService::actionPMRequestQueue
));
352 gIOPMReplyQueue
= IOPMRequestQueue::create(
353 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
354 this, &IOService::actionPMReplyQueue
));
356 gIOPMWorkQueue
= IOPMWorkQueue::create(this,
357 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
358 &IOService::actionPMWorkQueueInvoke
),
359 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
360 &IOService::actionPMWorkQueueRetire
));
362 gIOPMCompletionQueue
= IOPMCompletionQueue::create(
363 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
364 this, &IOService::actionPMCompletionQueue
));
366 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
369 gIOPMRequestQueue
->release();
370 gIOPMRequestQueue
= 0;
373 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
376 gIOPMReplyQueue
->release();
380 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
383 gIOPMWorkQueue
->release();
387 // Must be added after the work queue, which pushes request
388 // to the completion queue without signaling the work loop.
389 if (gIOPMWorkLoop
->addEventSource(gIOPMCompletionQueue
) !=
392 gIOPMCompletionQueue
->release();
393 gIOPMCompletionQueue
= 0;
396 gIOPMPowerClientDevice
=
397 OSSymbol::withCStringNoCopy( "DevicePowerState" );
399 gIOPMPowerClientDriver
=
400 OSSymbol::withCStringNoCopy( "DriverPowerState" );
402 gIOPMPowerClientChildProxy
=
403 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
405 gIOPMPowerClientChildren
=
406 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
408 gIOPMPowerClientAdvisoryTickle
=
409 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
411 gIOPMPowerClientRootDomain
=
412 OSSymbol::withCStringNoCopy( "RootDomainPower" );
414 gIOSpinDumpKextName
[0] = '\0';
415 gIOSpinDumpDelayType
[0] = '\0';
418 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMCompletionQueue
)
419 gIOPMInitialized
= true;
421 if (!gIOPMInitialized
)
424 pwrMgt
= new IOServicePM
;
426 setProperty(kPwrMgtKey
, pwrMgt
);
428 queue_init(&pwrMgt
->WorkChain
);
429 queue_init(&pwrMgt
->RequestHead
);
430 queue_init(&pwrMgt
->PMDriverCallQueue
);
433 fPMLock
= IOLockAlloc();
434 fInterestedDrivers
= new IOPMinformeeList
;
435 fInterestedDrivers
->initialize();
436 fDesiredPowerState
= kPowerStateZero
;
437 fDeviceDesire
= kPowerStateZero
;
438 fInitialPowerChange
= true;
439 fInitialSetPowerState
= true;
440 fPreviousRequestPowerFlags
= 0;
441 fDeviceOverrideEnabled
= false;
442 fMachineState
= kIOPM_Finished
;
443 fSavedMachineState
= kIOPM_BadMachineState
;
444 fIdleTimerMinPowerState
= kPowerStateZero
;
445 fActivityLock
= IOLockAlloc();
446 fStrictTreeOrder
= false;
447 fActivityTicklePowerState
= kInvalidTicklePowerState
;
448 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
449 fControllingDriver
= NULL
;
451 fNumberOfPowerStates
= 0;
452 fCurrentPowerState
= kPowerStateZero
;
453 fParentsCurrentPowerFlags
= 0;
454 fMaxPowerState
= kPowerStateZero
;
456 fParentsKnowState
= false;
458 fResponseArray
= NULL
;
459 fNotifyClientArray
= NULL
;
460 fCurrentPowerConsumption
= kIOPMUnknown
;
461 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
463 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot()))
465 gIOPMRootNode
= this;
466 fParentsKnowState
= true;
468 else if (getProperty(kIOPMResetPowerStateOnWakeKey
) == kOSBooleanTrue
)
470 fResetPowerStateOnWake
= true;
475 fWatchdogTimer
= thread_call_allocate(
476 &IOService::watchdog_timer_expired
, (thread_call_param_t
)this);
477 fWatchdogLock
= IOLockAlloc();
479 fBlockedArray
= OSArray::withCapacity(4);
482 fAckTimer
= thread_call_allocate(
483 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
484 fSettleTimer
= thread_call_allocate(
485 &settle_timer_expired
, (thread_call_param_t
)this);
486 fIdleTimer
= thread_call_allocate(
487 &idle_timer_expired
, (thread_call_param_t
)this);
488 fDriverCallEntry
= thread_call_allocate(
489 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
490 assert(fDriverCallEntry
);
491 if (kIOKextSpinDump
& gIOKitDebug
)
493 fSpinDumpTimer
= thread_call_allocate(
494 &IOService::spindump_timer_expired
, (thread_call_param_t
)this);
497 // Check for powerChangeDone override.
498 if (OSMemberFunctionCast(void (*)(void),
499 getResourceService(), &IOService::powerChangeDone
) !=
500 OSMemberFunctionCast(void (*)(void),
501 this, &IOService::powerChangeDone
))
503 fPCDFunctionOverride
= true;
507 IOPMprot
* prot
= new IOPMprot
;
511 prot
->ourName
= fName
;
512 prot
->thePlatform
= gPlatform
;
517 pm_vars
= (void *) (uintptr_t) true;
524 //*********************************************************************************
527 // Free the data created by PMinit. Only called from IOService::free().
528 //*********************************************************************************
530 void IOService::PMfree( void )
537 assert(fMachineState
== kIOPM_Finished
);
538 assert(fInsertInterestSet
== NULL
);
539 assert(fRemoveInterestSet
== NULL
);
540 assert(fNotifyChildArray
== NULL
);
541 assert(queue_empty(&pwrMgt
->RequestHead
));
542 assert(queue_empty(&fPMDriverCallQueue
));
544 if (fWatchdogTimer
) {
545 thread_call_cancel(fWatchdogTimer
);
546 thread_call_free(fWatchdogTimer
);
547 fWatchdogTimer
= NULL
;
551 IOLockFree(fWatchdogLock
);
552 fWatchdogLock
= NULL
;
556 fBlockedArray
->release();
557 fBlockedArray
= NULL
;
560 if ( fSettleTimer
) {
561 thread_call_cancel(fSettleTimer
);
562 thread_call_free(fSettleTimer
);
566 thread_call_cancel(fAckTimer
);
567 thread_call_free(fAckTimer
);
571 thread_call_cancel(fIdleTimer
);
572 thread_call_free(fIdleTimer
);
575 if ( fDriverCallEntry
) {
576 thread_call_free(fDriverCallEntry
);
577 fDriverCallEntry
= NULL
;
579 if ( fSpinDumpTimer
) {
580 thread_call_cancel(fSpinDumpTimer
);
581 thread_call_free(fSpinDumpTimer
);
582 fSpinDumpTimer
= NULL
;
588 if ( fActivityLock
) {
589 IOLockFree(fActivityLock
);
590 fActivityLock
= NULL
;
592 if ( fInterestedDrivers
) {
593 fInterestedDrivers
->release();
594 fInterestedDrivers
= NULL
;
596 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
597 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
598 fDriverCallParamPtr
= 0;
599 fDriverCallParamSlots
= 0;
601 if ( fResponseArray
) {
602 fResponseArray
->release();
603 fResponseArray
= NULL
;
605 if ( fNotifyClientArray
) {
606 fNotifyClientArray
->release();
607 fNotifyClientArray
= NULL
;
609 if (fPowerStates
&& fNumberOfPowerStates
) {
610 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
611 fNumberOfPowerStates
= 0;
615 fPowerClients
->release();
632 void IOService::PMDebug( uint32_t event
, uintptr_t param1
, uintptr_t param2
)
634 OUR_PMLog(event
, param1
, param2
);
637 //*********************************************************************************
638 // [public] joinPMtree
640 // A policy-maker calls its nub here when initializing, to be attached into
641 // the power management hierarchy. The default function is to call the
642 // platform expert, which knows how to do it. This method is overridden
643 // by a nub subclass which may either know how to do it, or may need to
644 // take other action.
646 // This may be the only "power management" method used in a nub,
647 // meaning it may not be initialized for power management.
648 //*********************************************************************************
650 void IOService::joinPMtree( IOService
* driver
)
652 IOPlatformExpert
* platform
;
654 platform
= getPlatform();
655 assert(platform
!= 0);
656 platform
->PMRegisterDevice(this, driver
);
660 //*********************************************************************************
661 // [deprecated] youAreRoot
663 // Power Managment is informing us that we are the root power domain.
664 //*********************************************************************************
666 IOReturn
IOService::youAreRoot( void )
670 #endif /* !__LP64__ */
672 //*********************************************************************************
675 // Immediately stop driver callouts. Schedule an async stop request to detach
677 //*********************************************************************************
679 void IOService::PMstop( void )
681 IOPMRequest
* request
;
688 if (fLockedFlags
.PMStop
)
690 PM_LOG2("%s: PMstop() already stopped\n", fName
);
695 // Inhibit future driver calls.
696 fLockedFlags
.PMStop
= true;
698 // Wait for all prior driver calls to finish.
699 waitForPMDriverCall();
703 // The rest of the work is performed async.
704 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
707 PM_LOG2("%s: %p PMstop\n", getName(), OBFUSCATE(this));
708 submitPMRequest( request
);
712 //*********************************************************************************
713 // [private] handlePMstop
715 // Disconnect the node from all parents and children in the power plane.
716 //*********************************************************************************
718 void IOService::handlePMstop( IOPMRequest
* request
)
722 IOPowerConnection
* connection
;
723 IOService
* theChild
;
724 IOService
* theParent
;
727 PM_LOG2("%s: %p %s start\n", getName(), OBFUSCATE(this), __FUNCTION__
);
729 // remove driver from prevent system sleep lists
730 getPMRootDomain()->updatePreventIdleSleepList(this, false);
731 getPMRootDomain()->updatePreventSystemSleepList(this, false);
733 // remove the property
734 removeProperty(kPwrMgtKey
);
737 iter
= getParentIterator(gIOPowerPlane
);
740 while ( (next
= iter
->getNextObject()) )
742 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
744 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
747 theParent
->removePowerChild(connection
);
748 theParent
->release();
755 // detach IOConnections
756 detachAbove( gIOPowerPlane
);
758 // no more power state changes
759 fParentsKnowState
= false;
762 iter
= getChildIterator(gIOPowerPlane
);
765 while ( (next
= iter
->getNextObject()) )
767 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
769 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
772 // detach nub from child
773 connection
->detachFromChild(theChild
, gIOPowerPlane
);
776 // detach us from nub
777 detachFromChild(connection
, gIOPowerPlane
);
783 // Remove all interested drivers from the list, including the power
784 // controlling driver.
786 // Usually, the controlling driver and the policy-maker functionality
787 // are implemented by the same object, and without the deregistration,
788 // the object will be holding an extra retain on itself, and cannot
791 if ( fInterestedDrivers
)
793 IOPMinformeeList
* list
= fInterestedDrivers
;
797 while ((item
= list
->firstInList()))
799 list
->removeFromList(item
->whatObject
);
804 // Clear idle period to prevent idleTimerExpired() from servicing
805 // idle timer expirations.
807 fIdleTimerPeriod
= 0;
808 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
811 PM_LOG2("%s: %p %s done\n", getName(), OBFUSCATE(this), __FUNCTION__
);
814 //*********************************************************************************
815 // [public] addPowerChild
817 // Power Management is informing us who our children are.
818 //*********************************************************************************
820 IOReturn
IOService::addPowerChild( IOService
* child
)
822 IOPowerConnection
* connection
= 0;
823 IOPMRequest
* requests
[3] = {0, 0, 0};
828 return kIOReturnBadArgument
;
830 if (!initialized
|| !child
->initialized
)
831 return IOPMNotYetInitialized
;
833 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
836 // Is this child already one of our children?
838 iter
= child
->getParentIterator( gIOPowerPlane
);
841 IORegistryEntry
* entry
;
844 while ((next
= iter
->getNextObject()))
846 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
847 isChild(entry
, gIOPowerPlane
))
857 PM_LOG("%s: %s (%p) is already a child\n",
858 getName(), child
->getName(), OBFUSCATE(child
));
862 // Add the child to the power plane immediately, but the
863 // joining connection is marked as not ready.
864 // We want the child to appear in the power plane before
865 // returning to the caller, but don't want the caller to
866 // block on the PM work loop.
868 connection
= new IOPowerConnection
;
872 // Create a chain of PM requests to perform the bottom-half
873 // work from the PM work loop.
875 requests
[0] = acquirePMRequest(
877 /* type */ kIOPMRequestTypeAddPowerChild1
);
879 requests
[1] = acquirePMRequest(
881 /* type */ kIOPMRequestTypeAddPowerChild2
);
883 requests
[2] = acquirePMRequest(
885 /* type */ kIOPMRequestTypeAddPowerChild3
);
887 if (!requests
[0] || !requests
[1] || !requests
[2])
890 requests
[0]->attachNextRequest( requests
[1] );
891 requests
[1]->attachNextRequest( requests
[2] );
894 connection
->start(this);
895 connection
->setAwaitingAck(false);
896 connection
->setReadyFlag(false);
898 attachToChild( connection
, gIOPowerPlane
);
899 connection
->attachToChild( child
, gIOPowerPlane
);
901 // connection needs to be released
902 requests
[0]->fArg0
= connection
;
903 requests
[1]->fArg0
= connection
;
904 requests
[2]->fArg0
= connection
;
906 submitPMRequests( requests
, 3 );
907 return kIOReturnSuccess
;
911 if (connection
) connection
->release();
912 if (requests
[0]) releasePMRequest(requests
[0]);
913 if (requests
[1]) releasePMRequest(requests
[1]);
914 if (requests
[2]) releasePMRequest(requests
[2]);
916 // Silent failure, to prevent platform drivers from adding the child
917 // to the root domain.
919 return kIOReturnSuccess
;
922 //*********************************************************************************
923 // [private] addPowerChild1
925 // Step 1/3 of adding a power child. Called on the power parent.
926 //*********************************************************************************
928 void IOService::addPowerChild1( IOPMRequest
* request
)
930 IOPMPowerStateIndex tempDesire
= kPowerStateZero
;
932 // Make us temporary usable before adding the child.
935 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
937 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
939 tempDesire
= fHighestPowerState
;
942 if ((tempDesire
!= kPowerStateZero
) &&
943 (IS_PM_ROOT
|| (StateOrder(fMaxPowerState
) >= StateOrder(tempDesire
))))
945 adjustPowerState(tempDesire
);
949 //*********************************************************************************
950 // [private] addPowerChild2
952 // Step 2/3 of adding a power child. Called on the joining child.
953 // Execution blocked behind addPowerChild1.
954 //*********************************************************************************
956 void IOService::addPowerChild2( IOPMRequest
* request
)
958 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
960 IOPMPowerFlags powerFlags
;
962 unsigned long powerState
;
963 unsigned long tempDesire
;
966 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
968 if (!parent
|| !inPlane(gIOPowerPlane
))
970 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
974 // Parent will be waiting for us to complete this stage.
975 // It is safe to directly access parent's vars.
977 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
978 powerState
= parent
->fCurrentPowerState
;
981 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
985 // Set our power parent.
987 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
989 setParentInfo( powerFlags
, connection
, knowsState
);
991 connection
->setReadyFlag(true);
993 if ( fControllingDriver
&& fParentsKnowState
)
995 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
996 // initially change into the state we are already in
997 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
998 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
999 adjustPowerState(tempDesire
);
1002 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
1005 //*********************************************************************************
1006 // [private] addPowerChild3
1008 // Step 3/3 of adding a power child. Called on the parent.
1009 // Execution blocked behind addPowerChild2.
1010 //*********************************************************************************
1012 void IOService::addPowerChild3( IOPMRequest
* request
)
1014 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
1016 IOPMrootDomain
* rootDomain
= getPMRootDomain();
1018 PM_ASSERT_IN_GATE();
1019 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
1021 if (child
&& inPlane(gIOPowerPlane
))
1023 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder"))
1025 PM_LOG1("%s: strict PM order enforced\n", getName());
1026 fStrictTreeOrder
= true;
1030 rootDomain
->joinAggressiveness( child
);
1034 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1037 connection
->release();
1041 //*********************************************************************************
1042 // [deprecated] setPowerParent
1044 // Power Management is informing us who our parent is.
1045 // If we have a controlling driver, find out, given our newly-informed
1046 // power domain state, what state it would be in, and then tell it
1047 // to assume that state.
1048 //*********************************************************************************
1050 IOReturn
IOService::setPowerParent(
1051 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
1053 return kIOReturnUnsupported
;
1055 #endif /* !__LP64__ */
1057 //*********************************************************************************
1058 // [public] removePowerChild
1060 // Called on a parent whose child is being removed by PMstop().
1061 //*********************************************************************************
1063 IOReturn
IOService::removePowerChild( IOPowerConnection
* theNub
)
1065 IORegistryEntry
* theChild
;
1067 PM_ASSERT_IN_GATE();
1068 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1072 // detach nub from child
1073 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1076 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1077 theChild
->release();
1079 // detach from the nub
1080 detachFromChild(theNub
, gIOPowerPlane
);
1082 // Are we awaiting an ack from this child?
1083 if ( theNub
->getAwaitingAck() )
1085 // yes, pretend we got one
1086 theNub
->setAwaitingAck(false);
1087 if (fHeadNotePendingAcks
!= 0 )
1089 // that's one fewer ack to worry about
1090 fHeadNotePendingAcks
--;
1092 // is that the last?
1093 if ( fHeadNotePendingAcks
== 0 )
1096 getPMRootDomain()->reset_watchdog_timer(this, 0);
1098 // This parent may have a request in the work queue that is
1099 // blocked on fHeadNotePendingAcks=0. And removePowerChild()
1100 // is called while executing the child's PMstop request so they
1101 // can occur simultaneously. IOPMWorkQueue::checkForWork() must
1102 // restart and check all request queues again.
1104 gIOPMWorkQueue
->incrementProducerCount();
1111 // A child has gone away, re-scan children desires and clamp bits.
1112 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1114 if (!fAdjustPowerScheduled
)
1116 IOPMRequest
* request
;
1117 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1120 submitPMRequest( request
);
1121 fAdjustPowerScheduled
= true;
1128 //*********************************************************************************
1129 // [public] registerPowerDriver
1131 // A driver has called us volunteering to control power to our device.
1132 //*********************************************************************************
1134 IOReturn
IOService::registerPowerDriver(
1135 IOService
* powerDriver
,
1136 IOPMPowerState
* powerStates
,
1137 unsigned long numberOfStates
)
1139 IOPMRequest
* request
;
1140 IOPMPSEntry
* powerStatesCopy
= 0;
1141 IOPMPowerStateIndex stateOrder
;
1142 IOReturn error
= kIOReturnSuccess
;
1145 return IOPMNotYetInitialized
;
1147 if (!powerStates
|| (numberOfStates
< 2))
1149 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1150 return kIOReturnBadArgument
;
1153 if (!powerDriver
|| !powerDriver
->initialized
)
1155 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1156 return kIOReturnBadArgument
;
1159 if (powerStates
[0].version
> kIOPMPowerStateVersion2
)
1161 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1162 return kIOReturnBadArgument
;
1166 // Make a copy of the supplied power state array.
1167 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1168 if (!powerStatesCopy
)
1170 error
= kIOReturnNoMemory
;
1174 // Initialize to bogus values
1175 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1176 powerStatesCopy
[i
].stateOrderToIndex
= kIOPMPowerStateMax
;
1178 for (uint32_t i
= 0; i
< numberOfStates
; i
++)
1180 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1181 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1182 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1183 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1184 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1185 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1186 if (powerStates
[i
].version
>= kIOPMPowerStateVersion2
)
1187 stateOrder
= powerStates
[i
].stateOrder
;
1191 if (stateOrder
< numberOfStates
)
1193 powerStatesCopy
[i
].stateOrder
= stateOrder
;
1194 powerStatesCopy
[stateOrder
].stateOrderToIndex
= i
;
1198 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1200 if (powerStatesCopy
[i
].stateOrderToIndex
== kIOPMPowerStateMax
)
1202 // power state order missing
1203 error
= kIOReturnBadArgument
;
1207 if (kIOReturnSuccess
!= error
)
1210 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1213 error
= kIOReturnNoMemory
;
1217 powerDriver
->retain();
1218 request
->fArg0
= (void *) powerDriver
;
1219 request
->fArg1
= (void *) powerStatesCopy
;
1220 request
->fArg2
= (void *) numberOfStates
;
1222 submitPMRequest( request
);
1223 return kIOReturnSuccess
;
1227 if (powerStatesCopy
)
1228 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1233 //*********************************************************************************
1234 // [private] handleRegisterPowerDriver
1235 //*********************************************************************************
1237 void IOService::handleRegisterPowerDriver( IOPMRequest
* request
)
1239 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1240 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1241 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1242 unsigned long i
, stateIndex
;
1243 unsigned long lowestPowerState
;
1247 PM_ASSERT_IN_GATE();
1248 assert(powerStates
);
1249 assert(powerDriver
);
1250 assert(numberOfStates
> 1);
1252 if ( !fNumberOfPowerStates
)
1254 OUR_PMLog(kPMLogControllingDriver
,
1255 (unsigned long) numberOfStates
,
1256 (unsigned long) kIOPMPowerStateVersion1
);
1258 fPowerStates
= powerStates
;
1259 fNumberOfPowerStates
= numberOfStates
;
1260 fControllingDriver
= powerDriver
;
1261 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1263 lowestPowerState
= fPowerStates
[0].stateOrderToIndex
;
1264 fHighestPowerState
= fPowerStates
[numberOfStates
- 1].stateOrderToIndex
;
1266 // OR'in all the output power flags
1267 fMergedOutputPowerFlags
= 0;
1268 fDeviceUsablePowerState
= lowestPowerState
;
1269 for ( i
= 0; i
< numberOfStates
; i
++ )
1271 fMergedOutputPowerFlags
|= fPowerStates
[i
].outputPowerFlags
;
1273 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
1274 assert(stateIndex
< numberOfStates
);
1275 if ((fDeviceUsablePowerState
== lowestPowerState
) &&
1276 (fPowerStates
[stateIndex
].capabilityFlags
& IOPMDeviceUsable
))
1278 // The minimum power state that the device is usable
1279 fDeviceUsablePowerState
= stateIndex
;
1283 // Register powerDriver as interested, unless already done.
1284 // We don't want to register the default implementation since
1285 // it does nothing. One ramification of not always registering
1286 // is the one fewer retain count held.
1288 root
= getPlatform()->getProvider();
1291 ((OSMemberFunctionCast(void (*)(void),
1292 root
, &IOService::powerStateDidChangeTo
)) !=
1293 ((OSMemberFunctionCast(void (*)(void),
1294 this, &IOService::powerStateDidChangeTo
)))) ||
1295 ((OSMemberFunctionCast(void (*)(void),
1296 root
, &IOService::powerStateWillChangeTo
)) !=
1297 ((OSMemberFunctionCast(void (*)(void),
1298 this, &IOService::powerStateWillChangeTo
)))))
1300 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
)
1303 fInterestedDrivers
->appendNewInformee(powerDriver
);
1308 // Examine all existing power clients and perform limit check.
1310 if (fPowerClients
&&
1311 (iter
= OSCollectionIterator::withCollection(fPowerClients
)))
1313 const OSSymbol
* client
;
1314 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
1316 IOPMPowerStateIndex powerState
= getPowerStateForClient(client
);
1317 if (powerState
>= numberOfStates
)
1319 updatePowerClient(client
, fHighestPowerState
);
1325 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1327 IOPMPowerStateIndex tempDesire
;
1328 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1329 // initially change into the state we are already in
1330 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1331 adjustPowerState(tempDesire
);
1336 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1337 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1340 powerDriver
->release();
1343 //*********************************************************************************
1344 // [public] registerInterestedDriver
1346 // Add the caller to our list of interested drivers and return our current
1347 // power state. If we don't have a power-controlling driver yet, we will
1348 // call this interested driver again later when we do get a driver and find
1349 // out what the current power state of the device is.
1350 //*********************************************************************************
1352 IOPMPowerFlags
IOService::registerInterestedDriver( IOService
* driver
)
1354 IOPMRequest
* request
;
1357 if (!driver
|| !initialized
|| !fInterestedDrivers
)
1361 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1362 if (fInsertInterestSet
== NULL
)
1363 fInsertInterestSet
= OSSet::withCapacity(4);
1364 if (fInsertInterestSet
)
1366 fInsertInterestSet
->setObject(driver
);
1367 if (fRemoveInterestSet
)
1368 fRemoveInterestSet
->removeObject(driver
);
1374 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1376 submitPMRequest( request
);
1379 // This return value cannot be trusted, but return a value
1380 // for those clients that care.
1382 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1383 return kIOPMDeviceUsable
;
1386 //*********************************************************************************
1387 // [public] deRegisterInterestedDriver
1388 //*********************************************************************************
1390 IOReturn
IOService::deRegisterInterestedDriver( IOService
* driver
)
1392 IOPMinformee
* item
;
1393 IOPMRequest
* request
;
1397 return kIOReturnBadArgument
;
1398 if (!initialized
|| !fInterestedDrivers
)
1399 return IOPMNotPowerManaged
;
1402 if (fInsertInterestSet
)
1404 fInsertInterestSet
->removeObject(driver
);
1407 item
= fInterestedDrivers
->findItem(driver
);
1411 return kIOReturnNotFound
;
1414 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1415 if (fRemoveInterestSet
== NULL
)
1416 fRemoveInterestSet
= OSSet::withCapacity(4);
1417 if (fRemoveInterestSet
)
1419 fRemoveInterestSet
->setObject(driver
);
1422 item
->active
= false;
1423 waitForPMDriverCall( driver
);
1430 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1432 submitPMRequest( request
);
1438 //*********************************************************************************
1439 // [private] handleInterestChanged
1441 // Handle interest added or removed.
1442 //*********************************************************************************
1444 void IOService::handleInterestChanged( IOPMRequest
* request
)
1447 IOPMinformee
* informee
;
1448 IOPMinformeeList
* list
= fInterestedDrivers
;
1452 if (fInsertInterestSet
)
1454 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject()))
1456 if (list
->findItem(driver
) == NULL
)
1458 informee
= list
->appendNewInformee(driver
);
1460 fInsertInterestSet
->removeObject(driver
);
1462 fInsertInterestSet
->release();
1463 fInsertInterestSet
= 0;
1466 if (fRemoveInterestSet
)
1468 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject()))
1470 informee
= list
->findItem(driver
);
1473 // Clean-up async interest acknowledgement
1474 if (fHeadNotePendingAcks
&& informee
->timer
)
1476 informee
->timer
= 0;
1477 fHeadNotePendingAcks
--;
1479 list
->removeFromList(driver
);
1481 fRemoveInterestSet
->removeObject(driver
);
1483 fRemoveInterestSet
->release();
1484 fRemoveInterestSet
= 0;
1490 //*********************************************************************************
1491 // [public] acknowledgePowerChange
1493 // After we notified one of the interested drivers or a power-domain child
1494 // of an impending change in power, it has called to say it is now
1495 // prepared for the change. If this object is the last to
1496 // acknowledge this change, we take whatever action we have been waiting
1498 // That may include acknowledging to our parent. In this case, we do it
1499 // last of all to insure that this doesn't cause the parent to call us some-
1500 // where else and alter data we are relying on here (like the very existance
1501 // of a "current change note".)
1502 //*********************************************************************************
1504 IOReturn
IOService::acknowledgePowerChange( IOService
* whichObject
)
1506 IOPMRequest
* request
;
1509 return IOPMNotYetInitialized
;
1511 return kIOReturnBadArgument
;
1513 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1515 return kIOReturnNoMemory
;
1517 whichObject
->retain();
1518 request
->fArg0
= whichObject
;
1520 submitPMRequest( request
);
1524 //*********************************************************************************
1525 // [private] handleAcknowledgePowerChange
1526 //*********************************************************************************
1528 bool IOService::handleAcknowledgePowerChange( IOPMRequest
* request
)
1530 IOPMinformee
* informee
;
1531 unsigned long childPower
= kIOPMUnknown
;
1532 IOService
* theChild
;
1533 IOService
* whichObject
;
1534 bool all_acked
= false;
1536 PM_ASSERT_IN_GATE();
1537 whichObject
= (IOService
*) request
->fArg0
;
1538 assert(whichObject
);
1540 // one of our interested drivers?
1541 informee
= fInterestedDrivers
->findItem( whichObject
);
1542 if ( informee
== NULL
)
1544 if ( !isChild(whichObject
, gIOPowerPlane
) )
1546 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1549 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1552 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1555 if ( fHeadNotePendingAcks
!= 0 )
1557 assert(fPowerStates
!= NULL
);
1559 // yes, make sure we're expecting acks
1560 if ( informee
!= NULL
)
1562 // it's an interested driver
1563 // make sure we're expecting this ack
1564 if ( informee
->timer
!= 0 )
1567 if (informee
->timer
> 0)
1569 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1570 if (nsec
> LOG_SETPOWER_TIMES
) {
1571 getPMRootDomain()->pmStatsRecordApplicationResponse(
1572 gIOPMStatsDriverPSChangeSlow
, informee
->whatObject
->getName(),
1573 fDriverCallReason
, NS_TO_MS(nsec
), informee
->whatObject
->getRegistryEntryID(),
1574 NULL
, fHeadNotePowerState
);
1579 informee
->timer
= 0;
1580 // that's one fewer to worry about
1581 fHeadNotePendingAcks
--;
1583 // this driver has already acked
1584 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1588 // make sure we're expecting this ack
1589 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1591 // that's one fewer to worry about
1592 fHeadNotePendingAcks
--;
1593 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1594 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1597 childPower
= theChild
->currentPowerConsumption();
1598 theChild
->release();
1600 if ( childPower
== kIOPMUnknown
)
1602 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1604 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
1606 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1612 if ( fHeadNotePendingAcks
== 0 ) {
1613 // yes, stop the timer
1615 // and now we can continue
1617 getPMRootDomain()->reset_watchdog_timer(this, 0);
1620 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1625 whichObject
->release();
1630 //*********************************************************************************
1631 // [public] acknowledgeSetPowerState
1633 // After we instructed our controlling driver to change power states,
1634 // it has called to say it has finished doing so.
1635 // We continue to process the power state change.
1636 //*********************************************************************************
1638 IOReturn
IOService::acknowledgeSetPowerState( void )
1640 IOPMRequest
* request
;
1643 return IOPMNotYetInitialized
;
1645 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1647 return kIOReturnNoMemory
;
1649 submitPMRequest( request
);
1650 return kIOReturnSuccess
;
1653 //*********************************************************************************
1654 // [private] adjustPowerState
1655 //*********************************************************************************
1657 void IOService::adjustPowerState( uint32_t clamp
)
1659 PM_ASSERT_IN_GATE();
1660 computeDesiredState(clamp
, false);
1661 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
))
1663 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1665 // Indicate that children desires must be ignored, and do not ask
1666 // apps for permission to drop power. This is used by root domain
1667 // for demand sleep.
1669 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
1670 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1673 /* flags */ changeFlags
,
1674 /* power state */ fDesiredPowerState
,
1675 /* domain flags */ 0,
1677 /* parent flags */ 0);
1681 //*********************************************************************************
1682 // [public] synchronizePowerTree
1683 //*********************************************************************************
1685 IOReturn
IOService::synchronizePowerTree(
1686 IOOptionBits options
,
1687 IOService
* notifyRoot
)
1689 IOPMRequest
* request_c
= 0;
1690 IOPMRequest
* request_s
;
1692 if (this != getPMRootDomain())
1693 return kIOReturnBadArgument
;
1695 return kIOPMNotYetInitialized
;
1697 OUR_PMLog(kPMLogCSynchronizePowerTree
, options
, (notifyRoot
!= 0));
1703 // Cancels don't need to be synchronized.
1704 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1705 if (nr
) submitPMRequest(nr
);
1706 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1707 if (nr
) submitPMRequest(nr
);
1710 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1712 goto error_no_memory
;
1714 if (options
& kIOPMSyncCancelPowerDown
)
1715 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1718 request_c
->attachNextRequest( request_s
);
1719 submitPMRequest(request_c
);
1722 request_s
->fArg0
= (void *)(uintptr_t) options
;
1723 submitPMRequest(request_s
);
1725 return kIOReturnSuccess
;
1728 if (request_c
) releasePMRequest(request_c
);
1729 if (request_s
) releasePMRequest(request_s
);
1730 return kIOReturnNoMemory
;
1733 //*********************************************************************************
1734 // [private] handleSynchronizePowerTree
1735 //*********************************************************************************
1737 void IOService::handleSynchronizePowerTree( IOPMRequest
* request
)
1739 PM_ASSERT_IN_GATE();
1740 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1741 (fCurrentPowerState
== fHighestPowerState
))
1743 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1746 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1747 (options
& kIOPMSyncNoChildNotify
),
1748 /* power state */ fCurrentPowerState
,
1749 /* domain flags */ 0,
1751 /* parent flags */ 0);
1756 //*********************************************************************************
1757 // [deprecated] powerDomainWillChangeTo
1759 // Called by the power-hierarchy parent notifying of a new power state
1760 // in the power domain.
1761 // We enqueue a parent power-change to our queue of power changes.
1762 // This may or may not cause us to change power, depending on what
1763 // kind of change is occuring in the domain.
1764 //*********************************************************************************
1766 IOReturn
IOService::powerDomainWillChangeTo(
1767 IOPMPowerFlags newPowerFlags
,
1768 IOPowerConnection
* whichParent
)
1771 return kIOReturnUnsupported
;
1773 #endif /* !__LP64__ */
1775 //*********************************************************************************
1776 // [private] handlePowerDomainWillChangeTo
1777 //*********************************************************************************
1779 void IOService::handlePowerDomainWillChangeTo( IOPMRequest
* request
)
1781 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1782 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1783 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1784 IOPMPowerChangeFlags myChangeFlags
;
1787 IOPowerConnection
* connection
;
1788 IOPMPowerStateIndex maxPowerState
;
1789 IOPMPowerFlags combinedPowerFlags
;
1790 bool savedParentsKnowState
;
1791 IOReturn result
= IOPMAckImplied
;
1793 PM_ASSERT_IN_GATE();
1794 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1796 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1798 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1802 savedParentsKnowState
= fParentsKnowState
;
1804 // Combine parents' output power flags.
1806 combinedPowerFlags
= 0;
1808 iter
= getParentIterator(gIOPowerPlane
);
1811 while ( (next
= iter
->getNextObject()) )
1813 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1815 if ( connection
== whichParent
)
1816 combinedPowerFlags
|= parentPowerFlags
;
1818 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1824 // If our initial change has yet to occur, then defer the power change
1825 // until after the power domain has completed its power transition.
1827 if ( fControllingDriver
&& !fInitialPowerChange
)
1829 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1830 combinedPowerFlags
);
1832 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1834 // fMaxPowerState set a limit on self-initiated power changes.
1835 // Update it before a parent power drop.
1836 fMaxPowerState
= maxPowerState
;
1839 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1840 // to avoid propagating the root change flags if any service must
1841 // change power state due to root's will-change notification.
1842 // Root does not change power state for kIOPMSynchronize.
1844 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1845 (parentChangeFlags
& kIOPMSynchronize
);
1847 result
= startPowerChange(
1848 /* flags */ myChangeFlags
,
1849 /* power state */ maxPowerState
,
1850 /* domain flags */ combinedPowerFlags
,
1851 /* connection */ whichParent
,
1852 /* parent flags */ parentPowerFlags
);
1855 // If parent is dropping power, immediately update the parent's
1856 // capability flags. Any future merging of parent(s) combined
1857 // power flags should account for this power drop.
1859 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1861 setParentInfo(parentPowerFlags
, whichParent
, true);
1864 // Parent is expecting an ACK from us. If we did not embark on a state
1865 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1866 // still required to issue an ACK to our parent.
1868 if (IOPMAckImplied
== result
)
1871 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1875 parent
->acknowledgePowerChange( whichParent
);
1881 // Drop the retain from notifyChild().
1882 if (whichParent
) whichParent
->release();
1886 //*********************************************************************************
1887 // [deprecated] powerDomainDidChangeTo
1889 // Called by the power-hierarchy parent after the power state of the power domain
1890 // has settled at a new level.
1891 // We enqueue a parent power-change to our queue of power changes.
1892 // This may or may not cause us to change power, depending on what
1893 // kind of change is occuring in the domain.
1894 //*********************************************************************************
1896 IOReturn
IOService::powerDomainDidChangeTo(
1897 IOPMPowerFlags newPowerFlags
,
1898 IOPowerConnection
* whichParent
)
1901 return kIOReturnUnsupported
;
1903 #endif /* !__LP64__ */
1905 //*********************************************************************************
1906 // [private] handlePowerDomainDidChangeTo
1907 //*********************************************************************************
1909 void IOService::handlePowerDomainDidChangeTo( IOPMRequest
* request
)
1911 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1912 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1913 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1914 IOPMPowerChangeFlags myChangeFlags
;
1915 IOPMPowerStateIndex maxPowerState
;
1916 IOPMPowerStateIndex initialDesire
= kPowerStateZero
;
1917 bool computeDesire
= false;
1918 bool desireChanged
= false;
1919 bool savedParentsKnowState
;
1920 IOReturn result
= IOPMAckImplied
;
1922 PM_ASSERT_IN_GATE();
1923 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1925 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1927 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1931 savedParentsKnowState
= fParentsKnowState
;
1933 setParentInfo(parentPowerFlags
, whichParent
, true);
1935 if ( fControllingDriver
)
1937 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1938 fParentsCurrentPowerFlags
);
1940 if ((parentChangeFlags
& kIOPMDomainPowerDrop
) == 0)
1942 // fMaxPowerState set a limit on self-initiated power changes.
1943 // Update it after a parent power rise.
1944 fMaxPowerState
= maxPowerState
;
1947 if (fInitialPowerChange
)
1949 computeDesire
= true;
1950 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1951 fParentsCurrentPowerFlags
);
1953 else if (parentChangeFlags
& kIOPMRootChangeUp
)
1955 if (fAdvisoryTickleUsed
)
1957 // On system wake, re-compute the desired power state since
1958 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1959 // which is an input to computeDesiredState(). This is not
1960 // necessary for a dark wake because powerChangeDone() will
1961 // handle the dark to full wake case, but it does no harm.
1963 desireChanged
= true;
1966 if (fResetPowerStateOnWake
)
1968 // Query the driver for the desired power state on system wake.
1969 // Default implementation returns the lowest power state.
1971 IOPMPowerStateIndex wakePowerState
=
1972 fControllingDriver
->initialPowerStateForDomainState(
1973 kIOPMRootDomainState
| kIOPMPowerOn
);
1975 // fDesiredPowerState was adjusted before going to sleep
1976 // with fDeviceDesire at min.
1978 if (StateOrder(wakePowerState
) > StateOrder(fDesiredPowerState
))
1980 // Must schedule a power adjustment if we changed the
1981 // device desire. That will update the desired domain
1982 // power on the parent power connection and ping the
1983 // power parent if necessary.
1985 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1986 desireChanged
= true;
1991 if (computeDesire
|| desireChanged
)
1992 computeDesiredState(initialDesire
, false);
1994 // Absorb and propagate parent's broadcast flags
1995 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1996 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1998 result
= startPowerChange(
1999 /* flags */ myChangeFlags
,
2000 /* power state */ maxPowerState
,
2001 /* domain flags */ fParentsCurrentPowerFlags
,
2002 /* connection */ whichParent
,
2003 /* parent flags */ 0);
2006 // Parent is expecting an ACK from us. If we did not embark on a state
2007 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
2008 // still required to issue an ACK to our parent.
2010 if (IOPMAckImplied
== result
)
2013 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
2017 parent
->acknowledgePowerChange( whichParent
);
2022 // If the parent registers its power driver late, then this is the
2023 // first opportunity to tell our parent about our desire. Or if the
2024 // child's desire changed during a parent change notify.
2026 if (fControllingDriver
&&
2027 ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
))
2029 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
2030 getName(), fParentsKnowState
);
2031 requestDomainPower( fDesiredPowerState
);
2035 // Drop the retain from notifyChild().
2036 if (whichParent
) whichParent
->release();
2039 //*********************************************************************************
2040 // [private] setParentInfo
2042 // Set our connection data for one specific parent, and then combine all the parent
2044 //*********************************************************************************
2046 void IOService::setParentInfo(
2047 IOPMPowerFlags newPowerFlags
,
2048 IOPowerConnection
* whichParent
,
2053 IOPowerConnection
* conn
;
2055 PM_ASSERT_IN_GATE();
2057 // set our connection data
2058 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
2059 whichParent
->setParentKnowsState(knowsState
);
2061 // recompute our parent info
2062 fParentsCurrentPowerFlags
= 0;
2063 fParentsKnowState
= true;
2065 iter
= getParentIterator(gIOPowerPlane
);
2068 while ( (next
= iter
->getNextObject()) )
2070 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
2072 fParentsKnowState
&= conn
->parentKnowsState();
2073 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
2080 //******************************************************************************
2081 // [private] trackSystemSleepPreventers
2082 //******************************************************************************
2084 void IOService::trackSystemSleepPreventers(
2085 IOPMPowerStateIndex oldPowerState
,
2086 IOPMPowerStateIndex newPowerState
,
2087 IOPMPowerChangeFlags changeFlags __unused
)
2089 IOPMPowerFlags oldCapability
, newCapability
;
2091 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2092 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2093 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2094 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2096 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)
2098 if (oldCapability
== newCapability
)
2101 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
)
2103 bool enablePrevention
= ((oldCapability
& kIOPMPreventIdleSleep
) == 0);
2104 bool idleCancelAllowed
= getPMRootDomain()->updatePreventIdleSleepList(
2105 this, enablePrevention
);
2106 #if SUPPORT_IDLE_CANCEL
2107 if (idleCancelAllowed
&& enablePrevention
)
2109 IOPMRequest
* cancelRequest
;
2111 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2114 submitPMRequest( cancelRequest
);
2120 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
)
2122 getPMRootDomain()->updatePreventSystemSleepList(this,
2123 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2127 //*********************************************************************************
2128 // [public] requestPowerDomainState
2130 // Called on a power parent when a child's power requirement changes.
2131 //*********************************************************************************
2133 IOReturn
IOService::requestPowerDomainState(
2134 IOPMPowerFlags childRequestPowerFlags
,
2135 IOPowerConnection
* childConnection
,
2136 unsigned long specification
)
2138 IOPMPowerStateIndex order
, powerState
;
2139 IOPMPowerFlags outputPowerFlags
;
2141 IOPMRequest
* subRequest
;
2142 bool adjustPower
= false;
2145 return IOPMNotYetInitialized
;
2147 if (gIOPMWorkLoop
->onThread() == false)
2149 PM_LOG("%s::requestPowerDomainState\n", getName());
2150 return kIOReturnSuccess
;
2153 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2155 if (!isChild(childConnection
, gIOPowerPlane
))
2156 return kIOReturnNotAttached
;
2158 if (!fControllingDriver
|| !fNumberOfPowerStates
)
2159 return kIOReturnNotReady
;
2161 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2164 // Remove flags from child request which we can't possibly supply
2165 childRequestPowerFlags
&= fMergedOutputPowerFlags
;
2167 // Merge in the power flags contributed by this power parent
2168 // at its current or impending power state.
2170 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2171 if (fMachineState
!= kIOPM_Finished
)
2173 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
)
2175 // Use the lower power state when dropping power.
2176 // Must be careful since a power drop can be cancelled
2177 // from the following states:
2178 // - kIOPM_OurChangeTellClientsPowerDown
2179 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2181 // The child must not wait for this parent to raise power
2182 // if the power drop was cancelled. The solution is to cancel
2183 // the power drop if possible, then schedule an adjustment to
2184 // re-evaluate the parent's power state.
2186 // Root domain is excluded to avoid idle sleep issues. And allow
2187 // root domain children to pop up when system is going to sleep.
2189 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2190 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
2192 fDoNotPowerDown
= true; // cancel power drop
2193 adjustPower
= true; // schedule an adjustment
2194 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2195 getName(), fMachineState
, child
->getName());
2199 // Beyond cancellation point, report the impending state.
2201 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2204 else if (IS_POWER_RISE
)
2206 // When raising power, must report the output power flags from
2207 // child's perspective. A child power request may arrive while
2208 // parent is transitioning upwards. If a request arrives after
2209 // setParentInfo() has already recorded the output power flags
2210 // for the next power state, then using the power supplied by
2211 // fCurrentPowerState is incorrect, and might cause the child
2212 // to wait when it should not.
2214 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2217 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2219 // Map child's requested power flags to one of our power state.
2221 for (order
= 0; order
< fNumberOfPowerStates
; order
++)
2223 powerState
= fPowerStates
[order
].stateOrderToIndex
;
2224 if ((fPowerStates
[powerState
].outputPowerFlags
& childRequestPowerFlags
)
2225 == childRequestPowerFlags
)
2228 if (order
>= fNumberOfPowerStates
)
2230 powerState
= kPowerStateZero
;
2233 // Conditions that warrants a power adjustment on this parent.
2234 // Adjust power will also propagate any changes to the child's
2235 // prevent idle/sleep flags towards the root domain.
2237 if (!childConnection
->childHasRequestedPower() ||
2238 (powerState
!= childConnection
->getDesiredDomainState()))
2241 #if ENABLE_DEBUG_LOGS
2244 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2245 getName(), child
->getName(),
2246 !childConnection
->childHasRequestedPower(),
2247 (uint32_t) childConnection
->getDesiredDomainState(),
2248 (uint32_t) powerState
);
2252 // Record the child's desires on the connection.
2253 childConnection
->setChildHasRequestedPower();
2254 childConnection
->setDesiredDomainState( powerState
);
2256 // Schedule a request to re-evaluate all children desires and
2257 // adjust power state. Submit a request if one wasn't pending,
2258 // or if the current request is part of a call tree.
2260 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2261 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest()))
2263 subRequest
= acquirePMRequest(
2264 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2267 submitPMRequest( subRequest
);
2268 fAdjustPowerScheduled
= true;
2272 return kIOReturnSuccess
;
2275 //*********************************************************************************
2276 // [public] temporaryPowerClampOn
2278 // A power domain wants to clamp its power on till it has children which
2279 // will thendetermine the power domain state.
2281 // We enter the highest state until addPowerChild is called.
2282 //*********************************************************************************
2284 IOReturn
IOService::temporaryPowerClampOn( void )
2286 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2289 //*********************************************************************************
2290 // [public] makeUsable
2292 // Some client of our device is asking that we become usable. Although
2293 // this has not come from a subclassed device object, treat it exactly
2294 // as if it had. In this way, subsequent requests for lower power from
2295 // a subclassed device object will pre-empt this request.
2297 // We treat this as a subclass object request to switch to the
2298 // highest power state.
2299 //*********************************************************************************
2301 IOReturn
IOService::makeUsable( void )
2303 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2304 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2307 //*********************************************************************************
2308 // [public] currentCapability
2309 //*********************************************************************************
2311 IOPMPowerFlags
IOService::currentCapability( void )
2314 return IOPMNotPowerManaged
;
2316 return fCurrentCapabilityFlags
;
2319 //*********************************************************************************
2320 // [public] changePowerStateTo
2322 // Called by our power-controlling driver to change power state. The new desired
2323 // power state is computed and compared against the current power state. If those
2324 // power states differ, then a power state change is initiated.
2325 //*********************************************************************************
2327 IOReturn
IOService::changePowerStateTo( unsigned long ordinal
)
2329 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2330 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2333 //*********************************************************************************
2334 // [protected] changePowerStateToPriv
2336 // Called by our driver subclass to change power state. The new desired power
2337 // state is computed and compared against the current power state. If those
2338 // power states differ, then a power state change is initiated.
2339 //*********************************************************************************
2341 IOReturn
IOService::changePowerStateToPriv( unsigned long ordinal
)
2343 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2344 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2347 //*********************************************************************************
2348 // [public] changePowerStateWithOverrideTo
2350 // Called by our driver subclass to change power state. The new desired power
2351 // state is computed and compared against the current power state. If those
2352 // power states differ, then a power state change is initiated.
2353 // Override enforced - Children and Driver desires are ignored.
2354 //*********************************************************************************
2356 IOReturn
IOService::changePowerStateWithOverrideTo( IOPMPowerStateIndex ordinal
,
2357 IOPMRequestTag tag
)
2359 IOPMRequest
* request
;
2362 return kIOPMNotYetInitialized
;
2364 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2366 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2368 return kIOReturnNoMemory
;
2370 gIOPMPowerClientDevice
->retain();
2371 request
->fRequestTag
= tag
;
2372 request
->fArg0
= (void *) ordinal
;
2373 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2377 request
->installCompletionAction( action
, target
, param
);
2380 // Prevent needless downwards power transitions by clamping power
2381 // until the scheduled request is executed.
2383 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
))
2385 fTempClampPowerState
= StateMax(fTempClampPowerState
, ordinal
);
2387 fOverrideMaxPowerState
= ordinal
;
2388 request
->fArg2
= (void *) (uintptr_t) true;
2391 submitPMRequest( request
);
2395 //*********************************************************************************
2396 // [public] changePowerStateForRootDomain
2398 // Adjust the root domain's power desire on the target
2399 //*********************************************************************************
2401 IOReturn
IOService::changePowerStateForRootDomain( IOPMPowerStateIndex ordinal
)
2403 OUR_PMLog(kPMLogChangeStateForRootDomain
, ordinal
, 0);
2404 return requestPowerState( gIOPMPowerClientRootDomain
, ordinal
);
2407 //*********************************************************************************
2408 // [public for PMRD] quiescePowerTree
2410 // For root domain to issue a request to quiesce the power tree.
2411 // Supplied callback invoked upon completion.
2412 //*********************************************************************************
2414 IOReturn
IOService::quiescePowerTree(
2415 void * target
, IOPMCompletionAction action
, void * param
)
2417 IOPMRequest
* request
;
2420 return kIOPMNotYetInitialized
;
2421 if (!target
|| !action
)
2422 return kIOReturnBadArgument
;
2424 OUR_PMLog(kPMLogQuiescePowerTree
, 0, 0);
2426 // Target the root node instead of root domain. This is to avoid blocking
2427 // the quiesce request behind an existing root domain request in the work
2428 // queue. Root parent and root domain requests in the work queue must not
2429 // block the completion of the quiesce request.
2431 request
= acquirePMRequest(gIOPMRootNode
, kIOPMRequestTypeQuiescePowerTree
);
2433 return kIOReturnNoMemory
;
2435 request
->installCompletionAction(target
, action
, param
);
2437 // Submit through the normal request flow. This will make sure any request
2438 // already in the request queue will get pushed over to the work queue for
2439 // execution. Any request submitted after this request may not be serviced.
2441 submitPMRequest( request
);
2442 return kIOReturnSuccess
;
2445 //*********************************************************************************
2446 // [private] requestPowerState
2447 //*********************************************************************************
2449 IOReturn
IOService::requestPowerState(
2450 const OSSymbol
* client
,
2453 IOPMRequest
* request
;
2456 return kIOReturnBadArgument
;
2458 return kIOPMNotYetInitialized
;
2460 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2462 return kIOReturnNoMemory
;
2465 request
->fArg0
= (void *)(uintptr_t) state
;
2466 request
->fArg1
= (void *) client
;
2470 request
->installCompletionAction( action
, target
, param
);
2473 // Prevent needless downwards power transitions by clamping power
2474 // until the scheduled request is executed.
2476 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
))
2478 fTempClampPowerState
= StateMax(fTempClampPowerState
, state
);
2480 request
->fArg2
= (void *) (uintptr_t) true;
2483 submitPMRequest( request
);
2487 //*********************************************************************************
2488 // [private] handleRequestPowerState
2489 //*********************************************************************************
2491 void IOService::handleRequestPowerState( IOPMRequest
* request
)
2493 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2494 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2496 PM_ASSERT_IN_GATE();
2499 assert(fTempClampCount
!= 0);
2500 if (fTempClampCount
) fTempClampCount
--;
2501 if (!fTempClampCount
) fTempClampPowerState
= kPowerStateZero
;
2504 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
))
2505 state
= fHighestPowerState
;
2507 // The power suppression due to changePowerStateWithOverrideTo() expires
2508 // upon the next "device" power request - changePowerStateToPriv().
2510 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2511 (client
== gIOPMPowerClientDevice
))
2512 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2514 if ((state
== kPowerStateZero
) &&
2515 (client
!= gIOPMPowerClientDevice
) &&
2516 (client
!= gIOPMPowerClientDriver
) &&
2517 (client
!= gIOPMPowerClientChildProxy
))
2518 removePowerClient(client
);
2520 updatePowerClient(client
, state
);
2526 //*********************************************************************************
2527 // [private] Helper functions to update/remove power clients.
2528 //*********************************************************************************
2530 void IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2532 IOPMPowerStateIndex oldPowerState
= kPowerStateZero
;
2535 fPowerClients
= OSDictionary::withCapacity(4);
2536 if (fPowerClients
&& client
)
2538 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2541 oldPowerState
= num
->unsigned32BitValue();
2542 num
->setValue(powerState
);
2546 num
= OSNumber::withNumber(powerState
, 32);
2549 fPowerClients
->setObject(client
, num
);
2554 PM_ACTION_3(actionUpdatePowerClient
, client
, oldPowerState
, powerState
);
2558 void IOService::removePowerClient( const OSSymbol
* client
)
2560 if (fPowerClients
&& client
)
2561 fPowerClients
->removeObject(client
);
2564 uint32_t IOService::getPowerStateForClient( const OSSymbol
* client
)
2566 uint32_t powerState
= kPowerStateZero
;
2568 if (fPowerClients
&& client
)
2570 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2571 if (num
) powerState
= num
->unsigned32BitValue();
2576 //*********************************************************************************
2577 // [protected] powerOverrideOnPriv
2578 //*********************************************************************************
2580 IOReturn
IOService::powerOverrideOnPriv( void )
2582 IOPMRequest
* request
;
2585 return IOPMNotYetInitialized
;
2587 if (gIOPMWorkLoop
->inGate())
2589 fDeviceOverrideEnabled
= true;
2593 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2595 return kIOReturnNoMemory
;
2597 submitPMRequest( request
);
2601 //*********************************************************************************
2602 // [protected] powerOverrideOffPriv
2603 //*********************************************************************************
2605 IOReturn
IOService::powerOverrideOffPriv( void )
2607 IOPMRequest
* request
;
2610 return IOPMNotYetInitialized
;
2612 if (gIOPMWorkLoop
->inGate())
2614 fDeviceOverrideEnabled
= false;
2618 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2620 return kIOReturnNoMemory
;
2622 submitPMRequest( request
);
2626 //*********************************************************************************
2627 // [private] handlePowerOverrideChanged
2628 //*********************************************************************************
2630 void IOService::handlePowerOverrideChanged( IOPMRequest
* request
)
2632 PM_ASSERT_IN_GATE();
2633 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
)
2635 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2636 fDeviceOverrideEnabled
= true;
2640 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2641 fDeviceOverrideEnabled
= false;
2647 //*********************************************************************************
2648 // [private] computeDesiredState
2649 //*********************************************************************************
2651 void IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2655 IOPowerConnection
* connection
;
2656 uint32_t desiredState
= kPowerStateZero
;
2657 uint32_t newPowerState
= kPowerStateZero
;
2658 bool hasChildren
= false;
2660 // Desired power state is always 0 without a controlling driver.
2662 if (!fNumberOfPowerStates
)
2664 fDesiredPowerState
= kPowerStateZero
;
2668 // Examine the children's desired power state.
2670 iter
= getChildIterator(gIOPowerPlane
);
2673 while ((next
= iter
->getNextObject()))
2675 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
2677 if (connection
->getReadyFlag() == false)
2679 PM_LOG3("[%s] %s: connection not ready\n",
2680 getName(), __FUNCTION__
);
2683 if (connection
->childHasRequestedPower())
2685 desiredState
= StateMax(connection
->getDesiredDomainState(), desiredState
);
2691 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2693 removePowerClient(gIOPMPowerClientChildren
);
2695 // Iterate through all power clients to determine the min power state.
2697 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2700 const OSSymbol
* client
;
2701 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
2703 // Ignore child and driver when override is in effect.
2704 if ((fDeviceOverrideEnabled
||
2705 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2706 ((client
== gIOPMPowerClientChildren
) ||
2707 (client
== gIOPMPowerClientDriver
)))
2710 // Ignore child proxy when children are present.
2711 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
))
2714 // Advisory tickles are irrelevant unless system is in full wake
2715 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2716 !gIOPMAdvisoryTickleEnabled
)
2719 desiredState
= getPowerStateForClient(client
);
2720 assert(desiredState
< fNumberOfPowerStates
);
2722 desiredState
, client
->getCStringNoCopy());
2724 newPowerState
= StateMax(newPowerState
, desiredState
);
2726 if (client
== gIOPMPowerClientDevice
)
2727 fDeviceDesire
= desiredState
;
2732 // Factor in the temporary power desires.
2734 newPowerState
= StateMax(newPowerState
, localClamp
);
2735 newPowerState
= StateMax(newPowerState
, fTempClampPowerState
);
2737 // Limit check against max power override.
2739 newPowerState
= StateMin(newPowerState
, fOverrideMaxPowerState
);
2741 // Limit check against number of power states.
2743 if (newPowerState
>= fNumberOfPowerStates
)
2744 newPowerState
= fHighestPowerState
;
2746 fDesiredPowerState
= newPowerState
;
2748 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2749 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2750 (uint32_t) fCurrentPowerState
, newPowerState
);
2754 // Restart idle timer if possible when device desire has increased.
2755 // Or if an advisory desire exists.
2757 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
2762 // Invalidate cached tickle power state when desires change, and not
2763 // due to a tickle request. In case the driver has requested a lower
2764 // power state, but the tickle is caching a higher power state which
2765 // will drop future tickles until the cached value is lowered or in-
2766 // validated. The invalidation must occur before the power transition
2767 // to avoid dropping a necessary tickle.
2769 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2770 (fActivityTicklePowerState
!= kInvalidTicklePowerState
))
2772 IOLockLock(fActivityLock
);
2773 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2774 IOLockUnlock(fActivityLock
);
2779 //*********************************************************************************
2780 // [public] currentPowerConsumption
2782 //*********************************************************************************
2784 unsigned long IOService::currentPowerConsumption( void )
2787 return kIOPMUnknown
;
2789 return fCurrentPowerConsumption
;
2792 //*********************************************************************************
2793 // [deprecated] getPMworkloop
2794 //*********************************************************************************
2797 IOWorkLoop
* IOService::getPMworkloop( void )
2799 return gIOPMWorkLoop
;
2805 //*********************************************************************************
2806 // Power Parent/Children Applier
2807 //*********************************************************************************
2810 applyToPowerChildren(
2811 IOService
* service
,
2812 IOServiceApplierFunction applier
,
2814 IOOptionBits options
)
2816 PM_ASSERT_IN_GATE();
2818 IORegistryEntry
* entry
;
2819 IORegistryIterator
* iter
;
2820 IOPowerConnection
* connection
;
2823 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2826 while ((entry
= iter
->getNextObject()))
2828 // Get child of IOPowerConnection objects
2829 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2831 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2834 (*applier
)(child
, context
);
2845 IOService
* service
,
2846 IOServiceApplierFunction applier
,
2848 IOOptionBits options
)
2850 PM_ASSERT_IN_GATE();
2852 IORegistryEntry
* entry
;
2853 IORegistryIterator
* iter
;
2854 IOPowerConnection
* connection
;
2857 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2858 options
| kIORegistryIterateParents
);
2861 while ((entry
= iter
->getNextObject()))
2863 // Get child of IOPowerConnection objects
2864 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2866 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2869 (*applier
)(parent
, context
);
2878 #endif /* NOT_YET */
2881 // MARK: Activity Tickle & Idle Timer
2883 void IOService::setAdvisoryTickleEnable( bool enable
)
2885 gIOPMAdvisoryTickleEnabled
= enable
;
2888 //*********************************************************************************
2889 // [public] activityTickle
2891 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2892 // flag to be set, and the device state checked. If the device has been
2893 // powered down, it is powered up again.
2894 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2895 // should be intercepted by a subclass.
2896 //*********************************************************************************
2898 bool IOService::activityTickle( unsigned long type
, unsigned long stateNumber
)
2900 IOPMRequest
* request
;
2901 bool noPowerChange
= true;
2902 uint32_t tickleFlags
;
2905 return true; // no power change
2907 if ((type
== kIOPMSuperclassPolicy1
) && StateOrder(stateNumber
))
2909 IOLockLock(fActivityLock
);
2911 // Record device activity for the idle timer handler.
2913 fDeviceWasActive
= true;
2914 fActivityTickleCount
++;
2915 clock_get_uptime(&fDeviceActiveTimestamp
);
2917 PM_ACTION_0(actionActivityTickle
);
2919 // Record the last tickle power state.
2920 // This helps to filter out redundant tickles as
2921 // this function may be called from the data path.
2923 if ((fActivityTicklePowerState
== kInvalidTicklePowerState
)
2924 || StateOrder(fActivityTicklePowerState
) < StateOrder(stateNumber
))
2926 fActivityTicklePowerState
= stateNumber
;
2927 noPowerChange
= false;
2929 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2930 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2933 request
->fArg0
= (void *) stateNumber
;
2934 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2935 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2936 submitPMRequest(request
);
2940 IOLockUnlock(fActivityLock
);
2943 else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2944 ((stateNumber
= fDeviceUsablePowerState
) != kPowerStateZero
))
2946 IOLockLock(fActivityLock
);
2948 fAdvisoryTickled
= true;
2950 if (fAdvisoryTicklePowerState
!= stateNumber
)
2952 fAdvisoryTicklePowerState
= stateNumber
;
2953 noPowerChange
= false;
2955 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2956 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2959 request
->fArg0
= (void *) stateNumber
;
2960 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2961 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2962 submitPMRequest(request
);
2966 IOLockUnlock(fActivityLock
);
2969 // Returns false if the activityTickle might cause a transition to a
2970 // higher powered state, true otherwise.
2972 return noPowerChange
;
2975 //*********************************************************************************
2976 // [private] handleActivityTickle
2977 //*********************************************************************************
2979 void IOService::handleActivityTickle( IOPMRequest
* request
)
2981 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2982 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
2983 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
2984 bool adjustPower
= false;
2986 PM_ASSERT_IN_GATE();
2987 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
))
2989 // Drivers that don't want power restored on wake will drop any
2990 // tickles that pre-dates the current system wake. The model is
2991 // that each wake is a fresh start, with power state depressed
2992 // until a new tickle or an explicit power up request from the
2993 // driver. It is possible for the PM work loop to enter the
2994 // system sleep path with tickle requests queued.
2999 if (tickleFlags
& kTickleTypeActivity
)
3001 IOPMPowerStateIndex deviceDesireOrder
= StateOrder(fDeviceDesire
);
3002 uint32_t idleTimerGeneration
= ticklePowerState
; // kTickleTypePowerDrop
3004 if (tickleFlags
& kTickleTypePowerRise
)
3006 if ((StateOrder(ticklePowerState
) > deviceDesireOrder
) &&
3007 (ticklePowerState
< fNumberOfPowerStates
))
3009 fIdleTimerMinPowerState
= ticklePowerState
;
3010 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
3014 else if ((deviceDesireOrder
> StateOrder(fIdleTimerMinPowerState
)) &&
3015 (idleTimerGeneration
== fIdleTimerGeneration
))
3017 // Power drop due to idle timer expiration.
3018 // Do not allow idle timer to reduce power below tickle power.
3019 // This prevents the idle timer from decreasing the device desire
3020 // to zero and cancelling the effect of a pre-sleep tickle when
3021 // system wakes up to doze state, while the device is unable to
3022 // raise its power state to satisfy the tickle.
3024 deviceDesireOrder
--;
3025 if (deviceDesireOrder
< fNumberOfPowerStates
)
3027 ticklePowerState
= fPowerStates
[deviceDesireOrder
].stateOrderToIndex
;
3028 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
3033 else // advisory tickle
3035 if (tickleFlags
& kTickleTypePowerRise
)
3037 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
3038 (ticklePowerState
< fNumberOfPowerStates
))
3040 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
3041 fHasAdvisoryDesire
= true;
3042 fAdvisoryTickleUsed
= true;
3047 IOLockLock(fActivityLock
);
3048 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3049 IOLockUnlock(fActivityLock
);
3052 else if (fHasAdvisoryDesire
)
3054 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
3055 fHasAdvisoryDesire
= false;
3066 //******************************************************************************
3067 // [public] setIdleTimerPeriod
3069 // A subclass policy-maker is using our standard idleness detection service.
3070 // Start the idle timer. Period is in seconds.
3071 //******************************************************************************
3073 IOReturn
IOService::setIdleTimerPeriod( unsigned long period
)
3076 return IOPMNotYetInitialized
;
3078 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
3080 IOPMRequest
* request
=
3081 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
3083 return kIOReturnNoMemory
;
3085 request
->fArg0
= (void *) period
;
3086 submitPMRequest( request
);
3088 return kIOReturnSuccess
;
3091 IOReturn
IOService::setIgnoreIdleTimer( bool ignore
)
3094 return IOPMNotYetInitialized
;
3096 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
3098 IOPMRequest
* request
=
3099 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
3101 return kIOReturnNoMemory
;
3103 request
->fArg0
= (void *) ignore
;
3104 submitPMRequest( request
);
3106 return kIOReturnSuccess
;
3109 //******************************************************************************
3110 // [public] nextIdleTimeout
3112 // Returns how many "seconds from now" the device should idle into its
3113 // next lowest power state.
3114 //******************************************************************************
3116 SInt32
IOService::nextIdleTimeout(
3117 AbsoluteTime currentTime
,
3118 AbsoluteTime lastActivity
,
3119 unsigned int powerState
)
3126 // Calculate time difference using funky macro from clock.h.
3127 delta
= currentTime
;
3128 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
3130 // Figure it in seconds.
3131 absolutetime_to_nanoseconds(delta
, &delta_ns
);
3132 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
3134 // Be paranoid about delta somehow exceeding timer period.
3135 if (delta_secs
< (int) fIdleTimerPeriod
)
3136 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3138 delay_secs
= (int) fIdleTimerPeriod
;
3140 return (SInt32
)delay_secs
;
3143 //*********************************************************************************
3144 // [public] start_PM_idle_timer
3145 //*********************************************************************************
3147 void IOService::start_PM_idle_timer( void )
3149 static const int maxTimeout
= 100000;
3150 static const int minTimeout
= 1;
3151 AbsoluteTime uptime
, deadline
;
3155 if (!initialized
|| !fIdleTimerPeriod
)
3158 IOLockLock(fActivityLock
);
3160 clock_get_uptime(&uptime
);
3162 // Subclasses may modify idle sleep algorithm
3163 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3165 // Check for out-of range responses
3166 if (idle_in
> maxTimeout
)
3168 // use standard implementation
3169 idle_in
= IOService::nextIdleTimeout(uptime
,
3170 fDeviceActiveTimestamp
,
3171 fCurrentPowerState
);
3172 } else if (idle_in
< minTimeout
) {
3173 idle_in
= fIdleTimerPeriod
;
3176 IOLockUnlock(fActivityLock
);
3178 fNextIdleTimerPeriod
= idle_in
;
3179 fIdleTimerStartTime
= uptime
;
3182 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3183 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3184 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3185 if (pending
) release();
3188 //*********************************************************************************
3189 // [private] restartIdleTimer
3190 //*********************************************************************************
3192 void IOService::restartIdleTimer( void )
3194 if (fDeviceDesire
!= kPowerStateZero
)
3196 fIdleTimerStopped
= false;
3197 fActivityTickleCount
= 0;
3198 start_PM_idle_timer();
3200 else if (fHasAdvisoryDesire
)
3202 fIdleTimerStopped
= false;
3203 start_PM_idle_timer();
3207 fIdleTimerStopped
= true;
3211 //*********************************************************************************
3212 // idle_timer_expired
3213 //*********************************************************************************
3217 thread_call_param_t arg0
, thread_call_param_t arg1
)
3219 IOService
* me
= (IOService
*) arg0
;
3222 gIOPMWorkLoop
->runAction(
3223 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3224 &IOService::idleTimerExpired
),
3230 //*********************************************************************************
3231 // [private] idleTimerExpired
3233 // The idle timer has expired. If there has been activity since the last
3234 // expiration, just restart the timer and return. If there has not been
3235 // activity, switch to the next lower power state and restart the timer.
3236 //*********************************************************************************
3238 void IOService::idleTimerExpired( void )
3240 IOPMRequest
* request
;
3241 bool restartTimer
= true;
3242 uint32_t tickleFlags
;
3244 if ( !initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3245 fLockedFlags
.PMStop
)
3248 fIdleTimerStartTime
= 0;
3250 IOLockLock(fActivityLock
);
3252 // Check for device activity (tickles) over last timer period.
3254 if (fDeviceWasActive
)
3256 // Device was active - do not drop power, restart timer.
3257 fDeviceWasActive
= false;
3259 else if (!fIdleTimerIgnored
)
3261 // No device activity - drop power state by one level.
3262 // Decrement the cached tickle power state when possible.
3263 // This value may be kInvalidTicklePowerState before activityTickle()
3264 // is called, but the power drop request must be issued regardless.
3266 if ((fActivityTicklePowerState
!= kInvalidTicklePowerState
) &&
3267 (fActivityTicklePowerState
!= kPowerStateZero
))
3268 fActivityTicklePowerState
--;
3270 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3271 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3274 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3275 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3276 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3277 submitPMRequest( request
);
3279 // Do not restart timer until after the tickle request has been
3282 restartTimer
= false;
3286 if (fAdvisoryTickled
)
3288 fAdvisoryTickled
= false;
3290 else if (fHasAdvisoryDesire
)
3292 // Want new tickles to turn into pm request after we drop the lock
3293 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3295 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3296 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3299 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3300 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3301 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3302 submitPMRequest( request
);
3304 // Do not restart timer until after the tickle request has been
3307 restartTimer
= false;
3311 IOLockUnlock(fActivityLock
);
3314 start_PM_idle_timer();
3318 //*********************************************************************************
3319 // [deprecated] PM_idle_timer_expiration
3320 //*********************************************************************************
3322 void IOService::PM_idle_timer_expiration( void )
3326 //*********************************************************************************
3327 // [deprecated] command_received
3328 //*********************************************************************************
3330 void IOService::command_received( void *statePtr
, void *, void * , void * )
3333 #endif /* !__LP64__ */
3335 //*********************************************************************************
3336 // [public] setAggressiveness
3338 // Pass on the input parameters to all power domain children. All those which are
3339 // power domains will pass it on to their children, etc.
3340 //*********************************************************************************
3342 IOReturn
IOService::setAggressiveness( unsigned long type
, unsigned long newLevel
)
3344 return kIOReturnSuccess
;
3347 //*********************************************************************************
3348 // [public] getAggressiveness
3350 // Called by the user client.
3351 //*********************************************************************************
3353 IOReturn
IOService::getAggressiveness( unsigned long type
, unsigned long * currentLevel
)
3355 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3358 return kIOReturnNotReady
;
3360 return rootDomain
->getAggressiveness( type
, currentLevel
);
3363 //*********************************************************************************
3364 // [public] getPowerState
3366 //*********************************************************************************
3368 UInt32
IOService::getPowerState( void )
3371 return kPowerStateZero
;
3373 return fCurrentPowerState
;
3377 //*********************************************************************************
3378 // [deprecated] systemWake
3380 // Pass this to all power domain children. All those which are
3381 // power domains will pass it on to their children, etc.
3382 //*********************************************************************************
3384 IOReturn
IOService::systemWake( void )
3388 IOPowerConnection
* connection
;
3389 IOService
* theChild
;
3391 iter
= getChildIterator(gIOPowerPlane
);
3394 while ( (next
= iter
->getNextObject()) )
3396 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
3398 if (connection
->getReadyFlag() == false)
3400 PM_LOG3("[%s] %s: connection not ready\n",
3401 getName(), __FUNCTION__
);
3405 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3408 theChild
->systemWake();
3409 theChild
->release();
3416 if ( fControllingDriver
!= NULL
)
3418 if ( fControllingDriver
->didYouWakeSystem() )
3427 //*********************************************************************************
3428 // [deprecated] temperatureCriticalForZone
3429 //*********************************************************************************
3431 IOReturn
IOService::temperatureCriticalForZone( IOService
* whichZone
)
3433 IOService
* theParent
;
3436 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3438 if ( inPlane(gIOPowerPlane
) && !IS_PM_ROOT
)
3440 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3443 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3447 theParent
->temperatureCriticalForZone(whichZone
);
3448 theParent
->release();
3454 #endif /* !__LP64__ */
3457 // MARK: Power Change (Common)
3459 //*********************************************************************************
3460 // [private] startPowerChange
3462 // All power state changes starts here.
3463 //*********************************************************************************
3465 IOReturn
IOService::startPowerChange(
3466 IOPMPowerChangeFlags changeFlags
,
3467 IOPMPowerStateIndex powerState
,
3468 IOPMPowerFlags domainFlags
,
3469 IOPowerConnection
* parentConnection
,
3470 IOPMPowerFlags parentFlags
)
3472 PM_ASSERT_IN_GATE();
3473 assert( fMachineState
== kIOPM_Finished
);
3474 assert( powerState
< fNumberOfPowerStates
);
3476 if (powerState
>= fNumberOfPowerStates
)
3477 return IOPMAckImplied
;
3479 fIsPreChange
= true;
3480 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3482 if (changeFlags
& kIOPMExpireIdleTimer
)
3484 // Root domain requested removal of tickle influence
3485 if (StateOrder(fDeviceDesire
) > StateOrder(powerState
))
3487 // Reset device desire down to the clamped power state
3488 updatePowerClient(gIOPMPowerClientDevice
, powerState
);
3489 computeDesiredState(kPowerStateZero
, true);
3491 // Invalidate tickle cache so the next tickle will issue a request
3492 IOLockLock(fActivityLock
);
3493 fDeviceWasActive
= false;
3494 fActivityTicklePowerState
= kInvalidTicklePowerState
;
3495 IOLockUnlock(fActivityLock
);
3497 fIdleTimerMinPowerState
= kPowerStateZero
;
3501 // Root domain's override handler may cancel the power change by
3502 // setting the kIOPMNotDone flag.
3504 if (changeFlags
& kIOPMNotDone
)
3505 return IOPMAckImplied
;
3507 // Forks to either Driver or Parent initiated power change paths.
3509 fHeadNoteChangeFlags
= changeFlags
;
3510 fHeadNotePowerState
= powerState
;
3511 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
3512 fHeadNoteParentConnection
= NULL
;
3514 if (changeFlags
& kIOPMSelfInitiated
)
3516 if (changeFlags
& kIOPMSynchronize
)
3524 assert(changeFlags
& kIOPMParentInitiated
);
3525 fHeadNoteDomainFlags
= domainFlags
;
3526 fHeadNoteParentFlags
= parentFlags
;
3527 fHeadNoteParentConnection
= parentConnection
;
3528 return ParentChangeStart();
3532 //*********************************************************************************
3533 // [private] notifyInterestedDrivers
3534 //*********************************************************************************
3536 bool IOService::notifyInterestedDrivers( void )
3538 IOPMinformee
* informee
;
3539 IOPMinformeeList
* list
= fInterestedDrivers
;
3540 DriverCallParam
* param
;
3542 IOItemCount skipCnt
= 0;
3544 PM_ASSERT_IN_GATE();
3545 assert( fDriverCallParamCount
== 0 );
3546 assert( fHeadNotePendingAcks
== 0 );
3548 fHeadNotePendingAcks
= 0;
3550 count
= list
->numberOfItems();
3552 goto done
; // no interested drivers
3554 // Allocate an array of interested drivers and their return values
3555 // for the callout thread. Everything else is still "owned" by the
3556 // PM work loop, which can run to process acknowledgePowerChange()
3559 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3560 if (count
> fDriverCallParamSlots
)
3562 if (fDriverCallParamSlots
)
3564 assert(fDriverCallParamPtr
);
3565 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3566 fDriverCallParamPtr
= 0;
3567 fDriverCallParamSlots
= 0;
3570 param
= IONew(DriverCallParam
, count
);
3572 goto done
; // no memory
3574 fDriverCallParamPtr
= (void *) param
;
3575 fDriverCallParamSlots
= count
;
3578 informee
= list
->firstInList();
3580 for (IOItemCount i
= 0; i
< count
; i
++)
3582 if (fInitialSetPowerState
|| (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)) {
3583 // Skip notifying self, if 'kIOPMInitialDeviceState' is set and
3584 // this is the initial power state change
3585 if ((this == informee
->whatObject
) &&
3586 (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)) {
3591 informee
->timer
= -1;
3592 param
[i
].Target
= informee
;
3594 informee
= list
->nextInList( informee
);
3601 fDriverCallParamCount
= count
;
3602 fHeadNotePendingAcks
= count
;
3604 // Block state machine and wait for callout completion.
3605 assert(!fDriverCallBusy
);
3606 fDriverCallBusy
= true;
3607 thread_call_enter( fDriverCallEntry
);
3611 // Return false if there are no interested drivers or could not schedule
3612 // callout thread due to error.
3616 //*********************************************************************************
3617 // [private] notifyInterestedDriversDone
3618 //*********************************************************************************
3620 void IOService::notifyInterestedDriversDone( void )
3622 IOPMinformee
* informee
;
3624 DriverCallParam
* param
;
3628 PM_ASSERT_IN_GATE();
3629 assert( fDriverCallBusy
== false );
3630 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3632 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3633 count
= fDriverCallParamCount
;
3637 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3639 informee
= (IOPMinformee
*) param
->Target
;
3640 result
= param
->Result
;
3642 if ((result
== IOPMAckImplied
) || (result
< 0))
3644 // Interested driver return IOPMAckImplied.
3645 // If informee timer is zero, it must have de-registered
3646 // interest during the thread callout. That also drops
3647 // the pending ack count.
3649 if (fHeadNotePendingAcks
&& informee
->timer
)
3650 fHeadNotePendingAcks
--;
3652 informee
->timer
= 0;
3654 else if (informee
->timer
)
3656 assert(informee
->timer
== -1);
3658 // Driver has not acked, and has returned a positive result.
3659 // Enforce a minimum permissible timeout value.
3660 // Make the min value large enough so timeout is less likely
3661 // to occur if a driver misinterpreted that the return value
3662 // should be in microsecond units. And make it large enough
3663 // to be noticeable if a driver neglects to ack.
3665 if (result
< kMinAckTimeoutTicks
)
3666 result
= kMinAckTimeoutTicks
;
3668 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3669 if (result
> maxTimeout
) {
3670 maxTimeout
= result
;
3673 // else, child has already acked or driver has removed interest,
3674 // and head_note_pendingAcks decremented.
3675 // informee may have been removed from the interested drivers list,
3676 // thus the informee must be retained across the callout.
3678 informee
->release();
3681 fDriverCallParamCount
= 0;
3683 if ( fHeadNotePendingAcks
)
3685 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3687 getPMRootDomain()->reset_watchdog_timer(this, maxTimeout
/USEC_PER_SEC
+1);
3691 MS_POP(); // pop the machine state passed to notifyAll()
3693 // If interest acks are outstanding, block the state machine until
3694 // fHeadNotePendingAcks drops to zero before notifying root domain.
3695 // Otherwise notify root domain directly.
3697 if (!fHeadNotePendingAcks
)
3703 MS_PUSH(fMachineState
);
3704 fMachineState
= kIOPM_NotifyChildrenStart
;
3708 //*********************************************************************************
3709 // [private] notifyRootDomain
3710 //*********************************************************************************
3712 void IOService::notifyRootDomain( void )
3714 assert( fDriverCallBusy
== false );
3716 // Only for root domain in the will-change phase
3717 if (!IS_ROOT_DOMAIN
|| (fMachineState
!= kIOPM_OurChangeSetPowerState
))
3723 MS_PUSH(fMachineState
); // push notifyAll() machine state
3724 fMachineState
= kIOPM_DriverThreadCallDone
;
3726 // Call IOPMrootDomain::willNotifyPowerChildren() on a thread call
3727 // to avoid a deadlock.
3728 fDriverCallReason
= kRootDomainInformPreChange
;
3729 fDriverCallBusy
= true;
3730 thread_call_enter( fDriverCallEntry
);
3733 void IOService::notifyRootDomainDone( void )
3735 assert( fDriverCallBusy
== false );
3736 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3738 MS_POP(); // pop notifyAll() machine state
3742 //*********************************************************************************
3743 // [private] notifyChildren
3744 //*********************************************************************************
3746 void IOService::notifyChildren( void )
3750 IOPowerConnection
* connection
;
3751 OSArray
* children
= 0;
3752 IOPMrootDomain
* rootDomain
;
3753 bool delayNotify
= false;
3755 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3756 (IS_POWER_DROP
== fIsPreChange
) &&
3757 ((rootDomain
= getPMRootDomain()) == this))
3759 rootDomain
->tracePoint( IS_POWER_DROP
?
3760 kIOPMTracePointSleepPowerPlaneDrivers
:
3761 kIOPMTracePointWakePowerPlaneDrivers
);
3764 if (fStrictTreeOrder
)
3765 children
= OSArray::withCapacity(8);
3767 // Sum child power consumption in notifyChild()
3768 fHeadNotePowerArrayEntry
->staticPower
= 0;
3770 iter
= getChildIterator(gIOPowerPlane
);
3773 while ((next
= iter
->getNextObject()))
3775 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3777 if (connection
->getReadyFlag() == false)
3779 PM_LOG3("[%s] %s: connection not ready\n",
3780 getName(), __FUNCTION__
);
3784 // Mechanism to postpone the did-change notification to
3785 // certain power children to order those children last.
3786 // Cannot be used together with strict tree ordering.
3788 if (!fIsPreChange
&&
3789 connection
->delayChildNotification
&&
3790 getPMRootDomain()->shouldDelayChildNotification(this))
3794 children
= OSArray::withCapacity(8);
3800 children
->setObject( connection
);
3805 if (!delayNotify
&& children
)
3806 children
->setObject( connection
);
3808 notifyChild( connection
);
3814 if (children
&& (children
->getCount() == 0))
3816 children
->release();
3821 assert(fNotifyChildArray
== 0);
3822 fNotifyChildArray
= children
;
3823 MS_PUSH(fMachineState
);
3827 // Block until all non-delayed children have acked their
3828 // notification. Then notify the remaining delayed child
3829 // in the array. This is used to hold off graphics child
3830 // notification while the rest of the system powers up.
3831 // If a hid tickle arrives during this time, the delayed
3832 // children are immediately notified and root domain will
3833 // not clamp power for dark wake.
3835 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3836 PM_LOG2("%s: %d children in delayed array\n",
3837 getName(), children
->getCount());
3841 // Child array created to support strict notification order.
3842 // Notify children in the array one at a time.
3844 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3849 //*********************************************************************************
3850 // [private] notifyChildrenOrdered
3851 //*********************************************************************************
3853 void IOService::notifyChildrenOrdered( void )
3855 PM_ASSERT_IN_GATE();
3856 assert(fNotifyChildArray
);
3857 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3859 // Notify one child, wait for it to ack, then repeat for next child.
3860 // This is a workaround for some drivers with multiple instances at
3861 // the same branch in the power tree, but the driver is slow to power
3862 // up unless the tree ordering is observed. Problem observed only on
3863 // system wake, not on system sleep.
3865 // We have the ability to power off in reverse child index order.
3866 // That works nicely on some machines, but not on all HW configs.
3868 if (fNotifyChildArray
->getCount())
3870 IOPowerConnection
* connection
;
3871 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3872 notifyChild( connection
);
3873 fNotifyChildArray
->removeObject(0);
3877 fNotifyChildArray
->release();
3878 fNotifyChildArray
= 0;
3880 MS_POP(); // pushed by notifyChildren()
3884 //*********************************************************************************
3885 // [private] notifyChildrenDelayed
3886 //*********************************************************************************
3888 void IOService::notifyChildrenDelayed( void )
3890 IOPowerConnection
* connection
;
3892 PM_ASSERT_IN_GATE();
3893 assert(fNotifyChildArray
);
3894 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3896 // Wait after all non-delayed children and interested drivers have ack'ed,
3897 // then notify all delayed children. If notify delay is canceled, child
3898 // acks may be outstanding with PM blocked on fHeadNotePendingAcks != 0.
3899 // But the handling for either case is identical.
3901 for (int i
= 0; ; i
++)
3903 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3907 notifyChild( connection
);
3910 PM_LOG2("%s: notified delayed children\n", getName());
3911 fNotifyChildArray
->release();
3912 fNotifyChildArray
= 0;
3914 MS_POP(); // pushed by notifyChildren()
3917 //*********************************************************************************
3918 // [private] notifyAll
3919 //*********************************************************************************
3921 IOReturn
IOService::notifyAll( uint32_t nextMS
)
3923 // Save the machine state to be restored by notifyInterestedDriversDone()
3925 PM_ASSERT_IN_GATE();
3927 fMachineState
= kIOPM_DriverThreadCallDone
;
3928 fDriverCallReason
= fIsPreChange
?
3929 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3931 if (!notifyInterestedDrivers())
3932 notifyInterestedDriversDone();
3934 return IOPMWillAckLater
;
3937 //*********************************************************************************
3938 // [private, static] pmDriverCallout
3940 // Thread call context
3941 //*********************************************************************************
3943 IOReturn
IOService::actionDriverCalloutDone(
3945 void * arg0
, void * arg1
,
3946 void * arg2
, void * arg3
)
3948 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3950 assert( fDriverCallBusy
);
3951 fDriverCallBusy
= false;
3953 assert(gIOPMWorkQueue
);
3954 gIOPMWorkQueue
->signalWorkAvailable();
3956 return kIOReturnSuccess
;
3959 void IOService::pmDriverCallout( IOService
* from
)
3962 switch (from
->fDriverCallReason
)
3964 case kDriverCallSetPowerState
:
3965 from
->driverSetPowerState();
3968 case kDriverCallInformPreChange
:
3969 case kDriverCallInformPostChange
:
3970 from
->driverInformPowerChange();
3973 case kRootDomainInformPreChange
:
3974 getPMRootDomain()->willNotifyPowerChildren(from
->fHeadNotePowerState
);
3978 panic("IOService::pmDriverCallout bad machine state %x",
3979 from
->fDriverCallReason
);
3982 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3984 /* arg0 */ (void *) from
->pwrMgt
);
3987 //*********************************************************************************
3988 // [private] driverSetPowerState
3990 // Thread call context
3991 //*********************************************************************************
3993 void IOService::driverSetPowerState( void )
3995 IOPMPowerStateIndex powerState
;
3996 DriverCallParam
* param
;
3997 IOPMDriverCallEntry callEntry
;
4000 uint32_t oldPowerState
= getPowerState();
4002 assert( fDriverCallBusy
);
4003 assert( fDriverCallParamPtr
);
4004 assert( fDriverCallParamCount
== 1 );
4006 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4007 powerState
= fHeadNotePowerState
;
4009 callEntry
.callMethod
= OSMemberFunctionCast(const void *, fControllingDriver
, &IOService::setPowerState
);
4010 if (assertPMDriverCall(&callEntry
))
4012 OUR_PMLogFuncStart(kPMLogProgramHardware
, (uintptr_t) this, powerState
);
4013 start_spindump_timer("SetState");
4014 clock_get_uptime(&fDriverCallStartTime
);
4015 result
= fControllingDriver
->setPowerState( powerState
, this );
4016 clock_get_uptime(&end
);
4017 stop_spindump_timer();
4018 OUR_PMLogFuncEnd(kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
4020 deassertPMDriverCall(&callEntry
);
4022 // Record the most recent max power state residency timings.
4023 // Use with DeviceActiveTimestamp to diagnose tickle issues.
4024 if (powerState
== fHighestPowerState
)
4025 fMaxPowerStateEntryTime
= end
;
4026 else if (oldPowerState
== fHighestPowerState
)
4027 fMaxPowerStateExitTime
= end
;
4031 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
4032 fName
, OBFUSCATE(this), fCurrentPowerState
, powerState
, result
);
4036 if ((result
== IOPMAckImplied
) || (result
< 0))
4040 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
4041 absolutetime_to_nanoseconds(end
, &nsec
);
4042 if (nsec
> LOG_SETPOWER_TIMES
) {
4043 getPMRootDomain()->pmStatsRecordApplicationResponse(
4044 gIOPMStatsDriverPSChangeSlow
,
4045 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
4052 result
= kIOPMAckImplied
;
4054 param
->Result
= result
;
4057 //*********************************************************************************
4058 // [private] driverInformPowerChange
4060 // Thread call context
4061 //*********************************************************************************
4063 void IOService::driverInformPowerChange( void )
4065 IOPMinformee
* informee
;
4067 DriverCallParam
* param
;
4068 IOPMDriverCallEntry callEntry
;
4069 IOPMPowerFlags powerFlags
;
4070 IOPMPowerStateIndex powerState
;
4075 assert( fDriverCallBusy
);
4076 assert( fDriverCallParamPtr
);
4077 assert( fDriverCallParamCount
);
4079 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4080 count
= fDriverCallParamCount
;
4082 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4083 powerState
= fHeadNotePowerState
;
4085 for (IOItemCount i
= 0; i
< count
; i
++)
4087 informee
= (IOPMinformee
*) param
->Target
;
4088 driver
= informee
->whatObject
;
4090 if (fDriverCallReason
== kDriverCallInformPreChange
) {
4091 callEntry
.callMethod
= OSMemberFunctionCast(const void *, driver
, &IOService::powerStateWillChangeTo
);
4094 callEntry
.callMethod
= OSMemberFunctionCast(const void *, driver
, &IOService::powerStateDidChangeTo
);
4096 if (assertPMDriverCall(&callEntry
, 0, informee
))
4098 if (fDriverCallReason
== kDriverCallInformPreChange
)
4100 OUR_PMLogFuncStart(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
4101 start_spindump_timer("WillChange");
4102 clock_get_uptime(&informee
->startTime
);
4103 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
4104 clock_get_uptime(&end
);
4105 stop_spindump_timer();
4106 OUR_PMLogFuncEnd(kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
4110 OUR_PMLogFuncStart(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
4111 start_spindump_timer("DidChange");
4112 clock_get_uptime(&informee
->startTime
);
4113 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
4114 clock_get_uptime(&end
);
4115 stop_spindump_timer();
4116 OUR_PMLogFuncEnd(kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
4119 deassertPMDriverCall(&callEntry
);
4122 if ((result
== IOPMAckImplied
) || (result
< 0))
4126 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
4127 absolutetime_to_nanoseconds(end
, &nsec
);
4128 if (nsec
> LOG_SETPOWER_TIMES
) {
4129 getPMRootDomain()->pmStatsRecordApplicationResponse(
4130 gIOPMStatsDriverPSChangeSlow
, driver
->getName(),
4131 fDriverCallReason
, NS_TO_MS(nsec
), driver
->getRegistryEntryID(),
4138 result
= kIOPMAckImplied
;
4140 param
->Result
= result
;
4145 //*********************************************************************************
4146 // [private] notifyChild
4148 // Notify a power domain child of an upcoming power change.
4149 // If the object acknowledges the current change, we return TRUE.
4150 //*********************************************************************************
4152 bool IOService::notifyChild( IOPowerConnection
* theNub
)
4154 IOReturn ret
= IOPMAckImplied
;
4155 unsigned long childPower
;
4156 IOService
* theChild
;
4157 IOPMRequest
* childRequest
;
4158 IOPMPowerChangeFlags requestArg2
;
4161 PM_ASSERT_IN_GATE();
4162 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
4168 // Unless the child handles the notification immediately and returns
4169 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4170 fHeadNotePendingAcks
++;
4171 theNub
->setAwaitingAck(true);
4173 requestArg2
= fHeadNoteChangeFlags
;
4174 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
))
4175 requestArg2
|= kIOPMDomainPowerDrop
;
4177 requestType
= fIsPreChange
?
4178 kIOPMRequestTypePowerDomainWillChange
:
4179 kIOPMRequestTypePowerDomainDidChange
;
4181 childRequest
= acquirePMRequest( theChild
, requestType
);
4185 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4186 childRequest
->fArg1
= (void *) theNub
;
4187 childRequest
->fArg2
= (void *)(uintptr_t) requestArg2
;
4188 theChild
->submitPMRequest( childRequest
);
4189 ret
= IOPMWillAckLater
;
4193 ret
= IOPMAckImplied
;
4194 fHeadNotePendingAcks
--;
4195 theNub
->setAwaitingAck(false);
4196 childPower
= theChild
->currentPowerConsumption();
4197 if ( childPower
== kIOPMUnknown
)
4199 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4201 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
4202 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4206 theChild
->release();
4207 return (IOPMAckImplied
== ret
);
4210 //*********************************************************************************
4211 // [private] notifyControllingDriver
4212 //*********************************************************************************
4214 bool IOService::notifyControllingDriver( void )
4216 DriverCallParam
* param
;
4218 PM_ASSERT_IN_GATE();
4219 assert( fDriverCallParamCount
== 0 );
4220 assert( fControllingDriver
);
4222 if (fInitialSetPowerState
)
4224 fInitialSetPowerState
= false;
4225 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4227 // Driver specified flag to skip the inital setPowerState()
4228 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)
4234 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4237 param
= IONew(DriverCallParam
, 1);
4239 return false; // no memory
4241 fDriverCallParamPtr
= (void *) param
;
4242 fDriverCallParamSlots
= 1;
4245 param
->Target
= fControllingDriver
;
4246 fDriverCallParamCount
= 1;
4249 // Block state machine and wait for callout completion.
4250 assert(!fDriverCallBusy
);
4251 fDriverCallBusy
= true;
4252 thread_call_enter( fDriverCallEntry
);
4257 //*********************************************************************************
4258 // [private] notifyControllingDriverDone
4259 //*********************************************************************************
4261 void IOService::notifyControllingDriverDone( void )
4263 DriverCallParam
* param
;
4266 PM_ASSERT_IN_GATE();
4267 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4269 assert( fDriverCallBusy
== false );
4270 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4272 if (param
&& fDriverCallParamCount
)
4274 assert(fDriverCallParamCount
== 1);
4276 // the return value from setPowerState()
4277 result
= param
->Result
;
4279 if ((result
== IOPMAckImplied
) || (result
< 0))
4283 else if (fDriverTimer
)
4285 assert(fDriverTimer
== -1);
4287 // Driver has not acked, and has returned a positive result.
4288 // Enforce a minimum permissible timeout value.
4289 // Make the min value large enough so timeout is less likely
4290 // to occur if a driver misinterpreted that the return value
4291 // should be in microsecond units. And make it large enough
4292 // to be noticeable if a driver neglects to ack.
4294 if (result
< kMinAckTimeoutTicks
)
4295 result
= kMinAckTimeoutTicks
;
4297 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4299 // else, child has already acked and driver_timer reset to 0.
4301 fDriverCallParamCount
= 0;
4305 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4307 getPMRootDomain()->reset_watchdog_timer(this, result
/USEC_PER_SEC
+1);
4311 MS_POP(); // pushed by OurChangeSetPowerState()
4312 fIsPreChange
= false;
4315 //*********************************************************************************
4316 // [private] all_done
4318 // A power change is done.
4319 //*********************************************************************************
4321 void IOService::all_done( void )
4323 IOPMPowerStateIndex prevPowerState
;
4324 const IOPMPSEntry
* powerStatePtr
;
4325 IOPMDriverCallEntry callEntry
;
4326 uint32_t prevMachineState
= fMachineState
;
4327 bool actionCalled
= false;
4330 fMachineState
= kIOPM_Finished
;
4332 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4333 ((prevMachineState
== kIOPM_Finished
) ||
4334 (prevMachineState
== kIOPM_SyncFinish
)))
4336 // Sync operation and no power change occurred.
4337 // Do not inform driver and clients about this request completion,
4338 // except for the originator (root domain).
4340 PM_ACTION_2(actionPowerChangeDone
,
4341 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4343 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
4345 powerChangeDone(fCurrentPowerState
);
4347 else if (fAdvisoryTickleUsed
)
4349 // Not root domain and advisory tickle target.
4350 // Re-adjust power after power tree sync at the 'did' pass
4351 // to recompute desire and adjust power state between dark
4352 // and full wake transitions. Root domain is responsible
4353 // for calling setAdvisoryTickleEnable() before starting
4354 // the kIOPMSynchronize power change.
4356 if (!fAdjustPowerScheduled
&&
4357 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
))
4359 IOPMRequest
* request
;
4360 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4363 submitPMRequest( request
);
4364 fAdjustPowerScheduled
= true;
4373 if (fHeadNoteChangeFlags
& kIOPMSelfInitiated
)
4375 // power state changed
4376 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0)
4378 trackSystemSleepPreventers(
4379 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4381 // we changed, tell our parent
4382 requestDomainPower(fHeadNotePowerState
);
4384 // yes, did power raise?
4385 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4387 // yes, inform clients and apps
4388 tellChangeUp (fHeadNotePowerState
);
4390 prevPowerState
= fCurrentPowerState
;
4392 fCurrentPowerState
= fHeadNotePowerState
;
4395 ts
= mach_absolute_time();
4396 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4400 fPMVars
->myCurrentState
= fCurrentPowerState
;
4402 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4403 PM_ACTION_2(actionPowerChangeDone
,
4404 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4405 actionCalled
= true;
4407 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4408 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4409 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4410 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4412 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4414 // Bump tickle generation count once the entire tree is down
4415 gIOPMTickleGeneration
++;
4418 // inform subclass policy-maker
4419 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4420 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4422 powerChangeDone(prevPowerState
);
4423 deassertPMDriverCall(&callEntry
);
4426 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
4428 // changePowerStateWithOverrideTo() was cancelled
4429 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4433 // parent-initiated power change
4434 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
4436 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4437 ParentChangeRootChangeDown();
4439 // power state changed
4440 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0)
4442 trackSystemSleepPreventers(
4443 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4446 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4448 // yes, inform clients and apps
4449 tellChangeUp (fHeadNotePowerState
);
4452 prevPowerState
= fCurrentPowerState
;
4453 fCurrentPowerState
= fHeadNotePowerState
;
4456 ts
= mach_absolute_time();
4457 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4461 fPMVars
->myCurrentState
= fCurrentPowerState
;
4464 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4465 PM_ACTION_2(actionPowerChangeDone
,
4466 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4467 actionCalled
= true;
4469 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4470 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4471 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4472 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4474 // inform subclass policy-maker
4475 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4476 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4478 powerChangeDone(prevPowerState
);
4479 deassertPMDriverCall(&callEntry
);
4484 // When power rises enough to satisfy the tickle's desire for more power,
4485 // the condition preventing idle-timer from dropping power is removed.
4487 if (StateOrder(fCurrentPowerState
) >= StateOrder(fIdleTimerMinPowerState
))
4489 fIdleTimerMinPowerState
= kPowerStateZero
;
4494 PM_ACTION_2(actionPowerChangeDone
,
4495 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4500 // MARK: Power Change Initiated by Driver
4502 //*********************************************************************************
4503 // [private] OurChangeStart
4505 // Begin the processing of a power change initiated by us.
4506 //*********************************************************************************
4508 void IOService::OurChangeStart( void )
4510 PM_ASSERT_IN_GATE();
4511 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4513 // fMaxPowerState is our maximum possible power state based on the current
4514 // power state of our parents. If we are trying to raise power beyond the
4515 // maximum, send an async request for more power to all parents.
4517 if (!IS_PM_ROOT
&& (StateOrder(fMaxPowerState
) < StateOrder(fHeadNotePowerState
)))
4519 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4520 requestDomainPower(fHeadNotePowerState
);
4525 // Redundant power changes skips to the end of the state machine.
4527 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
4532 fInitialPowerChange
= false;
4534 // Change started, but may not complete...
4535 // Can be canceled (power drop) or deferred (power rise).
4537 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4539 // Two separate paths, depending if power is being raised or lowered.
4540 // Lowering power is subject to approval by clients of this service.
4544 fDoNotPowerDown
= false;
4546 // Ask for persmission to drop power state
4547 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4548 fOutOfBandParameter
= kNotifyApps
;
4549 askChangeDown(fHeadNotePowerState
);
4553 // This service is raising power and parents are able to support the
4554 // new power state. However a parent may have already committed to
4555 // drop power, which might force this object to temporarily drop power.
4556 // This results in "oscillations" before the state machines converge
4557 // to a steady state.
4559 // To prevent this, a child must make a power reservation against all
4560 // parents before raising power. If the reservation fails, indicating
4561 // that the child will be unable to sustain the higher power state,
4562 // then the child will signal the parent to adjust power, and the child
4563 // will defer its power change.
4567 // Reserve parent power necessary to achieve fHeadNotePowerState.
4568 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4569 if (ret
!= kIOReturnSuccess
)
4571 // Reservation failed, defer power rise.
4572 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4577 OurChangeTellCapabilityWillChange();
4581 //*********************************************************************************
4582 // [private] requestDomainPowerApplier
4584 // Call requestPowerDomainState() on all power parents.
4585 //*********************************************************************************
4587 struct IOPMRequestDomainPowerContext
{
4588 IOService
* child
; // the requesting child
4589 IOPMPowerFlags requestPowerFlags
; // power flags requested by child
4593 requestDomainPowerApplier(
4594 IORegistryEntry
* entry
,
4597 IOPowerConnection
* connection
;
4599 IOPMRequestDomainPowerContext
* context
;
4601 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0)
4603 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4608 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4610 if (connection
->parentKnowsState() && connection
->getReadyFlag())
4612 parent
->requestPowerDomainState(
4613 context
->requestPowerFlags
,
4621 //*********************************************************************************
4622 // [private] requestDomainPower
4624 // Called by a power child to broadcast its desired power state to all parents.
4625 // If the child self-initiates a power change, it must call this function to
4626 // allow its parents to adjust power state.
4627 //*********************************************************************************
4629 IOReturn
IOService::requestDomainPower(
4630 IOPMPowerStateIndex ourPowerState
,
4631 IOOptionBits options
)
4633 IOPMPowerFlags requestPowerFlags
;
4634 IOPMPowerStateIndex maxPowerState
;
4635 IOPMRequestDomainPowerContext context
;
4637 PM_ASSERT_IN_GATE();
4638 assert(ourPowerState
< fNumberOfPowerStates
);
4639 if (ourPowerState
>= fNumberOfPowerStates
)
4640 return kIOReturnBadArgument
;
4642 return kIOReturnSuccess
;
4644 // Fetch our input power flags for the requested power state.
4645 // Parent request is stated in terms of required power flags.
4647 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4649 // Disregard the "previous request" for power reservation.
4651 if (((options
& kReserveDomainPower
) == 0) &&
4652 (fPreviousRequestPowerFlags
== requestPowerFlags
))
4654 // skip if domain already knows our requirements
4657 fPreviousRequestPowerFlags
= requestPowerFlags
;
4659 // The results will be collected by fHeadNoteDomainTargetFlags
4660 context
.child
= this;
4661 context
.requestPowerFlags
= requestPowerFlags
;
4662 fHeadNoteDomainTargetFlags
= 0;
4663 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4665 if (options
& kReserveDomainPower
)
4667 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4668 fHeadNoteDomainTargetFlags
);
4670 if (StateOrder(maxPowerState
) < StateOrder(ourPowerState
))
4672 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4674 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4675 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4676 return kIOReturnNoPower
;
4681 return kIOReturnSuccess
;
4684 //*********************************************************************************
4685 // [private] OurSyncStart
4686 //*********************************************************************************
4688 void IOService::OurSyncStart( void )
4690 PM_ASSERT_IN_GATE();
4692 if (fInitialPowerChange
)
4695 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4697 if (fHeadNoteChangeFlags
& kIOPMNotDone
)
4703 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
)
4705 fDoNotPowerDown
= false;
4707 // Ask for permission to drop power state
4708 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4709 fOutOfBandParameter
= kNotifyApps
;
4710 askChangeDown(fHeadNotePowerState
);
4714 // Only inform capability app and clients.
4715 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4719 //*********************************************************************************
4720 // [private] OurChangeTellClientsPowerDown
4722 // All applications and kernel clients have acknowledged our permission to drop
4723 // power. Here we notify them that we will lower the power and wait for acks.
4724 //*********************************************************************************
4726 void IOService::OurChangeTellClientsPowerDown( void )
4729 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4732 fMachineState
= kIOPM_OurChangeTellUserPMPolicyPowerDown
;
4734 tellChangeDown1(fHeadNotePowerState
);
4737 //*********************************************************************************
4738 // [private] OurChangeTellUserPMPolicyPowerDown
4740 // All applications and kernel clients have acknowledged our permission to drop
4741 // power. Here we notify power management policy in user-space and wait for acks
4742 // one last time before we lower power
4743 //*********************************************************************************
4744 void IOService::OurChangeTellUserPMPolicyPowerDown ( void )
4746 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4747 fOutOfBandParameter
= kNotifyApps
;
4749 tellClientsWithResponse(kIOPMMessageLastCallBeforeSleep
);
4752 //*********************************************************************************
4753 // [private] OurChangeTellPriorityClientsPowerDown
4755 // All applications and kernel clients have acknowledged our intention to drop
4756 // power. Here we notify "priority" clients that we are lowering power.
4757 //*********************************************************************************
4759 void IOService::OurChangeTellPriorityClientsPowerDown( void )
4761 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4762 tellChangeDown2(fHeadNotePowerState
);
4765 //*********************************************************************************
4766 // [private] OurChangeTellCapabilityWillChange
4768 // Extra stage for root domain to notify apps and drivers about the
4769 // system capability change when raising power state.
4770 //*********************************************************************************
4772 void IOService::OurChangeTellCapabilityWillChange( void )
4774 if (!IS_ROOT_DOMAIN
)
4775 return OurChangeNotifyInterestedDriversWillChange();
4777 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4780 //*********************************************************************************
4781 // [private] OurChangeNotifyInterestedDriversWillChange
4783 // All applications and kernel clients have acknowledged our power state change.
4784 // Here we notify interested drivers pre-change.
4785 //*********************************************************************************
4787 void IOService::OurChangeNotifyInterestedDriversWillChange( void )
4789 IOPMrootDomain
* rootDomain
;
4790 if ((rootDomain
= getPMRootDomain()) == this)
4794 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4797 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4800 notifyAll( kIOPM_OurChangeSetPowerState
);
4803 //*********************************************************************************
4804 // [private] OurChangeSetPowerState
4806 // Instruct our controlling driver to program the hardware for the power state
4807 // change. Wait for async completions.
4808 //*********************************************************************************
4810 void IOService::OurChangeSetPowerState( void )
4812 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4813 fMachineState
= kIOPM_DriverThreadCallDone
;
4814 fDriverCallReason
= kDriverCallSetPowerState
;
4816 if (notifyControllingDriver() == false)
4817 notifyControllingDriverDone();
4820 //*********************************************************************************
4821 // [private] OurChangeWaitForPowerSettle
4823 // Our controlling driver has completed the power state change we initiated.
4824 // Wait for the driver specified settle time to expire.
4825 //*********************************************************************************
4827 void IOService::OurChangeWaitForPowerSettle( void )
4829 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4833 //*********************************************************************************
4834 // [private] OurChangeNotifyInterestedDriversDidChange
4836 // Power has settled on a power change we initiated. Here we notify
4837 // all our interested drivers post-change.
4838 //*********************************************************************************
4840 void IOService::OurChangeNotifyInterestedDriversDidChange( void )
4842 IOPMrootDomain
* rootDomain
;
4843 if ((rootDomain
= getPMRootDomain()) == this)
4845 rootDomain
->tracePoint( IS_POWER_DROP
?
4846 kIOPMTracePointSleepDidChangeInterests
:
4847 kIOPMTracePointWakeDidChangeInterests
);
4850 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4853 //*********************************************************************************
4854 // [private] OurChangeTellCapabilityDidChange
4856 // For root domain to notify capability power-change.
4857 //*********************************************************************************
4859 void IOService::OurChangeTellCapabilityDidChange( void )
4861 if (!IS_ROOT_DOMAIN
)
4862 return OurChangeFinish();
4864 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4865 kIOPMTracePointSleepCapabilityClients
:
4866 kIOPMTracePointWakeCapabilityClients
);
4868 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4871 //*********************************************************************************
4872 // [private] OurChangeFinish
4874 // Done with this self-induced power state change.
4875 //*********************************************************************************
4877 void IOService::OurChangeFinish( void )
4883 // MARK: Power Change Initiated by Parent
4885 //*********************************************************************************
4886 // [private] ParentChangeStart
4888 // Here we begin the processing of a power change initiated by our parent.
4889 //*********************************************************************************
4891 IOReturn
IOService::ParentChangeStart( void )
4893 PM_ASSERT_IN_GATE();
4894 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4896 // Root power domain has transitioned to its max power state
4897 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4898 (kIOPMDomainDidChange
| kIOPMRootChangeUp
))
4900 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4901 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
4907 // Power domain is forcing us to lower power
4908 if ( StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
) )
4910 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4912 // Tell apps and kernel clients
4913 fInitialPowerChange
= false;
4914 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4915 tellChangeDown1(fHeadNotePowerState
);
4916 return IOPMWillAckLater
;
4919 // Power domain is allowing us to raise power up to fHeadNotePowerState
4920 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4922 if ( StateOrder(fDesiredPowerState
) > StateOrder(fCurrentPowerState
) )
4924 if ( StateOrder(fDesiredPowerState
) < StateOrder(fHeadNotePowerState
) )
4926 // We power up, but not all the way
4927 fHeadNotePowerState
= fDesiredPowerState
;
4928 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4929 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4932 // We don't need to change
4933 fHeadNotePowerState
= fCurrentPowerState
;
4934 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4935 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4939 if ( fHeadNoteChangeFlags
& kIOPMDomainDidChange
)
4941 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4943 PM_ACTION_2(actionPowerChangeStart
,
4944 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4946 // Parent did change up - start our change up
4947 fInitialPowerChange
= false;
4948 ParentChangeTellCapabilityWillChange();
4949 return IOPMWillAckLater
;
4951 else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
)
4953 // No need to change power state, but broadcast change
4955 fMachineState
= kIOPM_SyncNotifyDidChange
;
4956 fDriverCallReason
= kDriverCallInformPreChange
;
4957 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4959 return IOPMWillAckLater
;
4963 // No power state change necessary
4964 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4967 return IOPMAckImplied
;
4970 //******************************************************************************
4971 // [private] ParentChangeRootChangeDown
4973 // Root domain has finished the transition to the system sleep state. And all
4974 // drivers in the power plane should have powered down. Cancel the idle timer,
4975 // and also reset the device desire for those drivers that don't want power
4976 // automatically restored on wake.
4977 //******************************************************************************
4979 void IOService::ParentChangeRootChangeDown( void )
4981 // Always stop the idle timer before root power down
4982 if (fIdleTimerPeriod
&& !fIdleTimerStopped
)
4984 fIdleTimerStopped
= true;
4985 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
4989 if (fResetPowerStateOnWake
)
4991 // Reset device desire down to the lowest power state.
4992 // Advisory tickle desire is intentionally untouched since
4993 // it has no effect until system is promoted to full wake.
4995 if (fDeviceDesire
!= kPowerStateZero
)
4997 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4998 computeDesiredState(kPowerStateZero
, true);
4999 requestDomainPower( fDesiredPowerState
);
5000 PM_LOG1("%s: tickle desire removed\n", fName
);
5003 // Invalidate tickle cache so the next tickle will issue a request
5004 IOLockLock(fActivityLock
);
5005 fDeviceWasActive
= false;
5006 fActivityTicklePowerState
= kInvalidTicklePowerState
;
5007 IOLockUnlock(fActivityLock
);
5009 fIdleTimerMinPowerState
= kPowerStateZero
;
5011 else if (fAdvisoryTickleUsed
)
5013 // Less aggressive mechanism to accelerate idle timer expiration
5014 // before system sleep. May not always allow the driver to wake
5015 // up from system sleep in the min power state.
5019 bool dropTickleDesire
= false;
5021 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
5022 (fIdleTimerMinPowerState
== kPowerStateZero
) &&
5023 (fDeviceDesire
!= kPowerStateZero
))
5025 IOLockLock(fActivityLock
);
5027 if (!fDeviceWasActive
)
5029 // No tickles since the last idle timer expiration.
5030 // Safe to drop the device desire to zero.
5031 dropTickleDesire
= true;
5035 // Was tickled since the last idle timer expiration,
5036 // but not in the last minute.
5037 clock_get_uptime(&now
);
5038 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
5039 absolutetime_to_nanoseconds(now
, &nsec
);
5040 if (nsec
>= kNoTickleCancelWindow
)
5042 dropTickleDesire
= true;
5046 if (dropTickleDesire
)
5048 // Force the next tickle to raise power state
5049 fDeviceWasActive
= false;
5050 fActivityTicklePowerState
= kInvalidTicklePowerState
;
5053 IOLockUnlock(fActivityLock
);
5056 if (dropTickleDesire
)
5058 // Advisory tickle desire is intentionally untouched since
5059 // it has no effect until system is promoted to full wake.
5061 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
5062 computeDesiredState(kPowerStateZero
, true);
5063 PM_LOG1("%s: tickle desire dropped\n", fName
);
5068 //*********************************************************************************
5069 // [private] ParentChangeTellPriorityClientsPowerDown
5071 // All applications and kernel clients have acknowledged our intention to drop
5072 // power. Here we notify "priority" clients that we are lowering power.
5073 //*********************************************************************************
5075 void IOService::ParentChangeTellPriorityClientsPowerDown( void )
5077 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
5078 tellChangeDown2(fHeadNotePowerState
);
5081 //*********************************************************************************
5082 // [private] ParentChangeTellCapabilityWillChange
5084 // All (legacy) applications and kernel clients have acknowledged, extra stage for
5085 // root domain to notify apps and drivers about the system capability change.
5086 //*********************************************************************************
5088 void IOService::ParentChangeTellCapabilityWillChange( void )
5090 if (!IS_ROOT_DOMAIN
)
5091 return ParentChangeNotifyInterestedDriversWillChange();
5093 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
5096 //*********************************************************************************
5097 // [private] ParentChangeNotifyInterestedDriversWillChange
5099 // All applications and kernel clients have acknowledged our power state change.
5100 // Here we notify interested drivers pre-change.
5101 //*********************************************************************************
5103 void IOService::ParentChangeNotifyInterestedDriversWillChange( void )
5105 notifyAll( kIOPM_ParentChangeSetPowerState
);
5108 //*********************************************************************************
5109 // [private] ParentChangeSetPowerState
5111 // Instruct our controlling driver to program the hardware for the power state
5112 // change. Wait for async completions.
5113 //*********************************************************************************
5115 void IOService::ParentChangeSetPowerState( void )
5117 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
5118 fMachineState
= kIOPM_DriverThreadCallDone
;
5119 fDriverCallReason
= kDriverCallSetPowerState
;
5121 if (notifyControllingDriver() == false)
5122 notifyControllingDriverDone();
5125 //*********************************************************************************
5126 // [private] ParentChangeWaitForPowerSettle
5128 // Our controlling driver has completed the power state change initiated by our
5129 // parent. Wait for the driver specified settle time to expire.
5130 //*********************************************************************************
5132 void IOService::ParentChangeWaitForPowerSettle( void )
5134 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
5138 //*********************************************************************************
5139 // [private] ParentChangeNotifyInterestedDriversDidChange
5141 // Power has settled on a power change initiated by our parent. Here we notify
5142 // all our interested drivers post-change.
5143 //*********************************************************************************
5145 void IOService::ParentChangeNotifyInterestedDriversDidChange( void )
5147 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
5150 //*********************************************************************************
5151 // [private] ParentChangeTellCapabilityDidChange
5153 // For root domain to notify capability power-change.
5154 //*********************************************************************************
5156 void IOService::ParentChangeTellCapabilityDidChange( void )
5158 if (!IS_ROOT_DOMAIN
)
5159 return ParentChangeAcknowledgePowerChange();
5161 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
5164 //*********************************************************************************
5165 // [private] ParentAcknowledgePowerChange
5167 // Acknowledge our power parent that our power change is done.
5168 //*********************************************************************************
5170 void IOService::ParentChangeAcknowledgePowerChange( void )
5172 IORegistryEntry
* nub
;
5175 nub
= fHeadNoteParentConnection
;
5178 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
5181 parent
->acknowledgePowerChange((IOService
*)nub
);
5188 // MARK: Ack and Settle timers
5190 //*********************************************************************************
5191 // [private] settleTimerExpired
5193 // Power has settled after our last change. Notify interested parties that
5194 // there is a new power state.
5195 //*********************************************************************************
5197 void IOService::settleTimerExpired( void )
5200 gIOPMWorkQueue
->signalWorkAvailable();
5203 //*********************************************************************************
5204 // settle_timer_expired
5206 // Holds a retain while the settle timer callout is in flight.
5207 //*********************************************************************************
5210 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5212 IOService
* me
= (IOService
*) arg0
;
5214 if (gIOPMWorkLoop
&& gIOPMWorkQueue
)
5216 gIOPMWorkLoop
->runAction(
5217 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5223 //*********************************************************************************
5224 // [private] startSettleTimer
5226 // Calculate a power-settling delay in microseconds and start a timer.
5227 //*********************************************************************************
5229 void IOService::startSettleTimer( void )
5232 // This function is broken and serves no useful purpose since it never
5233 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5234 // yet it starts a delay timer. It appears no driver relies on a delay
5235 // from settleUpTime and settleDownTime in the power state table.
5237 AbsoluteTime deadline
;
5238 IOPMPowerStateIndex stateIndex
;
5239 IOPMPowerStateIndex currentOrder
, newOrder
, i
;
5240 uint32_t settleTime
= 0;
5243 PM_ASSERT_IN_GATE();
5245 currentOrder
= StateOrder(fCurrentPowerState
);
5246 newOrder
= StateOrder(fHeadNotePowerState
);
5251 if ( newOrder
< currentOrder
)
5253 while ( i
> newOrder
)
5255 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
5256 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleDownTime
;
5262 if ( newOrder
> currentOrder
)
5264 while ( i
< newOrder
)
5266 stateIndex
= fPowerStates
[i
+1].stateOrderToIndex
;
5267 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleUpTime
;
5275 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5276 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5277 if (pending
) release();
5282 //*********************************************************************************
5283 // [private] ackTimerTick
5285 // The acknowledgement timeout periodic timer has ticked.
5286 // If we are awaiting acks for a power change notification,
5287 // we decrement the timer word of each interested driver which hasn't acked.
5288 // If a timer word becomes zero, we pretend the driver aknowledged.
5289 // If we are waiting for the controlling driver to change the power
5290 // state of the hardware, we decrement its timer word, and if it becomes
5291 // zero, we pretend the driver acknowledged.
5293 // Returns true if the timer tick made it possible to advance to the next
5294 // machine state, false otherwise.
5295 //*********************************************************************************
5298 void IOService::ack_timer_ticked ( void )
5302 #endif /* !__LP64__ */
5304 bool IOService::ackTimerTick( void )
5306 IOPMinformee
* nextObject
;
5309 PM_ASSERT_IN_GATE();
5310 switch (fMachineState
) {
5311 case kIOPM_OurChangeWaitForPowerSettle
:
5312 case kIOPM_ParentChangeWaitForPowerSettle
:
5313 // are we waiting for controlling driver to acknowledge?
5314 if ( fDriverTimer
> 0 )
5316 // yes, decrement timer tick
5318 if ( fDriverTimer
== 0 )
5320 // controlling driver is tardy
5321 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5322 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
5323 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
5324 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5325 fName
, OBFUSCATE(this), fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5327 #if DEBUG && CONFIG_EMBEDDED
5328 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5329 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5331 if (gIOKitDebug
& kIOLogDebugPower
)
5333 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5334 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5338 // Unblock state machine and pretend driver has acked.
5342 getPMRootDomain()->reset_watchdog_timer(this, 0);
5344 // still waiting, set timer again
5350 case kIOPM_NotifyChildrenStart
:
5351 // are we waiting for interested parties to acknowledge?
5352 if ( fHeadNotePendingAcks
!= 0 )
5354 // yes, go through the list of interested drivers
5355 nextObject
= fInterestedDrivers
->firstInList();
5356 // and check each one
5357 while ( nextObject
!= NULL
)
5359 if ( nextObject
->timer
> 0 )
5361 nextObject
->timer
--;
5362 // this one should have acked by now
5363 if ( nextObject
->timer
== 0 )
5365 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5366 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5367 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5368 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5369 nextObject
->whatObject
->getName(),
5370 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5371 OBFUSCATE(nextObject
->whatObject
), fName
, fCurrentPowerState
, fHeadNotePowerState
,
5374 // Pretend driver has acked.
5375 fHeadNotePendingAcks
--;
5378 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5381 // is that the last?
5382 if ( fHeadNotePendingAcks
== 0 )
5384 // yes, we can continue
5387 // no, set timer again
5393 // TODO: aggreggate this
5394 case kIOPM_OurChangeTellClientsPowerDown
:
5395 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
5396 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5397 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5398 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5399 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5400 case kIOPM_SyncTellClientsPowerDown
:
5401 case kIOPM_SyncTellPriorityClientsPowerDown
:
5402 case kIOPM_SyncNotifyWillChange
:
5403 case kIOPM_TellCapabilityChangeDone
:
5404 // apps didn't respond in time
5405 cleanClientResponses(true);
5406 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5407 // tardy equates to approval
5412 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5413 getName(), fMachineState
);
5419 //*********************************************************************************
5420 // [private] start_watchdog_timer
5421 //*********************************************************************************
5422 void IOService::start_watchdog_timer( void )
5427 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5430 IOLockLock(fWatchdogLock
);
5432 timeout
= getPMRootDomain()->getWatchdogTimeout();
5433 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5434 fWatchdogDeadline
= deadline
;
5435 start_watchdog_timer(deadline
);
5436 IOLockUnlock(fWatchdogLock
);
5439 void IOService::start_watchdog_timer(uint64_t deadline
)
5442 IOLockAssert(fWatchdogLock
, kIOLockAssertOwned
);
5444 if (!thread_call_isactive(fWatchdogTimer
)) {
5445 thread_call_enter_delayed(fWatchdogTimer
, deadline
);
5450 //*********************************************************************************
5451 // [private] stop_watchdog_timer
5452 //*********************************************************************************
5454 void IOService::stop_watchdog_timer( void )
5456 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5459 IOLockLock(fWatchdogLock
);
5461 thread_call_cancel(fWatchdogTimer
);
5462 fWatchdogDeadline
= 0;
5464 while (fBlockedArray
->getCount()) {
5465 IOService
*obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(0));
5467 PM_ERROR("WDOG:Object %s unexpected in blocked array\n", obj
->fName
);
5468 fBlockedArray
->removeObject(0);
5472 IOLockUnlock(fWatchdogLock
);
5475 //*********************************************************************************
5476 // reset_watchdog_timer
5477 //*********************************************************************************
5479 void IOService::reset_watchdog_timer(IOService
*blockedObject
, int pendingResponseTimeout
)
5485 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5489 IOLockLock(fWatchdogLock
);
5490 if (!fWatchdogDeadline
) {
5494 i
= fBlockedArray
->getNextIndexOfObject(blockedObject
, 0);
5495 if (pendingResponseTimeout
== 0) {
5496 blockedObject
->fPendingResponseDeadline
= 0;
5497 if (i
== (unsigned int)-1) {
5500 fBlockedArray
->removeObject(i
);
5503 // Set deadline 2secs after the expected response timeout to allow
5504 // ack timer to handle the timeout.
5505 clock_interval_to_deadline(pendingResponseTimeout
+2, kSecondScale
, &deadline
);
5507 if (i
!= (unsigned int)-1) {
5508 PM_ERROR("WDOG:Object %s is already blocked for responses. Ignoring timeout %d\n",
5509 fName
, pendingResponseTimeout
);
5514 for (i
= 0; i
< fBlockedArray
->getCount(); i
++) {
5515 obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(i
));
5516 if (obj
&& (obj
->fPendingResponseDeadline
< deadline
)) {
5517 blockedObject
->fPendingResponseDeadline
= deadline
;
5518 fBlockedArray
->setObject(i
, blockedObject
);
5522 if (i
== fBlockedArray
->getCount()) {
5523 blockedObject
->fPendingResponseDeadline
= deadline
;
5524 fBlockedArray
->setObject(blockedObject
);
5528 obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(0));
5530 int timeout
= getPMRootDomain()->getWatchdogTimeout();
5531 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5534 deadline
= obj
->fPendingResponseDeadline
;
5537 thread_call_cancel(fWatchdogTimer
);
5538 start_watchdog_timer(deadline
);
5541 IOLockUnlock(fWatchdogLock
);
5545 //*********************************************************************************
5546 // [static] watchdog_timer_expired
5548 // Inside PM work loop's gate.
5549 //*********************************************************************************
5552 IOService::watchdog_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5554 IOService
* me
= (IOService
*) arg0
;
5557 gIOPMWatchDogThread
= current_thread();
5558 getPMRootDomain()->sleepWakeDebugTrig(true);
5559 gIOPMWatchDogThread
= 0;
5560 thread_call_free(me
->fWatchdogTimer
);
5561 me
->fWatchdogTimer
= 0;
5567 IOWorkLoop
* IOService::getIOPMWorkloop( void )
5569 return gIOPMWorkLoop
;
5574 //*********************************************************************************
5575 // [private] start_ack_timer
5576 //*********************************************************************************
5578 void IOService::start_ack_timer( void )
5580 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5583 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
5585 AbsoluteTime deadline
;
5588 clock_interval_to_deadline(interval
, scale
, &deadline
);
5591 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5592 if (pending
) release();
5596 //*********************************************************************************
5597 // [private] stop_ack_timer
5598 //*********************************************************************************
5600 void IOService::stop_ack_timer( void )
5604 pending
= thread_call_cancel(fAckTimer
);
5605 if (pending
) release();
5608 //*********************************************************************************
5609 // [static] actionAckTimerExpired
5611 // Inside PM work loop's gate.
5612 //*********************************************************************************
5615 IOService::actionAckTimerExpired(
5617 void * arg0
, void * arg1
,
5618 void * arg2
, void * arg3
)
5620 IOService
* me
= (IOService
*) target
;
5623 // done will be true if the timer tick unblocks the machine state,
5624 // otherwise no need to signal the work loop.
5626 done
= me
->ackTimerTick();
5627 if (done
&& gIOPMWorkQueue
)
5629 gIOPMWorkQueue
->signalWorkAvailable();
5632 return kIOReturnSuccess
;
5635 //*********************************************************************************
5636 // ack_timer_expired
5638 // Thread call function. Holds a retain while the callout is in flight.
5639 //*********************************************************************************
5642 IOService::ack_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5644 IOService
* me
= (IOService
*) arg0
;
5648 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5653 //*********************************************************************************
5654 // [private] start_spindump_timer
5655 //*********************************************************************************
5657 void IOService::start_spindump_timer( const char * delay_type
)
5659 AbsoluteTime deadline
;
5662 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
))
5665 if (gIOSpinDumpKextName
[0] == '\0' &&
5666 !(PE_parse_boot_argn("swd_kext_name", &gIOSpinDumpKextName
,
5667 sizeof(gIOSpinDumpKextName
))))
5672 if (strncmp(gIOSpinDumpKextName
, fName
, sizeof(gIOSpinDumpKextName
)) != 0)
5675 if (gIOSpinDumpDelayType
[0] == '\0' &&
5676 !(PE_parse_boot_argn("swd_delay_type", &gIOSpinDumpDelayType
,
5677 sizeof(gIOSpinDumpDelayType
))))
5679 strncpy(gIOSpinDumpDelayType
, "SetState", sizeof(gIOSpinDumpDelayType
));
5682 if (strncmp(delay_type
, gIOSpinDumpDelayType
, sizeof(gIOSpinDumpDelayType
)) != 0)
5685 if (gIOSpinDumpDelayDuration
== 0 &&
5686 !(PE_parse_boot_argn("swd_delay_duration", &gIOSpinDumpDelayDuration
,
5687 sizeof(gIOSpinDumpDelayDuration
))))
5689 gIOSpinDumpDelayDuration
= 300;
5692 clock_interval_to_deadline(gIOSpinDumpDelayDuration
, kMillisecondScale
, &deadline
);
5695 pending
= thread_call_enter_delayed(fSpinDumpTimer
, deadline
);
5696 if (pending
) release();
5699 //*********************************************************************************
5700 // [private] stop_spindump_timer
5701 //*********************************************************************************
5703 void IOService::stop_spindump_timer( void )
5707 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
))
5710 pending
= thread_call_cancel(fSpinDumpTimer
);
5711 if (pending
) release();
5715 //*********************************************************************************
5716 // [static] actionSpinDumpTimerExpired
5718 // Inside PM work loop's gate.
5719 //*********************************************************************************
5722 IOService::actionSpinDumpTimerExpired(
5724 void * arg0
, void * arg1
,
5725 void * arg2
, void * arg3
)
5727 getPMRootDomain()->takeStackshot(false, false, true);
5729 return kIOReturnSuccess
;
5732 //*********************************************************************************
5733 // spindump_timer_expired
5735 // Thread call function. Holds a retain while the callout is in flight.
5736 //*********************************************************************************
5739 IOService::spindump_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5741 IOService
* me
= (IOService
*) arg0
;
5745 gIOPMWorkLoop
->runAction(&actionSpinDumpTimerExpired
, me
);
5751 // MARK: Client Messaging
5753 //*********************************************************************************
5754 // [private] tellSystemCapabilityChange
5755 //*********************************************************************************
5757 void IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5760 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5761 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5765 // Notify app first on pre-change.
5766 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5770 // Notify kernel clients first on post-change.
5771 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5774 tellClientsWithResponse( fOutOfBandMessage
);
5777 //*********************************************************************************
5778 // [public] askChangeDown
5780 // Ask registered applications and kernel clients if we can change to a lower
5783 // Subclass can override this to send a different message type. Parameter is
5784 // the destination state number.
5786 // Return true if we don't have to wait for acknowledgements
5787 //*********************************************************************************
5789 bool IOService::askChangeDown( unsigned long stateNum
)
5791 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5794 //*********************************************************************************
5795 // [private] tellChangeDown1
5797 // Notify registered applications and kernel clients that we are definitely
5800 // Return true if we don't have to wait for acknowledgements
5801 //*********************************************************************************
5803 bool IOService::tellChangeDown1( unsigned long stateNum
)
5805 fOutOfBandParameter
= kNotifyApps
;
5806 return tellChangeDown(stateNum
);
5809 //*********************************************************************************
5810 // [private] tellChangeDown2
5812 // Notify priority clients that we are definitely dropping power.
5814 // Return true if we don't have to wait for acknowledgements
5815 //*********************************************************************************
5817 bool IOService::tellChangeDown2( unsigned long stateNum
)
5819 fOutOfBandParameter
= kNotifyPriority
;
5820 return tellChangeDown(stateNum
);
5823 //*********************************************************************************
5824 // [public] tellChangeDown
5826 // Notify registered applications and kernel clients that we are definitely
5829 // Subclass can override this to send a different message type. Parameter is
5830 // the destination state number.
5832 // Return true if we don't have to wait for acknowledgements
5833 //*********************************************************************************
5835 bool IOService::tellChangeDown( unsigned long stateNum
)
5837 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5840 //*********************************************************************************
5841 // cleanClientResponses
5843 //*********************************************************************************
5845 static void logAppTimeouts( OSObject
* object
, void * arg
)
5847 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5849 unsigned int clientIndex
;
5853 if (OSDynamicCast(_IOServiceInterestNotifier
, object
))
5855 // Discover the 'counter' value or index assigned to this client
5856 // when it was notified, by searching for the array index of the
5857 // client in an array holding the cached interested clients.
5859 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5861 if ((clientIndex
!= (unsigned int) -1) &&
5862 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5863 (flag
!= kOSBooleanTrue
))
5865 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5869 pid
= clientID
->unsigned32BitValue();
5870 proc_name(pid
, name
, sizeof(name
));
5871 clientID
->release();
5874 PM_ERROR(context
->errorLog
, pid
, name
);
5876 // TODO: record message type if possible
5877 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5878 gIOPMStatsResponseTimedOut
,
5879 name
, 0, (30*1000), pid
, object
);
5885 void IOService::cleanClientResponses( bool logErrors
)
5887 if (logErrors
&& fResponseArray
)
5889 switch ( fOutOfBandParameter
) {
5891 case kNotifyCapabilityChangeApps
:
5892 if (fNotifyClientArray
)
5894 IOPMInterestContext context
;
5896 context
.responseArray
= fResponseArray
;
5897 context
.notifyClients
= fNotifyClientArray
;
5898 context
.serialNumber
= fSerialNumber
;
5899 context
.messageType
= kIOMessageCopyClientID
;
5900 context
.notifyType
= kNotifyApps
;
5901 context
.isPreChange
= fIsPreChange
;
5902 context
.enableTracing
= false;
5904 context
.maxTimeRequested
= 0;
5905 context
.stateNumber
= fHeadNotePowerState
;
5906 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5907 context
.changeFlags
= fHeadNoteChangeFlags
;
5908 context
.errorLog
= "PM notification timeout (pid %d, %s)\n";
5910 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5915 // kNotifyPriority, kNotifyCapabilityChangePriority
5916 // TODO: identify the priority client that has not acked
5917 PM_ERROR("PM priority notification timeout\n");
5918 if (gIOKitDebug
& kIOLogDebugPower
)
5920 panic("PM priority notification timeout");
5926 if (IS_ROOT_DOMAIN
) {
5927 getPMRootDomain()->reset_watchdog_timer(this, 0);
5931 fResponseArray
->release();
5932 fResponseArray
= NULL
;
5934 if (fNotifyClientArray
)
5936 fNotifyClientArray
->release();
5937 fNotifyClientArray
= NULL
;
5941 //*********************************************************************************
5942 // [protected] tellClientsWithResponse
5944 // Notify registered applications and kernel clients that we are definitely
5947 // Return true if we don't have to wait for acknowledgements
5948 //*********************************************************************************
5950 bool IOService::tellClientsWithResponse( int messageType
)
5952 IOPMInterestContext context
;
5953 bool isRootDomain
= IS_ROOT_DOMAIN
;
5954 uint32_t maxTimeOut
= kMaxTimeRequested
;
5956 PM_ASSERT_IN_GATE();
5957 assert( fResponseArray
== NULL
);
5958 assert( fNotifyClientArray
== NULL
);
5960 if(messageType
== (int)kIOPMMessageLastCallBeforeSleep
)
5961 RD_LOG("tellClientsWithResponse( kIOPMMessageLastCallBeforeSleep, %d )\n",
5962 fOutOfBandParameter
);
5964 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5965 getIOMessageString(messageType
), fOutOfBandParameter
);
5967 fResponseArray
= OSArray::withCapacity( 1 );
5968 if (!fResponseArray
)
5971 fResponseArray
->setCapacityIncrement(8);
5972 if (++fSerialNumber
== 0)
5975 context
.responseArray
= fResponseArray
;
5976 context
.notifyClients
= 0;
5977 context
.serialNumber
= fSerialNumber
;
5978 context
.messageType
= messageType
;
5979 context
.notifyType
= fOutOfBandParameter
;
5980 context
.isPreChange
= fIsPreChange
;
5981 context
.enableTracing
= false;
5983 context
.maxTimeRequested
= 0;
5984 context
.stateNumber
= fHeadNotePowerState
;
5985 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5986 context
.changeFlags
= fHeadNoteChangeFlags
;
5987 context
.messageFilter
= (isRootDomain
) ?
5988 OSMemberFunctionCast(
5991 &IOPMrootDomain::systemMessageFilter
) : 0;
5993 switch ( fOutOfBandParameter
) {
5995 applyToInterested( gIOAppPowerStateInterest
,
5996 pmTellAppWithResponse
, (void *) &context
);
5999 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
6000 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
) &&
6001 (context
.messageType
!= kIOPMMessageLastCallBeforeSleep
))
6003 // Notify capability app for tellChangeDown1()
6004 // but not for askChangeDown().
6005 context
.notifyType
= kNotifyCapabilityChangeApps
;
6006 context
.messageType
= kIOMessageSystemCapabilityChange
;
6007 applyToInterested( gIOAppPowerStateInterest
,
6008 pmTellCapabilityAppWithResponse
, (void *) &context
);
6009 context
.notifyType
= fOutOfBandParameter
;
6010 context
.messageType
= messageType
;
6012 if(context
.messageType
== kIOMessageCanSystemSleep
)
6014 maxTimeOut
= kCanSleepMaxTimeReq
;
6015 if(gCanSleepTimeout
)
6017 maxTimeOut
= (gCanSleepTimeout
*us_per_s
);
6020 context
.maxTimeRequested
= maxTimeOut
;
6021 context
.enableTracing
= isRootDomain
;
6022 applyToInterested( gIOGeneralInterest
,
6023 pmTellClientWithResponse
, (void *) &context
);
6027 case kNotifyPriority
:
6028 context
.enableTracing
= isRootDomain
;
6029 applyToInterested( gIOPriorityPowerStateInterest
,
6030 pmTellClientWithResponse
, (void *) &context
);
6034 // Notify capability clients for tellChangeDown2().
6035 context
.notifyType
= kNotifyCapabilityChangePriority
;
6036 context
.messageType
= kIOMessageSystemCapabilityChange
;
6037 applyToInterested( gIOPriorityPowerStateInterest
,
6038 pmTellCapabilityClientWithResponse
, (void *) &context
);
6042 case kNotifyCapabilityChangeApps
:
6043 applyToInterested( gIOAppPowerStateInterest
,
6044 pmTellCapabilityAppWithResponse
, (void *) &context
);
6045 if(context
.messageType
== kIOMessageCanSystemSleep
)
6047 maxTimeOut
= kCanSleepMaxTimeReq
;
6048 if(gCanSleepTimeout
)
6050 maxTimeOut
= (gCanSleepTimeout
*us_per_s
);
6053 context
.maxTimeRequested
= maxTimeOut
;
6056 case kNotifyCapabilityChangePriority
:
6057 context
.enableTracing
= isRootDomain
;
6058 applyToInterested( gIOPriorityPowerStateInterest
,
6059 pmTellCapabilityClientWithResponse
, (void *) &context
);
6062 fNotifyClientArray
= context
.notifyClients
;
6064 // do we have to wait for somebody?
6065 if ( !checkForDone() )
6067 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
6068 if (context
.enableTracing
) {
6069 getPMRootDomain()->traceDetail(context
.messageType
, 0, context
.maxTimeRequested
/ 1000);
6070 getPMRootDomain()->reset_watchdog_timer(this, context
.maxTimeRequested
/USEC_PER_SEC
+1);
6072 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
6077 // everybody responded
6080 fResponseArray
->release();
6081 fResponseArray
= NULL
;
6083 if (fNotifyClientArray
)
6085 fNotifyClientArray
->release();
6086 fNotifyClientArray
= NULL
;
6092 //*********************************************************************************
6093 // [static private] pmTellAppWithResponse
6095 // We send a message to an application, and we expect a response, so we compute a
6096 // cookie we can identify the response with.
6097 //*********************************************************************************
6099 void IOService::pmTellAppWithResponse( OSObject
* object
, void * arg
)
6101 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6102 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6103 uint32_t msgIndex
, msgRef
, msgType
;
6104 OSNumber
*clientID
= NULL
;
6106 boolean_t proc_suspended
= FALSE
;
6107 OSObject
* waitForReply
= kOSBooleanTrue
;
6108 #if LOG_APP_RESPONSE_TIMES
6112 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
6115 if (context
->us
== getPMRootDomain())
6117 if ((clientID
= copyClientIDForNotification(object
, context
)))
6119 uint32_t clientPID
= clientID
->unsigned32BitValue();
6120 clientID
->release();
6121 proc
= proc_find(clientPID
);
6125 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6130 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
6137 if (context
->messageFilter
&&
6138 !context
->messageFilter(context
->us
, object
, context
, 0, &waitForReply
))
6140 if (kIOLogDebugPower
& gIOKitDebug
)
6142 logClientIDForNotification(object
, context
, "DROP App");
6147 // Create client array (for tracking purposes) only if the service
6148 // has app clients. Usually only root domain does.
6149 if (0 == context
->notifyClients
)
6150 context
->notifyClients
= OSArray::withCapacity( 32 );
6152 msgType
= context
->messageType
;
6153 msgIndex
= context
->responseArray
->getCount();
6154 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6156 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6157 if (kIOLogDebugPower
& gIOKitDebug
)
6159 logClientIDForNotification(object
, context
, "MESG App");
6162 if (waitForReply
== kOSBooleanTrue
)
6166 clock_get_uptime(&now
);
6167 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6170 context
->responseArray
->setObject(msgIndex
, num
);
6174 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6179 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6180 if (kIOLogDebugPower
& gIOKitDebug
)
6182 logClientIDForNotification(object
, context
, "App response ignored");
6186 if (context
->notifyClients
)
6187 context
->notifyClients
->setObject(msgIndex
, object
);
6189 context
->us
->messageClient(msgType
, object
, (void *)(uintptr_t) msgRef
);
6192 //*********************************************************************************
6193 // [static private] pmTellClientWithResponse
6195 // We send a message to an in-kernel client, and we expect a response,
6196 // so we compute a cookie we can identify the response with.
6197 //*********************************************************************************
6199 void IOService::pmTellClientWithResponse( OSObject
* object
, void * arg
)
6201 IOPowerStateChangeNotification notify
;
6202 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6203 OSObject
* replied
= kOSBooleanTrue
;
6204 _IOServiceInterestNotifier
* notifier
;
6205 uint32_t msgIndex
, msgRef
, msgType
;
6207 AbsoluteTime start
, end
;
6210 if (context
->messageFilter
&&
6211 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6213 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6214 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6216 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6217 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6218 context
->us
->getName(),
6219 getIOMessageString(context
->messageType
),
6220 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6225 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6226 msgType
= context
->messageType
;
6227 msgIndex
= context
->responseArray
->getCount();
6228 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6230 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6231 if (gIOKitDebug
& kIOLogPower
) {
6232 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6233 if (OSDynamicCast(IOService
, object
)) {
6234 const char *who
= ((IOService
*) object
)->getName();
6235 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6237 else if (notifier
) {
6238 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6241 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6243 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6244 context
->us
->getName(),
6245 getIOMessageString(msgType
),
6246 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6249 if (0 == context
->notifyClients
)
6250 context
->notifyClients
= OSArray::withCapacity( 32 );
6252 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
6253 notify
.returnValue
= 0;
6254 notify
.stateNumber
= context
->stateNumber
;
6255 notify
.stateFlags
= context
->stateFlags
;
6257 if (context
->enableTracing
&& (notifier
!= 0))
6259 getPMRootDomain()->traceDetail(notifier
, true);
6262 clock_get_uptime(&start
);
6263 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
6264 clock_get_uptime(&end
);
6266 if (context
->enableTracing
&& (notifier
!= NULL
))
6268 getPMRootDomain()->traceDetail(notifier
, false);
6272 if (kIOReturnSuccess
== retCode
)
6274 if (0 == notify
.returnValue
) {
6275 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6276 context
->responseArray
->setObject(msgIndex
, replied
);
6278 replied
= kOSBooleanFalse
;
6279 if ( notify
.returnValue
> context
->maxTimeRequested
)
6281 if (notify
.returnValue
> kPriorityClientMaxWait
)
6283 context
->maxTimeRequested
= kPriorityClientMaxWait
;
6284 PM_ERROR("%s: client %p returned %llu for %s\n",
6285 context
->us
->getName(),
6286 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6287 (uint64_t) notify
.returnValue
,
6288 getIOMessageString(msgType
));
6291 context
->maxTimeRequested
= notify
.returnValue
;
6294 // Track time taken to ack, by storing the timestamp of
6295 // callback completion
6297 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6299 context
->responseArray
->setObject(msgIndex
, num
);
6303 context
->responseArray
->setObject(msgIndex
, replied
);
6307 if (context
->enableTracing
) {
6308 SUB_ABSOLUTETIME(&end
, &start
);
6309 absolutetime_to_nanoseconds(end
, &nsec
);
6311 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (notify
.returnValue
!= 0)) {
6312 getPMRootDomain()->traceAckDelay(notifier
, notify
.returnValue
/1000, NS_TO_MS(nsec
));
6317 // not a client of ours
6318 // so we won't be waiting for response
6319 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6320 context
->responseArray
->setObject(msgIndex
, replied
);
6322 if (context
->notifyClients
) {
6323 context
->notifyClients
->setObject(msgIndex
, object
);
6328 //*********************************************************************************
6329 // [static private] pmTellCapabilityAppWithResponse
6330 //*********************************************************************************
6332 void IOService::pmTellCapabilityAppWithResponse( OSObject
* object
, void * arg
)
6334 IOPMSystemCapabilityChangeParameters msgArg
;
6335 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6336 OSObject
* replied
= kOSBooleanTrue
;
6337 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6338 uint32_t msgIndex
, msgRef
, msgType
;
6339 #if LOG_APP_RESPONSE_TIMES
6343 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
6346 memset(&msgArg
, 0, sizeof(msgArg
));
6347 if (context
->messageFilter
&&
6348 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
))
6353 // Create client array (for tracking purposes) only if the service
6354 // has app clients. Usually only root domain does.
6355 if (0 == context
->notifyClients
)
6356 context
->notifyClients
= OSArray::withCapacity( 32 );
6358 msgType
= context
->messageType
;
6359 msgIndex
= context
->responseArray
->getCount();
6360 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6362 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6363 if (kIOLogDebugPower
& gIOKitDebug
)
6365 // Log client pid/name and client array index.
6366 OSNumber
* clientID
= NULL
;
6367 OSString
* clientIDString
= NULL
;;
6368 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6370 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6373 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
6374 context
->us
->getName(),
6375 msgIndex
, getIOMessageString(msgType
),
6376 (replied
!= kOSBooleanTrue
),
6377 clientIDString
? clientIDString
->getCStringNoCopy() : "");
6378 if (clientID
) clientID
->release();
6379 if (clientIDString
) clientIDString
->release();
6382 msgArg
.notifyRef
= msgRef
;
6383 msgArg
.maxWaitForReply
= 0;
6385 if (replied
== kOSBooleanTrue
)
6387 msgArg
.notifyRef
= 0;
6388 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6389 if (context
->notifyClients
)
6390 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
6396 clock_get_uptime(&now
);
6397 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6400 context
->responseArray
->setObject(msgIndex
, num
);
6404 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6407 if (context
->notifyClients
)
6408 context
->notifyClients
->setObject(msgIndex
, object
);
6411 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6414 //*********************************************************************************
6415 // [static private] pmTellCapabilityClientWithResponse
6416 //*********************************************************************************
6418 void IOService::pmTellCapabilityClientWithResponse(
6419 OSObject
* object
, void * arg
)
6421 IOPMSystemCapabilityChangeParameters msgArg
;
6422 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6423 OSObject
* replied
= kOSBooleanTrue
;
6424 _IOServiceInterestNotifier
* notifier
;
6425 uint32_t msgIndex
, msgRef
, msgType
;
6427 AbsoluteTime start
, end
;
6430 memset(&msgArg
, 0, sizeof(msgArg
));
6431 if (context
->messageFilter
&&
6432 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, 0))
6434 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6435 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6437 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6438 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6439 context
->us
->getName(),
6440 getIOMessageString(context
->messageType
),
6441 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6446 if (0 == context
->notifyClients
) {
6447 context
->notifyClients
= OSArray::withCapacity( 32 );
6449 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6450 msgType
= context
->messageType
;
6451 msgIndex
= context
->responseArray
->getCount();
6452 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6454 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6455 if (gIOKitDebug
& kIOLogPower
) {
6456 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6457 if (OSDynamicCast(IOService
, object
)) {
6458 const char *who
= ((IOService
*) object
)->getName();
6459 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6461 else if (notifier
) {
6462 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6465 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6467 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6468 context
->us
->getName(),
6469 getIOMessageString(msgType
),
6470 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6473 msgArg
.notifyRef
= msgRef
;
6474 msgArg
.maxWaitForReply
= 0;
6476 if (context
->enableTracing
&& (notifier
!= 0))
6478 getPMRootDomain()->traceDetail(notifier
, true);
6481 clock_get_uptime(&start
);
6482 retCode
= context
->us
->messageClient(
6483 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6484 clock_get_uptime(&end
);
6485 if (context
->enableTracing
&& (notifier
!= NULL
))
6487 getPMRootDomain()->traceDetail(notifier
, false);
6490 if ( kIOReturnSuccess
== retCode
)
6492 if ( 0 == msgArg
.maxWaitForReply
)
6494 // client doesn't want time to respond
6495 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6496 context
->responseArray
->setObject(msgIndex
, replied
);
6500 replied
= kOSBooleanFalse
;
6501 if ( msgArg
.maxWaitForReply
> context
->maxTimeRequested
)
6503 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
)
6505 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
6506 PM_ERROR("%s: client %p returned %u for %s\n",
6507 context
->us
->getName(),
6508 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6509 msgArg
.maxWaitForReply
,
6510 getIOMessageString(msgType
));
6513 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6516 // Track time taken to ack, by storing the timestamp of
6517 // callback completion
6519 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6521 context
->responseArray
->setObject(msgIndex
, num
);
6525 context
->responseArray
->setObject(msgIndex
, replied
);
6529 if (context
->enableTracing
) {
6530 SUB_ABSOLUTETIME(&end
, &start
);
6531 absolutetime_to_nanoseconds(end
, &nsec
);
6533 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (msgArg
.maxWaitForReply
!= 0)) {
6534 getPMRootDomain()->traceAckDelay(notifier
, msgArg
.maxWaitForReply
/1000, NS_TO_MS(nsec
));
6540 // not a client of ours
6541 // so we won't be waiting for response
6542 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6543 context
->responseArray
->setObject(msgIndex
, replied
);
6545 if (context
->notifyClients
) {
6546 context
->notifyClients
->setObject(msgIndex
, object
);
6551 //*********************************************************************************
6552 // [public] tellNoChangeDown
6554 // Notify registered applications and kernel clients that we are not
6557 // Subclass can override this to send a different message type. Parameter is
6558 // the aborted destination state number.
6559 //*********************************************************************************
6561 void IOService::tellNoChangeDown( unsigned long )
6563 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6566 //*********************************************************************************
6567 // [public] tellChangeUp
6569 // Notify registered applications and kernel clients that we are raising power.
6571 // Subclass can override this to send a different message type. Parameter is
6572 // the aborted destination state number.
6573 //*********************************************************************************
6575 void IOService::tellChangeUp( unsigned long )
6577 return tellClients( kIOMessageDeviceHasPoweredOn
);
6580 //*********************************************************************************
6581 // [protected] tellClients
6583 // Notify registered applications and kernel clients of something.
6584 //*********************************************************************************
6586 void IOService::tellClients( int messageType
)
6588 IOPMInterestContext context
;
6590 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6592 memset(&context
, 0, sizeof(context
));
6593 context
.messageType
= messageType
;
6594 context
.isPreChange
= fIsPreChange
;
6596 context
.stateNumber
= fHeadNotePowerState
;
6597 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6598 context
.changeFlags
= fHeadNoteChangeFlags
;
6599 context
.enableTracing
= IS_ROOT_DOMAIN
;
6600 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6601 OSMemberFunctionCast(
6604 &IOPMrootDomain::systemMessageFilter
) : 0;
6606 context
.notifyType
= kNotifyPriority
;
6607 applyToInterested( gIOPriorityPowerStateInterest
,
6608 tellKernelClientApplier
, (void *) &context
);
6610 context
.notifyType
= kNotifyApps
;
6611 applyToInterested( gIOAppPowerStateInterest
,
6612 tellAppClientApplier
, (void *) &context
);
6614 applyToInterested( gIOGeneralInterest
,
6615 tellKernelClientApplier
, (void *) &context
);
6618 //*********************************************************************************
6619 // [private] tellKernelClientApplier
6621 // Message a kernel client.
6622 //*********************************************************************************
6624 static void tellKernelClientApplier( OSObject
* object
, void * arg
)
6626 IOPowerStateChangeNotification notify
;
6627 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6629 if (context
->messageFilter
&&
6630 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6632 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6633 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6635 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6636 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6637 context
->us
->getName(),
6638 IOService::getIOMessageString(context
->messageType
),
6639 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6644 notify
.powerRef
= (void *) 0;
6645 notify
.returnValue
= 0;
6646 notify
.stateNumber
= context
->stateNumber
;
6647 notify
.stateFlags
= context
->stateFlags
;
6649 if (context
->enableTracing
&& object
)
6651 IOService::getPMRootDomain()->traceDetail(object
, true);
6653 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6654 if (context
->enableTracing
&& object
)
6656 IOService::getPMRootDomain()->traceDetail(object
, false);
6661 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6662 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6664 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6665 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6666 context
->us
->getName(),
6667 IOService::getIOMessageString(context
->messageType
),
6668 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6672 static OSNumber
* copyClientIDForNotification(
6674 IOPMInterestContext
*context
)
6676 OSNumber
*clientID
= NULL
;
6677 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6681 static void logClientIDForNotification(
6683 IOPMInterestContext
*context
,
6684 const char *logString
)
6686 OSString
*logClientID
= NULL
;
6687 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6692 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6694 PM_LOG("%s %s %s, %s\n",
6695 context
->us
->getName(), logString
,
6696 IOService::getIOMessageString(context
->messageType
),
6697 logClientID
? logClientID
->getCStringNoCopy() : "");
6700 logClientID
->release();
6704 clientID
->release();
6709 static void tellAppClientApplier( OSObject
* object
, void * arg
)
6711 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6712 OSNumber
* clientID
= NULL
;
6714 boolean_t proc_suspended
= FALSE
;
6716 if (context
->us
== IOService::getPMRootDomain())
6718 if ((clientID
= copyClientIDForNotification(object
, context
)))
6720 uint32_t clientPID
= clientID
->unsigned32BitValue();
6721 clientID
->release();
6722 proc
= proc_find(clientPID
);
6726 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6731 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6738 if (context
->messageFilter
&&
6739 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6741 if (kIOLogDebugPower
& gIOKitDebug
)
6743 logClientIDForNotification(object
, context
, "DROP App");
6748 if (kIOLogDebugPower
& gIOKitDebug
)
6750 logClientIDForNotification(object
, context
, "MESG App");
6753 context
->us
->messageClient(context
->messageType
, object
, 0);
6756 //*********************************************************************************
6757 // [private] checkForDone
6758 //*********************************************************************************
6760 bool IOService::checkForDone( void )
6765 if (fResponseArray
== NULL
) {
6769 for (i
= 0; ; i
++) {
6770 theFlag
= fResponseArray
->getObject(i
);
6772 if (NULL
== theFlag
) {
6776 if (kOSBooleanTrue
!= theFlag
) {
6783 //*********************************************************************************
6784 // [public] responseValid
6785 //*********************************************************************************
6787 bool IOService::responseValid( uint32_t refcon
, int pid
)
6789 UInt16 serialComponent
;
6790 UInt16 ordinalComponent
;
6792 OSObject
*object
= 0;
6794 serialComponent
= (refcon
>> 16) & 0xFFFF;
6795 ordinalComponent
= (refcon
& 0xFFFF);
6797 if ( serialComponent
!= fSerialNumber
)
6802 if ( fResponseArray
== NULL
)
6807 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6814 if (fNotifyClientArray
)
6815 object
= fNotifyClientArray
->getObject(ordinalComponent
);
6818 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
6826 clock_get_uptime(&now
);
6827 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6828 SUB_ABSOLUTETIME(&now
, &start
);
6829 absolutetime_to_nanoseconds(now
, &nsec
);
6833 proc_name(pid
, name
, sizeof(name
));
6835 if (nsec
> LOG_APP_RESPONSE_TIMES
)
6837 IOLog("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec
),
6842 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
6844 // TODO: populate the messageType argument
6845 getPMRootDomain()->pmStatsRecordApplicationResponse(
6846 gIOPMStatsResponseSlow
,
6847 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6851 getPMRootDomain()->pmStatsRecordApplicationResponse(
6852 gIOPMStatsResponsePrompt
,
6853 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6857 getPMRootDomain()->traceAckDelay(object
, 0, NS_TO_MS(nsec
));
6860 if (kIOLogDebugPower
& gIOKitDebug
)
6862 PM_LOG("Ack(%u) %u ms\n",
6863 (uint32_t) ordinalComponent
,
6866 theFlag
= kOSBooleanFalse
;
6869 getPMRootDomain()->pmStatsRecordApplicationResponse(
6870 gIOPMStatsResponsePrompt
,
6871 0, 0, 0, pid
, object
);
6875 if ( kOSBooleanFalse
== theFlag
)
6877 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6883 //*********************************************************************************
6884 // [public] allowPowerChange
6886 // Our power state is about to lower, and we have notified applications
6887 // and kernel clients, and one of them has acknowledged. If this is the last to do
6888 // so, and all acknowledgements are positive, we continue with the power change.
6889 //*********************************************************************************
6891 IOReturn
IOService::allowPowerChange( unsigned long refcon
)
6893 IOPMRequest
* request
;
6898 return kIOReturnSuccess
;
6901 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6903 return kIOReturnNoMemory
;
6905 request
->fArg0
= (void *) refcon
;
6906 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6907 request
->fArg2
= (void *) 0;
6908 submitPMRequest( request
);
6910 return kIOReturnSuccess
;
6914 IOReturn
IOService::serializedAllowPowerChange2( unsigned long refcon
)
6916 // [deprecated] public
6917 return kIOReturnUnsupported
;
6919 #endif /* !__LP64__ */
6921 //*********************************************************************************
6922 // [public] cancelPowerChange
6924 // Our power state is about to lower, and we have notified applications
6925 // and kernel clients, and one of them has vetoed the change. If this is the last
6926 // client to respond, we abandon the power change.
6927 //*********************************************************************************
6929 IOReturn
IOService::cancelPowerChange( unsigned long refcon
)
6931 IOPMRequest
* request
;
6933 pid_t pid
= proc_selfpid();
6938 return kIOReturnSuccess
;
6942 proc_name(pid
, name
, sizeof(name
));
6943 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid
, name
);
6945 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6948 return kIOReturnNoMemory
;
6951 request
->fArg0
= (void *) refcon
;
6952 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6953 request
->fArg2
= (void *) OSString::withCString(name
);
6954 submitPMRequest( request
);
6956 return kIOReturnSuccess
;
6960 IOReturn
IOService::serializedCancelPowerChange2( unsigned long refcon
)
6962 // [deprecated] public
6963 return kIOReturnUnsupported
;
6966 //*********************************************************************************
6967 // PM_Clamp_Timer_Expired
6969 // called when clamp timer expires...set power state to 0.
6970 //*********************************************************************************
6972 void IOService::PM_Clamp_Timer_Expired( void )
6976 //*********************************************************************************
6979 // Set to highest available power state for a minimum of duration milliseconds
6980 //*********************************************************************************
6982 void IOService::clampPowerOn( unsigned long duration
)
6985 #endif /* !__LP64__ */
6987 //*********************************************************************************
6988 // configurePowerStateReport
6990 // Configures the IOStateReport for kPMPowerStateChannel
6991 //*********************************************************************************
6992 IOReturn
IOService::configurePowerStatesReport( IOReportConfigureAction action
, void *result
)
6995 IOReturn rc
= kIOReturnSuccess
;
7001 return kIOReturnUnsupported
;
7003 if (!fNumberOfPowerStates
)
7004 return kIOReturnSuccess
; // For drivers which are in power plane, but haven't called registerPowerDriver()
7009 case kIOReportEnable
:
7015 reportSize
= STATEREPORT_BUFSIZE(fNumberOfPowerStates
);
7016 fReportBuf
= IOMalloc(reportSize
);
7018 rc
= kIOReturnNoMemory
;
7021 memset(fReportBuf
, 0, reportSize
);
7023 STATEREPORT_INIT(fNumberOfPowerStates
, fReportBuf
, reportSize
,
7024 getRegistryEntryID(), kPMPowerStatesChID
, kIOReportCategoryPower
);
7026 for (i
= 0; i
< fNumberOfPowerStates
; i
++) {
7029 if (fPowerStates
[i
].capabilityFlags
& kIOPMPowerOn
)
7030 bits
|= kPMReportPowerOn
;
7031 if (fPowerStates
[i
].capabilityFlags
& kIOPMDeviceUsable
)
7032 bits
|= kPMReportDeviceUsable
;
7033 if (fPowerStates
[i
].capabilityFlags
& kIOPMLowPower
)
7034 bits
|= kPMReportLowPower
;
7036 STATEREPORT_SETSTATEID(fReportBuf
, i
, ((bits
& 0xff) << 8) |
7037 ((StateOrder(fMaxPowerState
) & 0xf) << 4) | (StateOrder(i
) & 0xf));
7039 ts
= mach_absolute_time();
7040 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
7043 case kIOReportDisable
:
7044 if (fReportClientCnt
== 0) {
7045 rc
= kIOReturnBadArgument
;
7048 if (fReportClientCnt
== 1)
7050 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
7056 case kIOReportGetDimensions
:
7058 STATEREPORT_UPDATERES(fReportBuf
, kIOReportGetDimensions
, result
);
7067 //*********************************************************************************
7068 // updatePowerStateReport
7070 // Updates the IOStateReport for kPMPowerStateChannel
7071 //*********************************************************************************
7072 IOReturn
IOService::updatePowerStatesReport( IOReportConfigureAction action
, void *result
, void *destination
)
7077 IOReturn rc
= kIOReturnSuccess
;
7078 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
7082 return kIOReturnUnsupported
;
7083 if (!fNumberOfPowerStates
)
7084 return kIOReturnSuccess
;
7086 if ( !result
|| !dest
) return kIOReturnBadArgument
;
7090 case kIOReportCopyChannelData
:
7091 if ( !fReportBuf
) {
7092 rc
= kIOReturnNotOpen
;
7096 ts
= mach_absolute_time();
7097 STATEREPORT_UPDATEPREP(fReportBuf
, ts
, data2cpy
, size2cpy
);
7098 if (size2cpy
> (dest
->getCapacity() - dest
->getLength()) ) {
7099 rc
= kIOReturnOverrun
;
7103 STATEREPORT_UPDATERES(fReportBuf
, kIOReportCopyChannelData
, result
);
7104 dest
->appendBytes(data2cpy
, size2cpy
);
7118 //*********************************************************************************
7119 // configureSimplePowerReport
7121 // Configures the IOSimpleReport for given channel id
7122 //*********************************************************************************
7123 IOReturn
IOService::configureSimplePowerReport(IOReportConfigureAction action
, void *result
)
7126 IOReturn rc
= kIOReturnSuccess
;
7129 return kIOReturnUnsupported
;
7131 if ( !fNumberOfPowerStates
)
7136 case kIOReportEnable
:
7137 case kIOReportDisable
:
7140 case kIOReportGetDimensions
:
7141 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
7149 //*********************************************************************************
7150 // updateSimplePowerReport
7152 // Updates the IOSimpleReport for the given chanel id
7153 //*********************************************************************************
7154 IOReturn
IOService::updateSimplePowerReport( IOReportConfigureAction action
, void *result
, void *destination
)
7158 uint64_t buf
[SIMPLEREPORT_BUFSIZE
/sizeof(uint64_t)+1]; // Force a 8-byte alignment
7159 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
7160 IOReturn rc
= kIOReturnSuccess
;
7165 return kIOReturnUnsupported
;
7166 if ( !result
|| !dest
) return kIOReturnBadArgument
;
7168 if ( !fNumberOfPowerStates
)
7173 case kIOReportCopyChannelData
:
7175 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), kPMCurrStateChID
, kIOReportCategoryPower
);
7177 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMPowerOn
)
7178 bits
|= kPMReportPowerOn
;
7179 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMDeviceUsable
)
7180 bits
|= kPMReportDeviceUsable
;
7181 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMLowPower
)
7182 bits
|= kPMReportLowPower
;
7185 SIMPLEREPORT_SETVALUE(buf
, ((bits
& 0xff) << 8) | ((StateOrder(fMaxPowerState
) & 0xf) << 4) |
7186 (StateOrder(fCurrentPowerState
) & 0xf));
7188 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
7189 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
7190 rc
= kIOReturnOverrun
;
7194 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
7195 dest
->appendBytes(data2cpy
, size2cpy
);
7205 return kIOReturnSuccess
;
7212 // MARK: Driver Overrides
7214 //*********************************************************************************
7215 // [public] setPowerState
7217 // Does nothing here. This should be implemented in a subclass driver.
7218 //*********************************************************************************
7220 IOReturn
IOService::setPowerState(
7221 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
7226 //*********************************************************************************
7227 // [public] maxCapabilityForDomainState
7229 // Finds the highest power state in the array whose input power requirement
7230 // is equal to the input parameter. Where a more intelligent decision is
7231 // possible, override this in the subclassed driver.
7232 //*********************************************************************************
7234 IOPMPowerStateIndex
IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags
)
7236 IOPMPowerStateIndex stateIndex
;
7238 if (!fNumberOfPowerStates
)
7239 return kPowerStateZero
;
7241 for ( int order
= fNumberOfPowerStates
- 1; order
>= 0; order
-- )
7243 stateIndex
= fPowerStates
[order
].stateOrderToIndex
;
7245 if ( (flags
& fPowerStates
[stateIndex
].inputPowerFlags
) ==
7246 fPowerStates
[stateIndex
].inputPowerFlags
)
7251 return kPowerStateZero
;
7254 unsigned long IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState
)
7256 return getPowerStateForDomainFlags(domainState
);
7259 //*********************************************************************************
7260 // [public] initialPowerStateForDomainState
7262 // Called to query the power state for the initial power transition.
7263 //*********************************************************************************
7265 unsigned long IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState
)
7267 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
))
7269 // Return lowest power state for any root power domain changes
7270 return kPowerStateZero
;
7273 return getPowerStateForDomainFlags(domainState
);
7276 //*********************************************************************************
7277 // [public] powerStateForDomainState
7279 // This method is not called from PM.
7280 //*********************************************************************************
7282 unsigned long IOService::powerStateForDomainState( IOPMPowerFlags domainState
)
7284 return getPowerStateForDomainFlags(domainState
);
7288 //*********************************************************************************
7289 // [deprecated] didYouWakeSystem
7291 // Does nothing here. This should be implemented in a subclass driver.
7292 //*********************************************************************************
7294 bool IOService::didYouWakeSystem( void )
7298 #endif /* !__LP64__ */
7300 //*********************************************************************************
7301 // [public] powerStateWillChangeTo
7303 // Does nothing here. This should be implemented in a subclass driver.
7304 //*********************************************************************************
7306 IOReturn
IOService::powerStateWillChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7308 return kIOPMAckImplied
;
7311 //*********************************************************************************
7312 // [public] powerStateDidChangeTo
7314 // Does nothing here. This should be implemented in a subclass driver.
7315 //*********************************************************************************
7317 IOReturn
IOService::powerStateDidChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7319 return kIOPMAckImplied
;
7322 //*********************************************************************************
7323 // [protected] powerChangeDone
7325 // Called from PM work loop thread.
7326 // Does nothing here. This should be implemented in a subclass policy-maker.
7327 //*********************************************************************************
7329 void IOService::powerChangeDone( unsigned long )
7334 //*********************************************************************************
7335 // [deprecated] newTemperature
7337 // Does nothing here. This should be implemented in a subclass driver.
7338 //*********************************************************************************
7340 IOReturn
IOService::newTemperature( long currentTemp
, IOService
* whichZone
)
7344 #endif /* !__LP64__ */
7346 //*********************************************************************************
7347 // [public] systemWillShutdown
7349 // System shutdown and restart notification.
7350 //*********************************************************************************
7352 void IOService::systemWillShutdown( IOOptionBits specifier
)
7354 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
7356 rootDomain
->acknowledgeSystemWillShutdown( this );
7360 // MARK: PM State Machine
7362 //*********************************************************************************
7363 // [private static] acquirePMRequest
7364 //*********************************************************************************
7367 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
7368 IOPMRequest
* active
)
7370 IOPMRequest
* request
;
7374 request
= IOPMRequest::create();
7377 request
->init( target
, requestType
);
7380 IOPMRequest
* root
= active
->getRootRequest();
7381 if (root
) request
->attachRootRequest(root
);
7386 PM_ERROR("%s: No memory for PM request type 0x%x\n",
7387 target
->getName(), (uint32_t) requestType
);
7392 //*********************************************************************************
7393 // [private static] releasePMRequest
7394 //*********************************************************************************
7396 void IOService::releasePMRequest( IOPMRequest
* request
)
7405 //*********************************************************************************
7406 // [private static] submitPMRequest
7407 //*********************************************************************************
7409 void IOService::submitPMRequest( IOPMRequest
* request
)
7412 assert( gIOPMReplyQueue
);
7413 assert( gIOPMRequestQueue
);
7415 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7416 (long)request
->getType(), OBFUSCATE(request
),
7417 OBFUSCATE(request
->getTarget()), request
->getTarget()->getName(),
7418 OBFUSCATE(request
->fArg0
),
7419 OBFUSCATE(request
->fArg1
), OBFUSCATE(request
->fArg2
));
7421 if (request
->isReplyType())
7422 gIOPMReplyQueue
->queuePMRequest( request
);
7424 gIOPMRequestQueue
->queuePMRequest( request
);
7427 void IOService::submitPMRequests( IOPMRequest
** requests
, IOItemCount count
)
7430 assert( count
> 0 );
7431 assert( gIOPMRequestQueue
);
7433 for (IOItemCount i
= 0; i
< count
; i
++)
7435 IOPMRequest
* req
= requests
[i
];
7436 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7437 (long)req
->getType(), OBFUSCATE(req
),
7438 OBFUSCATE(req
->getTarget()), req
->getTarget()->getName(),
7439 OBFUSCATE(req
->fArg0
),
7440 OBFUSCATE(req
->fArg1
), OBFUSCATE(req
->fArg2
));
7443 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
7446 //*********************************************************************************
7447 // [private] actionPMRequestQueue
7449 // IOPMRequestQueue::checkForWork() passing a new request to the request target.
7450 //*********************************************************************************
7452 bool IOService::actionPMRequestQueue(
7453 IOPMRequest
* request
,
7454 IOPMRequestQueue
* queue
)
7460 // Work queue will immediately execute the request if the per-service
7461 // request queue is empty. Note pwrMgt is the target's IOServicePM.
7463 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
7467 // Calling PM without PMinit() is not allowed, fail the request.
7468 // Need to signal more when completing attached requests.
7470 PM_LOG("%s: PM not initialized\n", getName());
7471 PM_LOG1("[- %02x] %p [%p %s] !initialized\n",
7472 request
->getType(), OBFUSCATE(request
),
7473 OBFUSCATE(this), getName());
7475 more
= gIOPMCompletionQueue
->queuePMRequest(request
);
7476 if (more
) gIOPMWorkQueue
->incrementProducerCount();
7482 //*********************************************************************************
7483 // [private] actionPMCompletionQueue
7485 // IOPMCompletionQueue::checkForWork() passing a completed request to the
7487 //*********************************************************************************
7489 bool IOService::actionPMCompletionQueue(
7490 IOPMRequest
* request
,
7491 IOPMCompletionQueue
* queue
)
7493 bool more
= (request
->getNextRequest() != 0);
7494 IOPMRequest
* root
= request
->getRootRequest();
7496 if (root
&& (root
!= request
))
7499 gIOPMWorkQueue
->incrementProducerCount();
7501 releasePMRequest( request
);
7505 //*********************************************************************************
7506 // [private] actionPMWorkQueueRetire
7508 // IOPMWorkQueue::checkForWork() passing a retired request to the request target.
7509 //*********************************************************************************
7511 bool IOService::actionPMWorkQueueRetire( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7513 assert(request
&& queue
);
7515 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7516 request
->getType(), OBFUSCATE(request
),
7517 OBFUSCATE(this), getName(),
7518 fMachineState
, gIOPMBusyRequestCount
);
7520 // Catch requests created by idleTimerExpired()
7521 if (request
->getType() == kIOPMRequestTypeActivityTickle
)
7523 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
7525 if ((tickleFlags
& kTickleTypePowerDrop
) && fIdleTimerPeriod
)
7529 else if (tickleFlags
== (kTickleTypeActivity
| kTickleTypePowerRise
))
7531 // Invalidate any idle power drop that got queued while
7532 // processing this request.
7533 fIdleTimerGeneration
++;
7537 // When the completed request is linked, tell work queue there is
7538 // more work pending.
7540 return (gIOPMCompletionQueue
->queuePMRequest( request
));
7543 //*********************************************************************************
7544 // [private] isPMBlocked
7546 // Check if machine state transition is blocked.
7547 //*********************************************************************************
7549 bool IOService::isPMBlocked( IOPMRequest
* request
, int count
)
7554 if (kIOPM_Finished
== fMachineState
)
7557 if (kIOPM_DriverThreadCallDone
== fMachineState
)
7559 // 5 = kDriverCallInformPreChange
7560 // 6 = kDriverCallInformPostChange
7561 // 7 = kDriverCallSetPowerState
7562 // 8 = kRootDomainInformPreChange
7563 if (fDriverCallBusy
)
7564 reason
= 5 + fDriverCallReason
;
7568 // Waiting on driver's setPowerState() timeout.
7574 // Child or interested driver acks pending.
7575 if (fHeadNotePendingAcks
)
7580 // Waiting on apps or priority power interest clients.
7586 // Waiting on settle timer expiration.
7593 fWaitReason
= reason
;
7599 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7600 request
->getType(), OBFUSCATE(request
),
7601 OBFUSCATE(this), getName(),
7602 fMachineState
, reason
);
7611 //*********************************************************************************
7612 // [private] actionPMWorkQueueInvoke
7614 // IOPMWorkQueue::checkForWork() passing a request to the
7615 // request target for execution.
7616 //*********************************************************************************
7618 bool IOService::actionPMWorkQueueInvoke( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7623 assert(request
&& queue
);
7625 while (isPMBlocked(request
, loop
++) == false)
7627 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7628 request
->getType(), OBFUSCATE(request
),
7629 OBFUSCATE(this), getName(), fMachineState
);
7631 gIOPMRequest
= request
;
7632 gIOPMWorkInvokeCount
++;
7634 // Every PM machine states must be handled in one of the cases below.
7636 switch ( fMachineState
)
7638 case kIOPM_Finished
:
7639 start_watchdog_timer();
7641 executePMRequest( request
);
7644 case kIOPM_OurChangeTellClientsPowerDown
:
7645 // Root domain might self cancel due to assertions.
7648 bool cancel
= (bool) fDoNotPowerDown
;
7649 getPMRootDomain()->askChangeDownDone(
7650 &fHeadNoteChangeFlags
, &cancel
);
7651 fDoNotPowerDown
= cancel
;
7654 // askChangeDown() done, was it vetoed?
7655 if (!fDoNotPowerDown
)
7657 // no, we can continue
7658 OurChangeTellClientsPowerDown();
7662 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7663 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7664 if (IS_ROOT_DOMAIN
) {
7665 // RootDomain already sent "WillSleep" to its clients
7666 tellChangeUp(fCurrentPowerState
);
7669 tellNoChangeDown(fHeadNotePowerState
);
7671 // mark the change note un-actioned
7672 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7678 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
7679 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7680 if (fDoNotPowerDown
)
7682 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7683 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7684 if (IS_ROOT_DOMAIN
) {
7685 // RootDomain already sent "WillSleep" to its clients
7686 tellChangeUp(fCurrentPowerState
);
7689 tellNoChangeDown(fHeadNotePowerState
);
7691 // mark the change note un-actioned
7692 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7697 OurChangeTellUserPMPolicyPowerDown();
7700 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
7701 // PMRD: LastCallBeforeSleep notify done
7702 // Non-PMRD: tellChangeDown/kNotifyApps done
7703 if (fDoNotPowerDown
)
7705 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7706 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7707 // no, tell clients we're back in the old state
7708 tellChangeUp(fCurrentPowerState
);
7709 // mark the change note un-actioned
7710 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7716 // yes, we can continue
7717 OurChangeTellPriorityClientsPowerDown();
7721 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
7722 OurChangeNotifyInterestedDriversWillChange();
7725 case kIOPM_OurChangeSetPowerState
:
7726 OurChangeSetPowerState();
7729 case kIOPM_OurChangeWaitForPowerSettle
:
7730 OurChangeWaitForPowerSettle();
7733 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
7734 OurChangeNotifyInterestedDriversDidChange();
7737 case kIOPM_OurChangeTellCapabilityDidChange
:
7738 OurChangeTellCapabilityDidChange();
7741 case kIOPM_OurChangeFinish
:
7745 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
7746 ParentChangeTellPriorityClientsPowerDown();
7749 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
7750 ParentChangeNotifyInterestedDriversWillChange();
7753 case kIOPM_ParentChangeSetPowerState
:
7754 ParentChangeSetPowerState();
7757 case kIOPM_ParentChangeWaitForPowerSettle
:
7758 ParentChangeWaitForPowerSettle();
7761 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7762 ParentChangeNotifyInterestedDriversDidChange();
7765 case kIOPM_ParentChangeTellCapabilityDidChange
:
7766 ParentChangeTellCapabilityDidChange();
7769 case kIOPM_ParentChangeAcknowledgePowerChange
:
7770 ParentChangeAcknowledgePowerChange();
7773 case kIOPM_DriverThreadCallDone
:
7774 switch (fDriverCallReason
)
7776 case kDriverCallInformPreChange
:
7777 case kDriverCallInformPostChange
:
7778 notifyInterestedDriversDone();
7780 case kDriverCallSetPowerState
:
7781 notifyControllingDriverDone();
7783 case kRootDomainInformPreChange
:
7784 notifyRootDomainDone();
7787 panic("%s: bad call reason %x",
7788 getName(), fDriverCallReason
);
7792 case kIOPM_NotifyChildrenOrdered
:
7793 notifyChildrenOrdered();
7796 case kIOPM_NotifyChildrenDelayed
:
7797 notifyChildrenDelayed();
7800 case kIOPM_NotifyChildrenStart
:
7801 // pop notifyAll() state saved by notifyInterestedDriversDone()
7806 case kIOPM_SyncTellClientsPowerDown
:
7807 // Root domain might self cancel due to assertions.
7810 bool cancel
= (bool) fDoNotPowerDown
;
7811 getPMRootDomain()->askChangeDownDone(
7812 &fHeadNoteChangeFlags
, &cancel
);
7813 fDoNotPowerDown
= cancel
;
7815 if (!fDoNotPowerDown
)
7817 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7818 fOutOfBandParameter
= kNotifyApps
;
7819 tellChangeDown(fHeadNotePowerState
);
7823 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7824 // askChangeDown/kNotifyApps
7825 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7826 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7827 tellNoChangeDown(fHeadNotePowerState
);
7828 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7833 case kIOPM_SyncTellPriorityClientsPowerDown
:
7834 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7835 if (!fDoNotPowerDown
)
7837 fMachineState
= kIOPM_SyncNotifyWillChange
;
7838 fOutOfBandParameter
= kNotifyPriority
;
7839 tellChangeDown(fHeadNotePowerState
);
7843 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7844 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7845 tellChangeUp(fCurrentPowerState
);
7846 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7851 case kIOPM_SyncNotifyWillChange
:
7852 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
)
7854 fMachineState
= kIOPM_SyncFinish
;
7857 fMachineState
= kIOPM_SyncNotifyDidChange
;
7858 fDriverCallReason
= kDriverCallInformPreChange
;
7862 case kIOPM_SyncNotifyDidChange
:
7863 fIsPreChange
= false;
7865 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7867 fMachineState
= kIOPM_SyncFinish
;
7871 assert(IS_ROOT_DOMAIN
);
7872 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7875 fDriverCallReason
= kDriverCallInformPostChange
;
7879 case kIOPM_SyncTellCapabilityDidChange
:
7880 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7883 case kIOPM_SyncFinish
:
7884 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7885 ParentChangeAcknowledgePowerChange();
7890 case kIOPM_TellCapabilityChangeDone
:
7893 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
)
7895 MS_POP(); // tellSystemCapabilityChange()
7898 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7902 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
)
7904 MS_POP(); // tellSystemCapabilityChange()
7907 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7909 tellClientsWithResponse( fOutOfBandMessage
);
7913 panic("PMWorkQueueInvoke: unknown machine state %x",
7919 if (fMachineState
== kIOPM_Finished
)
7921 stop_watchdog_timer();
7930 //*********************************************************************************
7931 // [private] executePMRequest
7932 //*********************************************************************************
7934 void IOService::executePMRequest( IOPMRequest
* request
)
7936 assert( kIOPM_Finished
== fMachineState
);
7938 switch (request
->getType())
7940 case kIOPMRequestTypePMStop
:
7941 handlePMstop( request
);
7944 case kIOPMRequestTypeAddPowerChild1
:
7945 addPowerChild1( request
);
7948 case kIOPMRequestTypeAddPowerChild2
:
7949 addPowerChild2( request
);
7952 case kIOPMRequestTypeAddPowerChild3
:
7953 addPowerChild3( request
);
7956 case kIOPMRequestTypeRegisterPowerDriver
:
7957 handleRegisterPowerDriver( request
);
7960 case kIOPMRequestTypeAdjustPowerState
:
7961 fAdjustPowerScheduled
= false;
7965 case kIOPMRequestTypePowerDomainWillChange
:
7966 handlePowerDomainWillChangeTo( request
);
7969 case kIOPMRequestTypePowerDomainDidChange
:
7970 handlePowerDomainDidChangeTo( request
);
7973 case kIOPMRequestTypeRequestPowerState
:
7974 case kIOPMRequestTypeRequestPowerStateOverride
:
7975 handleRequestPowerState( request
);
7978 case kIOPMRequestTypePowerOverrideOnPriv
:
7979 case kIOPMRequestTypePowerOverrideOffPriv
:
7980 handlePowerOverrideChanged( request
);
7983 case kIOPMRequestTypeActivityTickle
:
7984 handleActivityTickle( request
);
7987 case kIOPMRequestTypeSynchronizePowerTree
:
7988 handleSynchronizePowerTree( request
);
7991 case kIOPMRequestTypeSetIdleTimerPeriod
:
7993 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7994 fNextIdleTimerPeriod
= fIdleTimerPeriod
;
7995 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
8000 case kIOPMRequestTypeIgnoreIdleTimer
:
8001 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
8004 case kIOPMRequestTypeQuiescePowerTree
:
8005 gIOPMWorkQueue
->finishQuiesceRequest(request
);
8009 panic("executePMRequest: unknown request type %x", request
->getType());
8013 //*********************************************************************************
8014 // [private] actionPMReplyQueue
8016 // IOPMRequestQueue::checkForWork() passing a reply-type request to the
8018 //*********************************************************************************
8020 bool IOService::actionPMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
8024 assert( request
&& queue
);
8025 assert( request
->isReplyType() );
8027 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
8028 request
->getType(), OBFUSCATE(request
),
8029 OBFUSCATE(this), getName(), fMachineState
);
8031 switch ( request
->getType() )
8033 case kIOPMRequestTypeAllowPowerChange
:
8034 case kIOPMRequestTypeCancelPowerChange
:
8035 // Check if we are expecting this response.
8036 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
8037 (int)(uintptr_t) request
->fArg1
))
8039 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
8041 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
8042 // flag is set. Only root domain will set this flag.
8043 // However, there is one exception to this rule. User-space PM
8044 // policy may choose to cancel sleep even after all clients have
8045 // been notified that we will lower power.
8047 if ((fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
8048 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
8049 || ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0))
8051 fDoNotPowerDown
= true;
8053 OSString
* name
= (OSString
*) request
->fArg2
;
8054 getPMRootDomain()->pmStatsRecordApplicationResponse(
8055 gIOPMStatsResponseCancel
,
8056 name
? name
->getCStringNoCopy() : "", 0,
8057 0, (int)(uintptr_t) request
->fArg1
, 0);
8064 cleanClientResponses(false);
8068 // OSString containing app name in Arg2 must be released.
8069 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
8071 OSObject
* obj
= (OSObject
*) request
->fArg2
;
8072 if (obj
) obj
->release();
8076 case kIOPMRequestTypeAckPowerChange
:
8077 more
= handleAcknowledgePowerChange( request
);
8080 case kIOPMRequestTypeAckSetPowerState
:
8081 if (fDriverTimer
== -1)
8083 // driver acked while setPowerState() call is in-flight.
8084 // take this ack, return value from setPowerState() is irrelevant.
8085 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
8086 (uintptr_t) this, fDriverTimer
);
8089 else if (fDriverTimer
> 0)
8091 // expected ack, stop the timer
8094 getPMRootDomain()->reset_watchdog_timer(this, 0);
8096 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
8097 if (nsec
> LOG_SETPOWER_TIMES
) {
8098 getPMRootDomain()->pmStatsRecordApplicationResponse(
8099 gIOPMStatsDriverPSChangeSlow
,
8100 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
8101 NULL
, fHeadNotePowerState
);
8104 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
8111 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
8115 case kIOPMRequestTypeInterestChanged
:
8116 handleInterestChanged( request
);
8120 case kIOPMRequestTypeIdleCancel
:
8121 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
8122 || (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
8123 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
8124 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
8125 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
8127 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
8128 PM_LOG2("%s: cancel from machine state %d\n",
8129 getName(), fMachineState
);
8130 fDoNotPowerDown
= true;
8131 // Stop waiting for app replys.
8132 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
8133 (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
) ||
8134 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
) ||
8135 (fMachineState
== kIOPM_SyncTellClientsPowerDown
) )
8136 cleanClientResponses(false);
8141 case kIOPMRequestTypeChildNotifyDelayCancel
:
8142 if (fMachineState
== kIOPM_NotifyChildrenDelayed
)
8144 PM_LOG2("%s: delay notify cancelled\n", getName());
8145 notifyChildrenDelayed();
8150 panic("PMReplyQueue: unknown reply type %x", request
->getType());
8153 more
|= gIOPMCompletionQueue
->queuePMRequest(request
);
8155 gIOPMWorkQueue
->incrementProducerCount();
8160 //*********************************************************************************
8161 // [private] assertPMDriverCall / deassertPMDriverCall
8162 //*********************************************************************************
8164 bool IOService::assertPMDriverCall(
8165 IOPMDriverCallEntry
* entry
,
8166 IOOptionBits options
,
8167 IOPMinformee
* inform
)
8169 IOService
* target
= 0;
8177 if (fLockedFlags
.PMStop
)
8182 if (((options
& kIOPMADC_NoInactiveCheck
) == 0) && isInactive())
8189 if (!inform
->active
)
8193 target
= inform
->whatObject
;
8194 if (target
->isInactive())
8200 entry
->thread
= current_thread();
8201 entry
->target
= target
;
8202 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8211 void IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
8213 bool wakeup
= false;
8217 assert( !queue_empty(&fPMDriverCallQueue
) );
8218 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8219 if (fLockedFlags
.PMDriverCallWait
)
8227 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
8230 bool IOService::getBlockingDriverCall(thread_t
*thread
, const void **callMethod
)
8232 const IOPMDriverCallEntry
* entry
= NULL
;
8233 bool blocked
= false;
8239 if (current_thread() != gIOPMWatchDogThread
) {
8240 // Meant to be accessed only from watchdog thread
8245 entry
= qe_queue_first(&fPMDriverCallQueue
, IOPMDriverCallEntry
, link
);
8247 *thread
= entry
->thread
;
8248 *callMethod
= entry
->callMethod
;
8257 void IOService::waitForPMDriverCall( IOService
* target
)
8259 const IOPMDriverCallEntry
* entry
;
8260 thread_t thread
= current_thread();
8261 AbsoluteTime deadline
;
8268 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
8270 // Target of interested driver call
8271 if (target
&& (target
!= entry
->target
))
8274 if (entry
->thread
== thread
)
8278 PM_LOG("%s: %s(%s) on PM thread\n",
8279 fName
, __FUNCTION__
, target
? target
->getName() : "");
8280 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
8281 fName
, __FUNCTION__
, target
? target
->getName() : "");
8293 fLockedFlags
.PMDriverCallWait
= true;
8294 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
8295 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
8296 fLockedFlags
.PMDriverCallWait
= false;
8297 if (THREAD_TIMED_OUT
== waitResult
)
8299 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
8306 //*********************************************************************************
8307 // [private] Debug helpers
8308 //*********************************************************************************
8310 const char * IOService::getIOMessageString( uint32_t msg
)
8312 #define MSG_ENTRY(x) {(int) x, #x}
8314 static const IONamedValue msgNames
[] = {
8315 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
8316 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
8317 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
8318 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
8319 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
8320 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
8321 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
8322 MSG_ENTRY( kIOMessageCanSystemSleep
),
8323 MSG_ENTRY( kIOMessageSystemWillSleep
),
8324 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
8325 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
8326 MSG_ENTRY( kIOMessageSystemWillRestart
),
8327 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
8328 MSG_ENTRY( kIOMessageSystemCapabilityChange
),
8329 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep
),
8330 MSG_ENTRY( kIOMessageSystemPagingOff
),
8334 return IOFindNameForValue(msg
, msgNames
);
8339 // MARK: IOPMRequest
8341 //*********************************************************************************
8342 // IOPMRequest Class
8344 // Requests from PM clients, and also used for inter-object messaging within PM.
8345 //*********************************************************************************
8347 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
8349 IOPMRequest
* IOPMRequest::create( void )
8351 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
8352 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
8360 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
8362 if (!IOCommand::init())
8365 fRequestType
= type
;
8371 // Root node and root domain requests does not prevent the power tree from
8372 // becoming quiescent.
8374 fIsQuiesceBlocker
= ((fTarget
!= gIOPMRootNode
) &&
8375 (fTarget
!= IOService::getPMRootDomain()));
8380 void IOPMRequest::reset( void )
8382 assert( fWorkWaitCount
== 0 );
8383 assert( fFreeWaitCount
== 0 );
8385 detachNextRequest();
8386 detachRootRequest();
8388 if (fCompletionAction
&& (fRequestType
== kIOPMRequestTypeQuiescePowerTree
))
8390 // Call the completion on PM work loop context
8391 fCompletionAction(fCompletionTarget
, fCompletionParam
);
8392 fCompletionAction
= 0;
8395 fRequestType
= kIOPMRequestTypeInvalid
;
8404 bool IOPMRequest::attachNextRequest( IOPMRequest
* next
)
8410 // Postpone the execution of the next request after
8412 fRequestNext
= next
;
8413 fRequestNext
->fWorkWaitCount
++;
8414 #if LOG_REQUEST_ATTACH
8415 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8416 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8417 fRequestNext
->fRequestType
,
8418 (uint32_t) fRequestNext
->fWorkWaitCount
,
8419 fTarget
->getName());
8426 bool IOPMRequest::detachNextRequest( void )
8432 assert(fRequestNext
->fWorkWaitCount
);
8433 if (fRequestNext
->fWorkWaitCount
)
8434 fRequestNext
->fWorkWaitCount
--;
8435 #if LOG_REQUEST_ATTACH
8436 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8437 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8438 fRequestNext
->fRequestType
,
8439 (uint32_t) fRequestNext
->fWorkWaitCount
,
8440 fTarget
->getName());
8448 bool IOPMRequest::attachRootRequest( IOPMRequest
* root
)
8454 // Delay the completion of the root request after
8456 fRequestRoot
= root
;
8457 fRequestRoot
->fFreeWaitCount
++;
8458 #if LOG_REQUEST_ATTACH
8459 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8460 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8461 (uint32_t) fRequestRoot
->fType
,
8462 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8463 fTarget
->getName());
8470 bool IOPMRequest::detachRootRequest( void )
8476 assert(fRequestRoot
->fFreeWaitCount
);
8477 if (fRequestRoot
->fFreeWaitCount
)
8478 fRequestRoot
->fFreeWaitCount
--;
8479 #if LOG_REQUEST_ATTACH
8480 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8481 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8482 (uint32_t) fRequestRoot
->fType
,
8483 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8484 fTarget
->getName());
8493 // MARK: IOPMRequestQueue
8495 //*********************************************************************************
8496 // IOPMRequestQueue Class
8498 // Global queues. Queues are created once and never released.
8499 //*********************************************************************************
8501 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
8503 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
8505 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
8506 if (me
&& !me
->init(inOwner
, inAction
))
8514 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
8516 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8519 queue_init(&fQueue
);
8520 fLock
= IOLockAlloc();
8521 return (fLock
!= 0);
8524 void IOPMRequestQueue::free( void )
8531 return IOEventSource::free();
8534 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
8538 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8539 IOLockUnlock(fLock
);
8540 if (workLoop
) signalWorkAvailable();
8544 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
8548 assert(requests
&& count
);
8554 queue_enter(&fQueue
, next
, typeof(next
), fCommandChain
);
8556 IOLockUnlock(fLock
);
8557 if (workLoop
) signalWorkAvailable();
8560 bool IOPMRequestQueue::checkForWork( void )
8562 Action dqAction
= (Action
) action
;
8563 IOPMRequest
* request
;
8565 int dequeueCount
= 0;
8568 IOLockLock( fLock
);
8570 while (!queue_empty(&fQueue
))
8572 if (dequeueCount
++ >= kMaxDequeueCount
)
8574 // Allow other queues a chance to work
8579 queue_remove_first(&fQueue
, request
, typeof(request
), fCommandChain
);
8580 IOLockUnlock(fLock
);
8581 target
= request
->getTarget();
8583 more
|= (*dqAction
)( target
, request
, this );
8584 IOLockLock( fLock
);
8587 IOLockUnlock( fLock
);
8592 // MARK: IOPMWorkQueue
8594 //*********************************************************************************
8595 // IOPMWorkQueue Class
8597 // Queue of IOServicePM objects, each with a queue of IOPMRequest sharing the
8599 //*********************************************************************************
8601 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
8604 IOPMWorkQueue::create( IOService
* inOwner
, Action invoke
, Action retire
)
8606 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
8607 if (me
&& !me
->init(inOwner
, invoke
, retire
))
8615 bool IOPMWorkQueue::init( IOService
* inOwner
, Action invoke
, Action retire
)
8617 if (!invoke
|| !retire
||
8618 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
8621 queue_init(&fWorkQueue
);
8623 fInvokeAction
= invoke
;
8624 fRetireAction
= retire
;
8625 fConsumerCount
= fProducerCount
= 0;
8630 bool IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
8632 queue_head_t
* requestQueue
;
8638 assert( onThread() );
8639 assert( queue_next(&request
->fCommandChain
) ==
8640 queue_prev(&request
->fCommandChain
) );
8642 gIOPMBusyRequestCount
++;
8644 if (request
->isQuiesceType())
8646 if ((request
->getTarget() == gIOPMRootNode
) && !fQuiesceStartTime
)
8648 // Attach new quiesce request to all quiesce blockers in the queue
8649 fQuiesceStartTime
= mach_absolute_time();
8650 attachQuiesceRequest(request
);
8651 fQuiesceRequest
= request
;
8654 else if (fQuiesceRequest
&& request
->isQuiesceBlocker())
8656 // Attach the new quiesce blocker to the blocked quiesce request
8657 request
->attachNextRequest(fQuiesceRequest
);
8660 // Add new request to the tail of the per-service request queue.
8661 // Then immediately check the request queue to minimize latency
8662 // if the queue was empty.
8664 requestQueue
= &pwrMgt
->RequestHead
;
8665 empty
= queue_empty(requestQueue
);
8666 queue_enter(requestQueue
, request
, typeof(request
), fCommandChain
);
8669 more
= checkRequestQueue(requestQueue
, &empty
);
8672 // Request just added is blocked, add its target IOServicePM
8673 // to the work queue.
8674 assert( queue_next(&pwrMgt
->WorkChain
) ==
8675 queue_prev(&pwrMgt
->WorkChain
) );
8677 queue_enter(&fWorkQueue
, pwrMgt
, typeof(pwrMgt
), WorkChain
);
8679 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8680 fQueueLength
, pwrMgt
->Name
, OBFUSCATE(pwrMgt
));
8687 bool IOPMWorkQueue::checkRequestQueue( queue_head_t
* requestQueue
, bool * empty
)
8689 IOPMRequest
* request
;
8694 assert(!queue_empty(requestQueue
));
8696 request
= (typeof(request
)) queue_first(requestQueue
);
8697 if (request
->isWorkBlocked())
8698 break; // request dispatch blocked on attached request
8700 target
= request
->getTarget();
8703 done
= (*fInvokeAction
)( target
, request
, this );
8707 PM_LOG("PM request 0x%x dropped\n", request
->getType());
8711 break; // PM state machine blocked
8713 assert(gIOPMBusyRequestCount
> 0);
8714 if (gIOPMBusyRequestCount
)
8715 gIOPMBusyRequestCount
--;
8717 if (request
== fQuiesceRequest
)
8719 fQuiesceRequest
= 0;
8722 queue_remove_first(requestQueue
, request
, typeof(request
), fCommandChain
);
8723 more
|= (*fRetireAction
)( target
, request
, this );
8724 done
= queue_empty(requestQueue
);
8731 // Retired a request that may unblock a previously visited request
8732 // that is still waiting on the work queue. Must trigger another
8740 bool IOPMWorkQueue::checkForWork( void )
8742 IOServicePM
* entry
;
8747 #if WORK_QUEUE_STATS
8748 fStatCheckForWork
++;
8751 // Iterate over all IOServicePM entries in the work queue,
8752 // and check each entry's request queue.
8754 while (fConsumerCount
!= fProducerCount
)
8756 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8757 fProducerCount
, fConsumerCount
);
8759 fConsumerCount
= fProducerCount
;
8761 #if WORK_QUEUE_STATS
8762 if (queue_empty(&fWorkQueue
))
8768 uint32_t cachedWorkCount
= gIOPMWorkInvokeCount
;
8771 __IGNORE_WCASTALIGN(entry
= (typeof(entry
)) queue_first(&fWorkQueue
));
8772 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
))
8774 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
8776 // Get next entry, points to head if current entry is last.
8777 __IGNORE_WCASTALIGN(next
= (typeof(next
)) queue_next(&entry
->WorkChain
));
8779 // if request queue is empty, remove IOServicePM from work queue.
8782 assert(fQueueLength
);
8783 if (fQueueLength
) fQueueLength
--;
8784 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8785 fQueueLength
, entry
->Name
, OBFUSCATE(entry
));
8786 queue_remove(&fWorkQueue
, entry
, typeof(entry
), WorkChain
);
8791 #if WORK_QUEUE_STATS
8792 if (cachedWorkCount
== gIOPMWorkInvokeCount
)
8800 void IOPMWorkQueue::signalWorkAvailable( void )
8803 IOEventSource::signalWorkAvailable();
8806 void IOPMWorkQueue::incrementProducerCount( void )
8811 void IOPMWorkQueue::attachQuiesceRequest( IOPMRequest
* quiesceRequest
)
8813 IOServicePM
* entry
;
8814 IOPMRequest
* request
;
8816 if (queue_empty(&fWorkQueue
))
8821 queue_iterate(&fWorkQueue
, entry
, typeof(entry
), WorkChain
)
8823 queue_iterate(&entry
->RequestHead
, request
, typeof(request
), fCommandChain
)
8825 // Attach the quiesce request to any request in the queue that
8826 // is not linked to a next request. These requests will block
8827 // the quiesce request.
8829 if (request
->isQuiesceBlocker())
8831 request
->attachNextRequest(quiesceRequest
);
8837 void IOPMWorkQueue::finishQuiesceRequest( IOPMRequest
* quiesceRequest
)
8839 if (fQuiesceRequest
&& (quiesceRequest
== fQuiesceRequest
) &&
8840 (fQuiesceStartTime
!= 0))
8843 fQuiesceFinishTime
= mach_absolute_time();
8848 // MARK: IOPMCompletionQueue
8850 //*********************************************************************************
8851 // IOPMCompletionQueue Class
8852 //*********************************************************************************
8854 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
8856 IOPMCompletionQueue
*
8857 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
8859 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
8860 if (me
&& !me
->init(inOwner
, inAction
))
8868 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
8870 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8873 queue_init(&fQueue
);
8877 bool IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
8882 // unblock dependent request
8883 more
= request
->detachNextRequest();
8884 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8888 bool IOPMCompletionQueue::checkForWork( void )
8890 Action dqAction
= (Action
) action
;
8891 IOPMRequest
* request
;
8896 request
= (typeof(request
)) queue_first(&fQueue
);
8897 while (!queue_end(&fQueue
, (queue_entry_t
) request
))
8899 next
= (typeof(next
)) queue_next(&request
->fCommandChain
);
8900 if (!request
->isFreeBlocked())
8902 queue_remove(&fQueue
, request
, typeof(request
), fCommandChain
);
8903 target
= request
->getTarget();
8905 more
|= (*dqAction
)( target
, request
, this );
8914 // MARK: IOServicePM
8916 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8918 //*********************************************************************************
8921 // Serialize IOServicePM for debugging.
8922 //*********************************************************************************
8925 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8927 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8930 dict
->setObject(key
, num
);
8935 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
) const
8937 OSDictionary
* dict
;
8939 int powerClamp
= -1;
8942 if (IdleTimerPeriod
)
8945 if (PMActions
.parameter
& kPMActionsFlagLimitPower
)
8949 if (PMActions
.parameter
&
8950 (kPMActionsFlagIsDisplayWrangler
| kPMActionsFlagIsGraphicsDevice
))
8954 #if WORK_QUEUE_STATS
8955 if (gIOPMRootNode
== ControllingDriver
)
8960 dict
= OSDictionary::withDictionary(
8961 PowerClients
, PowerClients
->getCount() + dictSize
);
8963 dict
= OSDictionary::withCapacity(dictSize
);
8967 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8968 setPMProperty(dict
, "CapabilityFlags", CurrentCapabilityFlags
);
8969 if (NumberOfPowerStates
)
8970 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
-1);
8971 if (DesiredPowerState
!= CurrentPowerState
)
8972 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8973 if (kIOPM_Finished
!= MachineState
)
8974 setPMProperty(dict
, "MachineState", MachineState
);
8975 if (DeviceOverrideEnabled
)
8976 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8977 if (powerClamp
>= 0)
8978 setPMProperty(dict
, "PowerClamp", powerClamp
);
8980 if (IdleTimerPeriod
)
8986 clock_get_uptime(&now
);
8988 // The idle timer period in milliseconds
8989 setPMProperty(dict
, "IdleTimerPeriod", NextIdleTimerPeriod
* 1000ULL);
8991 // Number of tickles since the last idle timer expiration
8992 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8994 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
8996 // Milliseconds since the last activity tickle
8998 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8999 absolutetime_to_nanoseconds(delta
, &nsecs
);
9000 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
9003 if (!IdleTimerStopped
&& AbsoluteTime_to_scalar(&IdleTimerStartTime
))
9005 // Idle timer elapsed time in milliseconds
9007 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
9008 absolutetime_to_nanoseconds(delta
, &nsecs
);
9009 setPMProperty(dict
, "IdleTimerElapsedTime", NS_TO_MS(nsecs
));
9013 #if WORK_QUEUE_STATS
9014 if (gIOPMRootNode
== Owner
)
9016 setPMProperty(dict
, "WQ-CheckForWork",
9017 gIOPMWorkQueue
->fStatCheckForWork
);
9018 setPMProperty(dict
, "WQ-ScanEntries",
9019 gIOPMWorkQueue
->fStatScanEntries
);
9020 setPMProperty(dict
, "WQ-QueueEmpty",
9021 gIOPMWorkQueue
->fStatQueueEmpty
);
9022 setPMProperty(dict
, "WQ-NoWorkDone",
9023 gIOPMWorkQueue
->fStatNoWorkDone
);
9027 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
)
9029 // Don't report advisory tickle when it has no influence
9030 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
9033 ok
= dict
->serialize(s
);
9037 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
9040 bool IOServicePM::serialize( OSSerialize
* s
) const
9042 IOReturn ret
= kIOReturnNotReady
;
9044 if (gIOPMWatchDogThread
== current_thread())
9046 // Calling without lock as this data is collected for debug purpose, before reboot.
9047 // The workloop is probably already hung in state machine.
9048 ret
= gatedSerialize(s
);
9050 else if (gIOPMWorkLoop
)
9052 ret
= gIOPMWorkLoop
->runAction(
9053 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
9054 (OSObject
*) this, (void *) s
);
9057 return (kIOReturnSuccess
== ret
);
9060 void IOServicePM::pmPrint(
9063 uintptr_t param2
) const
9065 gPlatform
->PMLog(Name
, event
, param1
, param2
);
9068 void IOServicePM::pmTrace(
9072 uintptr_t param2
) const
9074 uintptr_t nameAsArg
= 0;
9076 assert(event
< KDBG_CODE_MAX
);
9077 assert((eventFunc
& ~KDBG_FUNC_MASK
) == 0);
9079 // Copy the first characters of the name into an uintptr_t.
9080 // NULL termination is not required.
9081 strncpy((char*)&nameAsArg
, Name
, sizeof(nameAsArg
));
9083 IOTimeStampConstant(IODBG_POWER(event
) | eventFunc
, nameAsArg
, (uintptr_t)Owner
->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1
)), (uintptr_t)(OBFUSCATE(param2
)));