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
);
66 computeTimeDeltaNS( const AbsoluteTime
* start
)
71 clock_get_uptime(&now
);
72 SUB_ABSOLUTETIME(&now
, start
);
73 absolutetime_to_nanoseconds(now
, &nsec
);
78 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
81 //******************************************************************************
83 //******************************************************************************
85 static bool gIOPMInitialized
= false;
86 static uint32_t gIOPMBusyRequestCount
= 0;
87 static uint32_t gIOPMWorkInvokeCount
= 0;
88 static uint32_t gIOPMTickleGeneration
= 0;
89 static IOWorkLoop
* gIOPMWorkLoop
= 0;
90 static IOPMRequestQueue
* gIOPMRequestQueue
= 0;
91 static IOPMRequestQueue
* gIOPMReplyQueue
= 0;
92 static IOPMWorkQueue
* gIOPMWorkQueue
= 0;
93 static IOPMCompletionQueue
* gIOPMCompletionQueue
= 0;
94 static IOPMRequest
* gIOPMRequest
= 0;
95 static IOService
* gIOPMRootNode
= 0;
96 static IOPlatformExpert
* gPlatform
= 0;
98 static char gIOSpinDumpKextName
[128];
99 static char gIOSpinDumpDelayType
[16];
100 static uint32_t gIOSpinDumpDelayDuration
= 0;
102 static SYSCTL_STRING(_debug
, OID_AUTO
, swd_kext_name
,
103 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
104 &gIOSpinDumpKextName
, sizeof(gIOSpinDumpKextName
), "");
105 static SYSCTL_STRING(_debug
, OID_AUTO
, swd_delay_type
,
106 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
107 &gIOSpinDumpDelayType
, sizeof(gIOSpinDumpDelayType
), "");
108 static SYSCTL_INT(_debug
, OID_AUTO
, swd_delay_duration
,
109 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
110 &gIOSpinDumpDelayDuration
, 0, "");
112 const OSSymbol
* gIOPMPowerClientDevice
= 0;
113 const OSSymbol
* gIOPMPowerClientDriver
= 0;
114 const OSSymbol
* gIOPMPowerClientChildProxy
= 0;
115 const OSSymbol
* gIOPMPowerClientChildren
= 0;
116 const OSSymbol
* gIOPMPowerClientRootDomain
= 0;
118 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= 0;
119 static bool gIOPMAdvisoryTickleEnabled
= true;
120 static thread_t gIOPMWatchDogThread
= NULL
;
121 uint32_t gCanSleepTimeout
= 0;
124 getPMRequestType( void )
126 uint32_t type
= kIOPMRequestTypeInvalid
;
128 type
= gIOPMRequest
->getType();
133 static IOPMRequestTag
134 getPMRequestTag( void )
136 IOPMRequestTag tag
= 0;
138 (gIOPMRequest
->getType() == kIOPMRequestTypeRequestPowerStateOverride
)) {
139 tag
= gIOPMRequest
->fRequestTag
;
144 SYSCTL_UINT(_kern
, OID_AUTO
, pmtimeout
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &gCanSleepTimeout
, 0, "Power Management Timeout");
146 //******************************************************************************
148 //******************************************************************************
150 #define PM_ERROR(x...) do { kprintf(x);IOLog(x); \
152 #define PM_LOG(x...) do { kprintf(x); } while (false)
154 #define PM_LOG1(x...) do { \
155 if (kIOLogDebugPower & gIOKitDebug) \
156 kprintf(x); } while (false)
158 #define PM_LOG2(x...) do { \
159 if (kIOLogDebugPower & gIOKitDebug) \
160 kprintf(x); } while (false)
163 #define PM_LOG3(x...) do { kprintf(x); } while (false)
165 #define PM_LOG3(x...)
168 #define RD_LOG(x...) do { \
169 if ((kIOLogPMRootDomain & gIOKitDebug) && \
170 (getPMRootDomain() == this)) { \
171 kprintf("PMRD: " x); \
173 #define PM_ASSERT_IN_GATE(x) \
175 assert(gIOPMWorkLoop->inGate()); \
178 #define PM_LOCK() IOLockLock(fPMLock)
179 #define PM_UNLOCK() IOLockUnlock(fPMLock)
180 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
181 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
183 #define us_per_s 1000000
184 #define ns_per_us 1000
185 #define k30Seconds (30*us_per_s)
186 #define k5Seconds ( 5*us_per_s)
188 #define kCanSleepMaxTimeReq k5Seconds
190 #define kCanSleepMaxTimeReq k30Seconds
192 #define kMaxTimeRequested k30Seconds
193 #define kMinAckTimeoutTicks (10*1000000)
194 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
195 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
196 #define kPwrMgtKey "IOPowerManagement"
198 #define OUR_PMLog(t, a, b) do { \
200 if (gIOKitDebug & kIOLogPower) \
201 pwrMgt->pmPrint(t, a, b); \
202 if (gIOKitTrace & kIOTracePowerMgmt) \
203 pwrMgt->pmTrace(t, DBG_FUNC_NONE, a, b); \
207 #define OUR_PMLogFuncStart(t, a, b) do { \
209 if (gIOKitDebug & kIOLogPower) \
210 pwrMgt->pmPrint(t, a, b); \
211 if (gIOKitTrace & kIOTracePowerMgmt) \
212 pwrMgt->pmTrace(t, DBG_FUNC_START, a, b); \
216 #define OUR_PMLogFuncEnd(t, a, b) do { \
218 if (gIOKitDebug & kIOLogPower) \
219 pwrMgt->pmPrint(-t, a, b); \
220 if (gIOKitTrace & kIOTracePowerMgmt) \
221 pwrMgt->pmTrace(t, DBG_FUNC_END, a, b); \
225 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
226 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
228 #define SUPPORT_IDLE_CANCEL 1
230 #define kIOPMPowerStateMax 0xFFFFFFFF
231 #define kInvalidTicklePowerState kIOPMPowerStateMax
233 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
235 #define IS_PM_ROOT (this == gIOPMRootNode)
236 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
237 #define IS_POWER_DROP (StateOrder(fHeadNotePowerState) < StateOrder(fCurrentPowerState))
238 #define IS_POWER_RISE (StateOrder(fHeadNotePowerState) > StateOrder(fCurrentPowerState))
240 // log setPowerStates longer than (ns):
241 #if defined(__i386__) || defined(__x86_64__)
242 #define LOG_SETPOWER_TIMES (300ULL * 1000ULL * 1000ULL)
244 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
246 // log app responses longer than (ns):
247 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
248 // use message tracer to log messages longer than (ns):
249 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
251 // log kext responses longer than (ns):
252 #define LOG_KEXT_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
255 kReserveDomainPower
= 1
259 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
260 assert(kIOPM_BadMachineState != n); \
261 fSavedMachineState = n; } while (false)
264 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
265 fMachineState = fSavedMachineState; \
266 fSavedMachineState = kIOPM_BadMachineState; } while (false)
268 #define PM_ACTION_0(a) \
269 do { if (fPMActions.a) { \
270 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
273 #define PM_ACTION_2(a, x, y) \
274 do { if (fPMActions.a) { \
275 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, \
276 getPMRequestTag()); } \
279 #define PM_ACTION_3(a, x, y, z) \
280 do { if (fPMActions.a) { \
281 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, z); } \
284 static OSNumber
* copyClientIDForNotification(
286 IOPMInterestContext
*context
);
288 static void logClientIDForNotification(
290 IOPMInterestContext
*context
,
291 const char *logString
);
293 //*********************************************************************************
296 // Check kgmacros after modifying machine states.
297 //*********************************************************************************
302 kIOPM_OurChangeTellClientsPowerDown
= 1,
303 kIOPM_OurChangeTellUserPMPolicyPowerDown
= 2,
304 kIOPM_OurChangeTellPriorityClientsPowerDown
= 3,
305 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 4,
306 kIOPM_OurChangeSetPowerState
= 5,
307 kIOPM_OurChangeWaitForPowerSettle
= 6,
308 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 7,
309 kIOPM_OurChangeTellCapabilityDidChange
= 8,
310 kIOPM_OurChangeFinish
= 9,
312 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
313 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
314 kIOPM_ParentChangeSetPowerState
= 12,
315 kIOPM_ParentChangeWaitForPowerSettle
= 13,
316 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
317 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
318 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
320 kIOPM_NotifyChildrenStart
= 17,
321 kIOPM_NotifyChildrenOrdered
= 18,
322 kIOPM_NotifyChildrenDelayed
= 19,
323 kIOPM_SyncTellClientsPowerDown
= 20,
324 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
325 kIOPM_SyncNotifyWillChange
= 22,
326 kIOPM_SyncNotifyDidChange
= 23,
327 kIOPM_SyncTellCapabilityDidChange
= 24,
328 kIOPM_SyncFinish
= 25,
329 kIOPM_TellCapabilityChangeDone
= 26,
330 kIOPM_DriverThreadCallDone
= 27,
332 kIOPM_BadMachineState
= 0xFFFFFFFF
335 //*********************************************************************************
338 // Initialize power management.
339 //*********************************************************************************
342 IOService::PMinit( void )
345 if (!gIOPMInitialized
) {
346 gPlatform
= getPlatform();
347 gIOPMWorkLoop
= IOWorkLoop::workLoop();
349 gIOPMRequestQueue
= IOPMRequestQueue::create(
350 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
351 this, &IOService::actionPMRequestQueue
));
353 gIOPMReplyQueue
= IOPMRequestQueue::create(
354 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
355 this, &IOService::actionPMReplyQueue
));
357 gIOPMWorkQueue
= IOPMWorkQueue::create(this,
358 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
359 &IOService::actionPMWorkQueueInvoke
),
360 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
361 &IOService::actionPMWorkQueueRetire
));
363 gIOPMCompletionQueue
= IOPMCompletionQueue::create(
364 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
365 this, &IOService::actionPMCompletionQueue
));
367 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
369 gIOPMRequestQueue
->release();
370 gIOPMRequestQueue
= 0;
373 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
375 gIOPMReplyQueue
->release();
379 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
381 gIOPMWorkQueue
->release();
385 // Must be added after the work queue, which pushes request
386 // to the completion queue without signaling the work loop.
387 if (gIOPMWorkLoop
->addEventSource(gIOPMCompletionQueue
) !=
389 gIOPMCompletionQueue
->release();
390 gIOPMCompletionQueue
= 0;
393 gIOPMPowerClientDevice
=
394 OSSymbol::withCStringNoCopy( "DevicePowerState" );
396 gIOPMPowerClientDriver
=
397 OSSymbol::withCStringNoCopy( "DriverPowerState" );
399 gIOPMPowerClientChildProxy
=
400 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
402 gIOPMPowerClientChildren
=
403 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
405 gIOPMPowerClientAdvisoryTickle
=
406 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
408 gIOPMPowerClientRootDomain
=
409 OSSymbol::withCStringNoCopy( "RootDomainPower" );
411 gIOSpinDumpKextName
[0] = '\0';
412 gIOSpinDumpDelayType
[0] = '\0';
415 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMCompletionQueue
) {
416 gIOPMInitialized
= true;
419 if (!gIOPMInitialized
) {
423 pwrMgt
= new IOServicePM
;
425 setProperty(kPwrMgtKey
, pwrMgt
);
427 queue_init(&pwrMgt
->WorkChain
);
428 queue_init(&pwrMgt
->RequestHead
);
429 queue_init(&pwrMgt
->PMDriverCallQueue
);
432 fPMLock
= IOLockAlloc();
433 fInterestedDrivers
= new IOPMinformeeList
;
434 fInterestedDrivers
->initialize();
435 fDesiredPowerState
= kPowerStateZero
;
436 fDeviceDesire
= kPowerStateZero
;
437 fInitialPowerChange
= true;
438 fInitialSetPowerState
= true;
439 fPreviousRequestPowerFlags
= 0;
440 fDeviceOverrideEnabled
= false;
441 fMachineState
= kIOPM_Finished
;
442 fSavedMachineState
= kIOPM_BadMachineState
;
443 fIdleTimerMinPowerState
= kPowerStateZero
;
444 fActivityLock
= IOLockAlloc();
445 fStrictTreeOrder
= false;
446 fActivityTicklePowerState
= kInvalidTicklePowerState
;
447 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
448 fControllingDriver
= NULL
;
450 fNumberOfPowerStates
= 0;
451 fCurrentPowerState
= kPowerStateZero
;
452 fParentsCurrentPowerFlags
= 0;
453 fMaxPowerState
= kPowerStateZero
;
455 fParentsKnowState
= false;
457 fResponseArray
= NULL
;
458 fNotifyClientArray
= NULL
;
459 fCurrentPowerConsumption
= kIOPMUnknown
;
460 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
462 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot())) {
463 gIOPMRootNode
= this;
464 fParentsKnowState
= true;
465 } else if (getProperty(kIOPMResetPowerStateOnWakeKey
) == kOSBooleanTrue
) {
466 fResetPowerStateOnWake
= true;
469 if (IS_ROOT_DOMAIN
) {
470 fWatchdogTimer
= thread_call_allocate(
471 &IOService::watchdog_timer_expired
, (thread_call_param_t
)this);
472 fWatchdogLock
= IOLockAlloc();
474 fBlockedArray
= OSArray::withCapacity(4);
477 fAckTimer
= thread_call_allocate(
478 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
479 fSettleTimer
= thread_call_allocate(
480 &settle_timer_expired
, (thread_call_param_t
)this);
481 fIdleTimer
= thread_call_allocate(
482 &idle_timer_expired
, (thread_call_param_t
)this);
483 fDriverCallEntry
= thread_call_allocate(
484 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
485 assert(fDriverCallEntry
);
486 if (kIOKextSpinDump
& gIOKitDebug
) {
487 fSpinDumpTimer
= thread_call_allocate(
488 &IOService::spindump_timer_expired
, (thread_call_param_t
)this);
491 // Check for powerChangeDone override.
492 if (OSMemberFunctionCast(void (*)(void),
493 getResourceService(), &IOService::powerChangeDone
) !=
494 OSMemberFunctionCast(void (*)(void),
495 this, &IOService::powerChangeDone
)) {
496 fPCDFunctionOverride
= true;
500 IOPMprot
* prot
= new IOPMprot
;
503 prot
->ourName
= fName
;
504 prot
->thePlatform
= gPlatform
;
509 pm_vars
= (void *) (uintptr_t) true;
516 //*********************************************************************************
519 // Free the data created by PMinit. Only called from IOService::free().
520 //*********************************************************************************
523 IOService::PMfree( void )
529 assert(fMachineState
== kIOPM_Finished
);
530 assert(fInsertInterestSet
== NULL
);
531 assert(fRemoveInterestSet
== NULL
);
532 assert(fNotifyChildArray
== NULL
);
533 assert(queue_empty(&pwrMgt
->RequestHead
));
534 assert(queue_empty(&fPMDriverCallQueue
));
536 if (fWatchdogTimer
) {
537 thread_call_cancel(fWatchdogTimer
);
538 thread_call_free(fWatchdogTimer
);
539 fWatchdogTimer
= NULL
;
543 IOLockFree(fWatchdogLock
);
544 fWatchdogLock
= NULL
;
548 fBlockedArray
->release();
549 fBlockedArray
= NULL
;
553 thread_call_cancel(fSettleTimer
);
554 thread_call_free(fSettleTimer
);
558 thread_call_cancel(fAckTimer
);
559 thread_call_free(fAckTimer
);
563 thread_call_cancel(fIdleTimer
);
564 thread_call_free(fIdleTimer
);
567 if (fDriverCallEntry
) {
568 thread_call_free(fDriverCallEntry
);
569 fDriverCallEntry
= NULL
;
571 if (fSpinDumpTimer
) {
572 thread_call_cancel(fSpinDumpTimer
);
573 thread_call_free(fSpinDumpTimer
);
574 fSpinDumpTimer
= NULL
;
581 IOLockFree(fActivityLock
);
582 fActivityLock
= NULL
;
584 if (fInterestedDrivers
) {
585 fInterestedDrivers
->release();
586 fInterestedDrivers
= NULL
;
588 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
589 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
590 fDriverCallParamPtr
= 0;
591 fDriverCallParamSlots
= 0;
593 if (fResponseArray
) {
594 fResponseArray
->release();
595 fResponseArray
= NULL
;
597 if (fNotifyClientArray
) {
598 fNotifyClientArray
->release();
599 fNotifyClientArray
= NULL
;
601 if (fPowerStates
&& fNumberOfPowerStates
) {
602 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
603 fNumberOfPowerStates
= 0;
607 fPowerClients
->release();
624 IOService::PMDebug( uint32_t event
, uintptr_t param1
, uintptr_t param2
)
626 OUR_PMLog(event
, param1
, param2
);
629 //*********************************************************************************
630 // [public] joinPMtree
632 // A policy-maker calls its nub here when initializing, to be attached into
633 // the power management hierarchy. The default function is to call the
634 // platform expert, which knows how to do it. This method is overridden
635 // by a nub subclass which may either know how to do it, or may need to
636 // take other action.
638 // This may be the only "power management" method used in a nub,
639 // meaning it may not be initialized for power management.
640 //*********************************************************************************
643 IOService::joinPMtree( IOService
* driver
)
645 IOPlatformExpert
* platform
;
647 platform
= getPlatform();
648 assert(platform
!= 0);
649 platform
->PMRegisterDevice(this, driver
);
653 //*********************************************************************************
654 // [deprecated] youAreRoot
656 // Power Managment is informing us that we are the root power domain.
657 //*********************************************************************************
660 IOService::youAreRoot( void )
664 #endif /* !__LP64__ */
666 //*********************************************************************************
669 // Immediately stop driver callouts. Schedule an async stop request to detach
671 //*********************************************************************************
674 IOService::PMstop( void )
676 IOPMRequest
* request
;
684 if (fLockedFlags
.PMStop
) {
685 PM_LOG2("%s: PMstop() already stopped\n", fName
);
690 // Inhibit future driver calls.
691 fLockedFlags
.PMStop
= true;
693 // Wait for all prior driver calls to finish.
694 waitForPMDriverCall();
698 // The rest of the work is performed async.
699 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
701 PM_LOG2("%s: %p PMstop\n", getName(), OBFUSCATE(this));
702 submitPMRequest( request
);
706 //*********************************************************************************
707 // [private] handlePMstop
709 // Disconnect the node from all parents and children in the power plane.
710 //*********************************************************************************
713 IOService::handlePMstop( IOPMRequest
* request
)
717 IOPowerConnection
* connection
;
718 IOService
* theChild
;
719 IOService
* theParent
;
722 PM_LOG2("%s: %p %s start\n", getName(), OBFUSCATE(this), __FUNCTION__
);
724 // remove driver from prevent system sleep lists
725 getPMRootDomain()->updatePreventIdleSleepList(this, false);
726 getPMRootDomain()->updatePreventSystemSleepList(this, false);
728 // remove the property
729 removeProperty(kPwrMgtKey
);
732 iter
= getParentIterator(gIOPowerPlane
);
734 while ((next
= iter
->getNextObject())) {
735 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
736 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
738 theParent
->removePowerChild(connection
);
739 theParent
->release();
746 // detach IOConnections
747 detachAbove( gIOPowerPlane
);
749 // no more power state changes
750 fParentsKnowState
= false;
753 iter
= getChildIterator(gIOPowerPlane
);
755 while ((next
= iter
->getNextObject())) {
756 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
757 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
759 // detach nub from child
760 connection
->detachFromChild(theChild
, gIOPowerPlane
);
763 // detach us from nub
764 detachFromChild(connection
, gIOPowerPlane
);
770 // Remove all interested drivers from the list, including the power
771 // controlling driver.
773 // Usually, the controlling driver and the policy-maker functionality
774 // are implemented by the same object, and without the deregistration,
775 // the object will be holding an extra retain on itself, and cannot
778 if (fInterestedDrivers
) {
779 IOPMinformeeList
* list
= fInterestedDrivers
;
783 while ((item
= list
->firstInList())) {
784 list
->removeFromList(item
->whatObject
);
789 // Clear idle period to prevent idleTimerExpired() from servicing
790 // idle timer expirations.
792 fIdleTimerPeriod
= 0;
793 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
)) {
797 PM_LOG2("%s: %p %s done\n", getName(), OBFUSCATE(this), __FUNCTION__
);
800 //*********************************************************************************
801 // [public] addPowerChild
803 // Power Management is informing us who our children are.
804 //*********************************************************************************
807 IOService::addPowerChild( IOService
* child
)
809 IOPowerConnection
* connection
= 0;
810 IOPMRequest
* requests
[3] = {0, 0, 0};
815 return kIOReturnBadArgument
;
818 if (!initialized
|| !child
->initialized
) {
819 return IOPMNotYetInitialized
;
822 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
825 // Is this child already one of our children?
827 iter
= child
->getParentIterator( gIOPowerPlane
);
829 IORegistryEntry
* entry
;
832 while ((next
= iter
->getNextObject())) {
833 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
834 isChild(entry
, gIOPowerPlane
)) {
842 PM_LOG("%s: %s (%p) is already a child\n",
843 getName(), child
->getName(), OBFUSCATE(child
));
847 // Add the child to the power plane immediately, but the
848 // joining connection is marked as not ready.
849 // We want the child to appear in the power plane before
850 // returning to the caller, but don't want the caller to
851 // block on the PM work loop.
853 connection
= new IOPowerConnection
;
858 // Create a chain of PM requests to perform the bottom-half
859 // work from the PM work loop.
861 requests
[0] = acquirePMRequest(
863 /* type */ kIOPMRequestTypeAddPowerChild1
);
865 requests
[1] = acquirePMRequest(
867 /* type */ kIOPMRequestTypeAddPowerChild2
);
869 requests
[2] = acquirePMRequest(
871 /* type */ kIOPMRequestTypeAddPowerChild3
);
873 if (!requests
[0] || !requests
[1] || !requests
[2]) {
877 requests
[0]->attachNextRequest( requests
[1] );
878 requests
[1]->attachNextRequest( requests
[2] );
881 connection
->start(this);
882 connection
->setAwaitingAck(false);
883 connection
->setReadyFlag(false);
885 attachToChild( connection
, gIOPowerPlane
);
886 connection
->attachToChild( child
, gIOPowerPlane
);
888 // connection needs to be released
889 requests
[0]->fArg0
= connection
;
890 requests
[1]->fArg0
= connection
;
891 requests
[2]->fArg0
= connection
;
893 submitPMRequests( requests
, 3 );
894 return kIOReturnSuccess
;
898 connection
->release();
901 releasePMRequest(requests
[0]);
904 releasePMRequest(requests
[1]);
907 releasePMRequest(requests
[2]);
910 // Silent failure, to prevent platform drivers from adding the child
911 // to the root domain.
913 return kIOReturnSuccess
;
916 //*********************************************************************************
917 // [private] addPowerChild1
919 // Step 1/3 of adding a power child. Called on the power parent.
920 //*********************************************************************************
923 IOService::addPowerChild1( IOPMRequest
* request
)
925 IOPMPowerStateIndex tempDesire
= kPowerStateZero
;
927 // Make us temporary usable before adding the child.
930 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
932 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
) {
933 tempDesire
= fHighestPowerState
;
936 if ((tempDesire
!= kPowerStateZero
) &&
937 (IS_PM_ROOT
|| (StateOrder(fMaxPowerState
) >= StateOrder(tempDesire
)))) {
938 adjustPowerState(tempDesire
);
942 //*********************************************************************************
943 // [private] addPowerChild2
945 // Step 2/3 of adding a power child. Called on the joining child.
946 // Execution blocked behind addPowerChild1.
947 //*********************************************************************************
950 IOService::addPowerChild2( IOPMRequest
* request
)
952 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
954 IOPMPowerFlags powerFlags
;
956 unsigned long powerState
;
957 unsigned long tempDesire
;
960 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
962 if (!parent
|| !inPlane(gIOPowerPlane
)) {
963 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
967 // Parent will be waiting for us to complete this stage.
968 // It is safe to directly access parent's vars.
970 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
971 powerState
= parent
->fCurrentPowerState
;
974 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
979 // Set our power parent.
981 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
983 setParentInfo( powerFlags
, connection
, knowsState
);
985 connection
->setReadyFlag(true);
987 if (fControllingDriver
&& fParentsKnowState
) {
988 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
989 // initially change into the state we are already in
990 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
991 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
992 adjustPowerState(tempDesire
);
995 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
998 //*********************************************************************************
999 // [private] addPowerChild3
1001 // Step 3/3 of adding a power child. Called on the parent.
1002 // Execution blocked behind addPowerChild2.
1003 //*********************************************************************************
1006 IOService::addPowerChild3( IOPMRequest
* request
)
1008 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
1010 IOPMrootDomain
* rootDomain
= getPMRootDomain();
1012 PM_ASSERT_IN_GATE();
1013 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
1015 if (child
&& inPlane(gIOPowerPlane
)) {
1016 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder")) {
1017 PM_LOG1("%s: strict PM order enforced\n", getName());
1018 fStrictTreeOrder
= true;
1022 rootDomain
->joinAggressiveness( child
);
1025 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1028 connection
->release();
1032 //*********************************************************************************
1033 // [deprecated] setPowerParent
1035 // Power Management is informing us who our parent is.
1036 // If we have a controlling driver, find out, given our newly-informed
1037 // power domain state, what state it would be in, and then tell it
1038 // to assume that state.
1039 //*********************************************************************************
1042 IOService::setPowerParent(
1043 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
1045 return kIOReturnUnsupported
;
1047 #endif /* !__LP64__ */
1049 //*********************************************************************************
1050 // [public] removePowerChild
1052 // Called on a parent whose child is being removed by PMstop().
1053 //*********************************************************************************
1056 IOService::removePowerChild( IOPowerConnection
* theNub
)
1058 IORegistryEntry
* theChild
;
1060 PM_ASSERT_IN_GATE();
1061 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1065 // detach nub from child
1066 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1068 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1069 theChild
->release();
1071 // detach from the nub
1072 detachFromChild(theNub
, gIOPowerPlane
);
1074 // Are we awaiting an ack from this child?
1075 if (theNub
->getAwaitingAck()) {
1076 // yes, pretend we got one
1077 theNub
->setAwaitingAck(false);
1078 if (fHeadNotePendingAcks
!= 0) {
1079 // that's one fewer ack to worry about
1080 fHeadNotePendingAcks
--;
1082 // is that the last?
1083 if (fHeadNotePendingAcks
== 0) {
1085 getPMRootDomain()->reset_watchdog_timer(this, 0);
1087 // This parent may have a request in the work queue that is
1088 // blocked on fHeadNotePendingAcks=0. And removePowerChild()
1089 // is called while executing the child's PMstop request so they
1090 // can occur simultaneously. IOPMWorkQueue::checkForWork() must
1091 // restart and check all request queues again.
1093 gIOPMWorkQueue
->incrementProducerCount();
1100 // A child has gone away, re-scan children desires and clamp bits.
1101 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1103 if (!fAdjustPowerScheduled
) {
1104 IOPMRequest
* request
;
1105 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1107 submitPMRequest( request
);
1108 fAdjustPowerScheduled
= true;
1115 //*********************************************************************************
1116 // [public] registerPowerDriver
1118 // A driver has called us volunteering to control power to our device.
1119 //*********************************************************************************
1122 IOService::registerPowerDriver(
1123 IOService
* powerDriver
,
1124 IOPMPowerState
* powerStates
,
1125 unsigned long numberOfStates
)
1127 IOPMRequest
* request
;
1128 IOPMPSEntry
* powerStatesCopy
= 0;
1129 IOPMPowerStateIndex stateOrder
;
1130 IOReturn error
= kIOReturnSuccess
;
1133 return IOPMNotYetInitialized
;
1136 if (!powerStates
|| (numberOfStates
< 2)) {
1137 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1138 return kIOReturnBadArgument
;
1141 if (!powerDriver
|| !powerDriver
->initialized
) {
1142 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1143 return kIOReturnBadArgument
;
1146 if (powerStates
[0].version
> kIOPMPowerStateVersion2
) {
1147 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1148 return kIOReturnBadArgument
;
1152 // Make a copy of the supplied power state array.
1153 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1154 if (!powerStatesCopy
) {
1155 error
= kIOReturnNoMemory
;
1159 // Initialize to bogus values
1160 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++) {
1161 powerStatesCopy
[i
].stateOrderToIndex
= kIOPMPowerStateMax
;
1164 for (uint32_t i
= 0; i
< numberOfStates
; i
++) {
1165 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1166 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1167 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1168 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1169 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1170 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1171 if (powerStates
[i
].version
>= kIOPMPowerStateVersion2
) {
1172 stateOrder
= powerStates
[i
].stateOrder
;
1177 if (stateOrder
< numberOfStates
) {
1178 powerStatesCopy
[i
].stateOrder
= stateOrder
;
1179 powerStatesCopy
[stateOrder
].stateOrderToIndex
= i
;
1183 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++) {
1184 if (powerStatesCopy
[i
].stateOrderToIndex
== kIOPMPowerStateMax
) {
1185 // power state order missing
1186 error
= kIOReturnBadArgument
;
1190 if (kIOReturnSuccess
!= error
) {
1194 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1196 error
= kIOReturnNoMemory
;
1200 powerDriver
->retain();
1201 request
->fArg0
= (void *) powerDriver
;
1202 request
->fArg1
= (void *) powerStatesCopy
;
1203 request
->fArg2
= (void *) numberOfStates
;
1205 submitPMRequest( request
);
1206 return kIOReturnSuccess
;
1209 if (powerStatesCopy
) {
1210 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1216 //*********************************************************************************
1217 // [private] handleRegisterPowerDriver
1218 //*********************************************************************************
1221 IOService::handleRegisterPowerDriver( IOPMRequest
* request
)
1223 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1224 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1225 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1226 unsigned long i
, stateIndex
;
1227 unsigned long lowestPowerState
;
1231 PM_ASSERT_IN_GATE();
1232 assert(powerStates
);
1233 assert(powerDriver
);
1234 assert(numberOfStates
> 1);
1236 if (!fNumberOfPowerStates
) {
1237 OUR_PMLog(kPMLogControllingDriver
,
1238 (unsigned long) numberOfStates
,
1239 (unsigned long) kIOPMPowerStateVersion1
);
1241 fPowerStates
= powerStates
;
1242 fNumberOfPowerStates
= numberOfStates
;
1243 fControllingDriver
= powerDriver
;
1244 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1246 lowestPowerState
= fPowerStates
[0].stateOrderToIndex
;
1247 fHighestPowerState
= fPowerStates
[numberOfStates
- 1].stateOrderToIndex
;
1249 // OR'in all the output power flags
1250 fMergedOutputPowerFlags
= 0;
1251 fDeviceUsablePowerState
= lowestPowerState
;
1252 for (i
= 0; i
< numberOfStates
; i
++) {
1253 fMergedOutputPowerFlags
|= fPowerStates
[i
].outputPowerFlags
;
1255 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
1256 assert(stateIndex
< numberOfStates
);
1257 if ((fDeviceUsablePowerState
== lowestPowerState
) &&
1258 (fPowerStates
[stateIndex
].capabilityFlags
& IOPMDeviceUsable
)) {
1259 // The minimum power state that the device is usable
1260 fDeviceUsablePowerState
= stateIndex
;
1264 // Register powerDriver as interested, unless already done.
1265 // We don't want to register the default implementation since
1266 // it does nothing. One ramification of not always registering
1267 // is the one fewer retain count held.
1269 root
= getPlatform()->getProvider();
1272 ((OSMemberFunctionCast(void (*)(void),
1273 root
, &IOService::powerStateDidChangeTo
)) !=
1274 ((OSMemberFunctionCast(void (*)(void),
1275 this, &IOService::powerStateDidChangeTo
)))) ||
1276 ((OSMemberFunctionCast(void (*)(void),
1277 root
, &IOService::powerStateWillChangeTo
)) !=
1278 ((OSMemberFunctionCast(void (*)(void),
1279 this, &IOService::powerStateWillChangeTo
))))) {
1280 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
) {
1282 fInterestedDrivers
->appendNewInformee(powerDriver
);
1287 // Examine all existing power clients and perform limit check.
1289 if (fPowerClients
&&
1290 (iter
= OSCollectionIterator::withCollection(fPowerClients
))) {
1291 const OSSymbol
* client
;
1292 while ((client
= (const OSSymbol
*) iter
->getNextObject())) {
1293 IOPMPowerStateIndex powerState
= getPowerStateForClient(client
);
1294 if (powerState
>= numberOfStates
) {
1295 updatePowerClient(client
, fHighestPowerState
);
1301 if (inPlane(gIOPowerPlane
) && fParentsKnowState
) {
1302 IOPMPowerStateIndex tempDesire
;
1303 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1304 // initially change into the state we are already in
1305 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1306 adjustPowerState(tempDesire
);
1309 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1310 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1313 powerDriver
->release();
1316 //*********************************************************************************
1317 // [public] registerInterestedDriver
1319 // Add the caller to our list of interested drivers and return our current
1320 // power state. If we don't have a power-controlling driver yet, we will
1321 // call this interested driver again later when we do get a driver and find
1322 // out what the current power state of the device is.
1323 //*********************************************************************************
1326 IOService::registerInterestedDriver( IOService
* driver
)
1328 IOPMRequest
* request
;
1331 if (!driver
|| !initialized
|| !fInterestedDrivers
) {
1336 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1337 if (fInsertInterestSet
== NULL
) {
1338 fInsertInterestSet
= OSSet::withCapacity(4);
1340 if (fInsertInterestSet
) {
1341 fInsertInterestSet
->setObject(driver
);
1342 if (fRemoveInterestSet
) {
1343 fRemoveInterestSet
->removeObject(driver
);
1349 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1351 submitPMRequest( request
);
1355 // This return value cannot be trusted, but return a value
1356 // for those clients that care.
1358 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1359 return kIOPMDeviceUsable
;
1362 //*********************************************************************************
1363 // [public] deRegisterInterestedDriver
1364 //*********************************************************************************
1367 IOService::deRegisterInterestedDriver( IOService
* driver
)
1369 IOPMinformee
* item
;
1370 IOPMRequest
* request
;
1374 return kIOReturnBadArgument
;
1376 if (!initialized
|| !fInterestedDrivers
) {
1377 return IOPMNotPowerManaged
;
1381 if (fInsertInterestSet
) {
1382 fInsertInterestSet
->removeObject(driver
);
1385 item
= fInterestedDrivers
->findItem(driver
);
1388 return kIOReturnNotFound
;
1391 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1392 if (fRemoveInterestSet
== NULL
) {
1393 fRemoveInterestSet
= OSSet::withCapacity(4);
1395 if (fRemoveInterestSet
) {
1396 fRemoveInterestSet
->setObject(driver
);
1398 item
->active
= false;
1399 waitForPMDriverCall( driver
);
1405 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1407 submitPMRequest( request
);
1414 //*********************************************************************************
1415 // [private] handleInterestChanged
1417 // Handle interest added or removed.
1418 //*********************************************************************************
1421 IOService::handleInterestChanged( IOPMRequest
* request
)
1424 IOPMinformee
* informee
;
1425 IOPMinformeeList
* list
= fInterestedDrivers
;
1429 if (fInsertInterestSet
) {
1430 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject())) {
1431 if (list
->findItem(driver
) == NULL
) {
1432 informee
= list
->appendNewInformee(driver
);
1434 fInsertInterestSet
->removeObject(driver
);
1436 fInsertInterestSet
->release();
1437 fInsertInterestSet
= 0;
1440 if (fRemoveInterestSet
) {
1441 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject())) {
1442 informee
= list
->findItem(driver
);
1444 // Clean-up async interest acknowledgement
1445 if (fHeadNotePendingAcks
&& informee
->timer
) {
1446 informee
->timer
= 0;
1447 fHeadNotePendingAcks
--;
1449 list
->removeFromList(driver
);
1451 fRemoveInterestSet
->removeObject(driver
);
1453 fRemoveInterestSet
->release();
1454 fRemoveInterestSet
= 0;
1460 //*********************************************************************************
1461 // [public] acknowledgePowerChange
1463 // After we notified one of the interested drivers or a power-domain child
1464 // of an impending change in power, it has called to say it is now
1465 // prepared for the change. If this object is the last to
1466 // acknowledge this change, we take whatever action we have been waiting
1468 // That may include acknowledging to our parent. In this case, we do it
1469 // last of all to insure that this doesn't cause the parent to call us some-
1470 // where else and alter data we are relying on here (like the very existance
1471 // of a "current change note".)
1472 //*********************************************************************************
1475 IOService::acknowledgePowerChange( IOService
* whichObject
)
1477 IOPMRequest
* request
;
1480 return IOPMNotYetInitialized
;
1483 return kIOReturnBadArgument
;
1486 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1488 return kIOReturnNoMemory
;
1491 whichObject
->retain();
1492 request
->fArg0
= whichObject
;
1494 submitPMRequest( request
);
1498 //*********************************************************************************
1499 // [private] handleAcknowledgePowerChange
1500 //*********************************************************************************
1503 IOService::handleAcknowledgePowerChange( IOPMRequest
* request
)
1505 IOPMinformee
* informee
;
1506 unsigned long childPower
= kIOPMUnknown
;
1507 IOService
* theChild
;
1508 IOService
* whichObject
;
1509 bool all_acked
= false;
1511 PM_ASSERT_IN_GATE();
1512 whichObject
= (IOService
*) request
->fArg0
;
1513 assert(whichObject
);
1515 // one of our interested drivers?
1516 informee
= fInterestedDrivers
->findItem( whichObject
);
1517 if (informee
== NULL
) {
1518 if (!isChild(whichObject
, gIOPowerPlane
)) {
1519 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1522 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1525 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1528 if (fHeadNotePendingAcks
!= 0) {
1529 assert(fPowerStates
!= NULL
);
1531 // yes, make sure we're expecting acks
1532 if (informee
!= NULL
) {
1533 // it's an interested driver
1534 // make sure we're expecting this ack
1535 if (informee
->timer
!= 0) {
1536 if (informee
->timer
> 0) {
1537 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1538 if (nsec
> LOG_SETPOWER_TIMES
) {
1539 getPMRootDomain()->pmStatsRecordApplicationResponse(
1540 gIOPMStatsDriverPSChangeSlow
, informee
->whatObject
->getName(),
1541 fDriverCallReason
, NS_TO_MS(nsec
), informee
->whatObject
->getRegistryEntryID(),
1542 NULL
, fHeadNotePowerState
);
1547 informee
->timer
= 0;
1548 // that's one fewer to worry about
1549 fHeadNotePendingAcks
--;
1551 // this driver has already acked
1552 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1556 // make sure we're expecting this ack
1557 if (((IOPowerConnection
*)whichObject
)->getAwaitingAck()) {
1558 // that's one fewer to worry about
1559 fHeadNotePendingAcks
--;
1560 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1561 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1563 childPower
= theChild
->currentPowerConsumption();
1564 theChild
->release();
1566 if (childPower
== kIOPMUnknown
) {
1567 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1569 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
) {
1570 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1576 if (fHeadNotePendingAcks
== 0) {
1577 // yes, stop the timer
1579 // and now we can continue
1581 getPMRootDomain()->reset_watchdog_timer(this, 0);
1584 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1589 whichObject
->release();
1595 //*********************************************************************************
1596 // [public] acknowledgeSetPowerState
1598 // After we instructed our controlling driver to change power states,
1599 // it has called to say it has finished doing so.
1600 // We continue to process the power state change.
1601 //*********************************************************************************
1604 IOService::acknowledgeSetPowerState( void )
1606 IOPMRequest
* request
;
1609 return IOPMNotYetInitialized
;
1612 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1614 return kIOReturnNoMemory
;
1617 submitPMRequest( request
);
1618 return kIOReturnSuccess
;
1621 //*********************************************************************************
1622 // [private] adjustPowerState
1623 //*********************************************************************************
1626 IOService::adjustPowerState( uint32_t clamp
)
1628 PM_ASSERT_IN_GATE();
1629 computeDesiredState(clamp
, false);
1630 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
)) {
1631 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1633 // Indicate that children desires must be ignored, and do not ask
1634 // apps for permission to drop power. This is used by root domain
1635 // for demand sleep.
1637 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
) {
1638 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1642 /* flags */ changeFlags
,
1643 /* power state */ fDesiredPowerState
,
1644 /* domain flags */ 0,
1646 /* parent flags */ 0);
1650 //*********************************************************************************
1651 // [public] synchronizePowerTree
1652 //*********************************************************************************
1655 IOService::synchronizePowerTree(
1656 IOOptionBits options
,
1657 IOService
* notifyRoot
)
1659 IOPMRequest
* request_c
= 0;
1660 IOPMRequest
* request_s
;
1662 if (this != getPMRootDomain()) {
1663 return kIOReturnBadArgument
;
1666 return kIOPMNotYetInitialized
;
1669 OUR_PMLog(kPMLogCSynchronizePowerTree
, options
, (notifyRoot
!= 0));
1674 // Cancels don't need to be synchronized.
1675 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1677 submitPMRequest(nr
);
1679 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1681 submitPMRequest(nr
);
1685 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1687 goto error_no_memory
;
1690 if (options
& kIOPMSyncCancelPowerDown
) {
1691 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1694 request_c
->attachNextRequest( request_s
);
1695 submitPMRequest(request_c
);
1698 request_s
->fArg0
= (void *)(uintptr_t) options
;
1699 submitPMRequest(request_s
);
1701 return kIOReturnSuccess
;
1705 releasePMRequest(request_c
);
1708 releasePMRequest(request_s
);
1710 return kIOReturnNoMemory
;
1713 //*********************************************************************************
1714 // [private] handleSynchronizePowerTree
1715 //*********************************************************************************
1718 IOService::handleSynchronizePowerTree( IOPMRequest
* request
)
1720 PM_ASSERT_IN_GATE();
1721 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1722 (fCurrentPowerState
== fHighestPowerState
)) {
1723 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1726 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1727 (options
& kIOPMSyncNoChildNotify
),
1728 /* power state */ fCurrentPowerState
,
1729 /* domain flags */ 0,
1731 /* parent flags */ 0);
1736 //*********************************************************************************
1737 // [deprecated] powerDomainWillChangeTo
1739 // Called by the power-hierarchy parent notifying of a new power state
1740 // in the power domain.
1741 // We enqueue a parent power-change to our queue of power changes.
1742 // This may or may not cause us to change power, depending on what
1743 // kind of change is occuring in the domain.
1744 //*********************************************************************************
1747 IOService::powerDomainWillChangeTo(
1748 IOPMPowerFlags newPowerFlags
,
1749 IOPowerConnection
* whichParent
)
1752 return kIOReturnUnsupported
;
1754 #endif /* !__LP64__ */
1756 //*********************************************************************************
1757 // [private] handlePowerDomainWillChangeTo
1758 //*********************************************************************************
1761 IOService::handlePowerDomainWillChangeTo( IOPMRequest
* request
)
1763 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1764 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1765 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1766 IOPMPowerChangeFlags myChangeFlags
;
1769 IOPowerConnection
* connection
;
1770 IOPMPowerStateIndex maxPowerState
;
1771 IOPMPowerFlags combinedPowerFlags
;
1772 bool savedParentsKnowState
;
1773 IOReturn result
= IOPMAckImplied
;
1775 PM_ASSERT_IN_GATE();
1776 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1778 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck()) {
1779 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1783 savedParentsKnowState
= fParentsKnowState
;
1785 // Combine parents' output power flags.
1787 combinedPowerFlags
= 0;
1789 iter
= getParentIterator(gIOPowerPlane
);
1791 while ((next
= iter
->getNextObject())) {
1792 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
1793 if (connection
== whichParent
) {
1794 combinedPowerFlags
|= parentPowerFlags
;
1796 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1803 // If our initial change has yet to occur, then defer the power change
1804 // until after the power domain has completed its power transition.
1806 if (fControllingDriver
&& !fInitialPowerChange
) {
1807 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1808 combinedPowerFlags
);
1810 if (parentChangeFlags
& kIOPMDomainPowerDrop
) {
1811 // fMaxPowerState set a limit on self-initiated power changes.
1812 // Update it before a parent power drop.
1813 fMaxPowerState
= maxPowerState
;
1816 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1817 // to avoid propagating the root change flags if any service must
1818 // change power state due to root's will-change notification.
1819 // Root does not change power state for kIOPMSynchronize.
1821 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1822 (parentChangeFlags
& kIOPMSynchronize
);
1824 result
= startPowerChange(
1825 /* flags */ myChangeFlags
,
1826 /* power state */ maxPowerState
,
1827 /* domain flags */ combinedPowerFlags
,
1828 /* connection */ whichParent
,
1829 /* parent flags */ parentPowerFlags
);
1832 // If parent is dropping power, immediately update the parent's
1833 // capability flags. Any future merging of parent(s) combined
1834 // power flags should account for this power drop.
1836 if (parentChangeFlags
& kIOPMDomainPowerDrop
) {
1837 setParentInfo(parentPowerFlags
, whichParent
, true);
1840 // Parent is expecting an ACK from us. If we did not embark on a state
1841 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1842 // still required to issue an ACK to our parent.
1844 if (IOPMAckImplied
== result
) {
1846 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1849 parent
->acknowledgePowerChange( whichParent
);
1855 // Drop the retain from notifyChild().
1857 whichParent
->release();
1862 //*********************************************************************************
1863 // [deprecated] powerDomainDidChangeTo
1865 // Called by the power-hierarchy parent after the power state of the power domain
1866 // has settled at a new level.
1867 // We enqueue a parent power-change to our queue of power changes.
1868 // This may or may not cause us to change power, depending on what
1869 // kind of change is occuring in the domain.
1870 //*********************************************************************************
1873 IOService::powerDomainDidChangeTo(
1874 IOPMPowerFlags newPowerFlags
,
1875 IOPowerConnection
* whichParent
)
1878 return kIOReturnUnsupported
;
1880 #endif /* !__LP64__ */
1882 //*********************************************************************************
1883 // [private] handlePowerDomainDidChangeTo
1884 //*********************************************************************************
1887 IOService::handlePowerDomainDidChangeTo( IOPMRequest
* request
)
1889 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1890 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1891 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1892 IOPMPowerChangeFlags myChangeFlags
;
1893 IOPMPowerStateIndex maxPowerState
;
1894 IOPMPowerStateIndex initialDesire
= kPowerStateZero
;
1895 bool computeDesire
= false;
1896 bool desireChanged
= false;
1897 bool savedParentsKnowState
;
1898 IOReturn result
= IOPMAckImplied
;
1900 PM_ASSERT_IN_GATE();
1901 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1903 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck()) {
1904 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1908 savedParentsKnowState
= fParentsKnowState
;
1910 setParentInfo(parentPowerFlags
, whichParent
, true);
1912 if (fControllingDriver
) {
1913 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1914 fParentsCurrentPowerFlags
);
1916 if ((parentChangeFlags
& kIOPMDomainPowerDrop
) == 0) {
1917 // fMaxPowerState set a limit on self-initiated power changes.
1918 // Update it after a parent power rise.
1919 fMaxPowerState
= maxPowerState
;
1922 if (fInitialPowerChange
) {
1923 computeDesire
= true;
1924 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1925 fParentsCurrentPowerFlags
);
1926 } else if (parentChangeFlags
& kIOPMRootChangeUp
) {
1927 if (fAdvisoryTickleUsed
) {
1928 // On system wake, re-compute the desired power state since
1929 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1930 // which is an input to computeDesiredState(). This is not
1931 // necessary for a dark wake because powerChangeDone() will
1932 // handle the dark to full wake case, but it does no harm.
1934 desireChanged
= true;
1937 if (fResetPowerStateOnWake
) {
1938 // Query the driver for the desired power state on system wake.
1939 // Default implementation returns the lowest power state.
1941 IOPMPowerStateIndex wakePowerState
=
1942 fControllingDriver
->initialPowerStateForDomainState(
1943 kIOPMRootDomainState
| kIOPMPowerOn
);
1945 // fDesiredPowerState was adjusted before going to sleep
1946 // with fDeviceDesire at min.
1948 if (StateOrder(wakePowerState
) > StateOrder(fDesiredPowerState
)) {
1949 // Must schedule a power adjustment if we changed the
1950 // device desire. That will update the desired domain
1951 // power on the parent power connection and ping the
1952 // power parent if necessary.
1954 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1955 desireChanged
= true;
1960 if (computeDesire
|| desireChanged
) {
1961 computeDesiredState(initialDesire
, false);
1964 // Absorb and propagate parent's broadcast flags
1965 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1966 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1968 result
= startPowerChange(
1969 /* flags */ myChangeFlags
,
1970 /* power state */ maxPowerState
,
1971 /* domain flags */ fParentsCurrentPowerFlags
,
1972 /* connection */ whichParent
,
1973 /* parent flags */ 0);
1976 // Parent is expecting an ACK from us. If we did not embark on a state
1977 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1978 // still required to issue an ACK to our parent.
1980 if (IOPMAckImplied
== result
) {
1982 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1985 parent
->acknowledgePowerChange( whichParent
);
1990 // If the parent registers its power driver late, then this is the
1991 // first opportunity to tell our parent about our desire. Or if the
1992 // child's desire changed during a parent change notify.
1994 if (fControllingDriver
&&
1995 ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
)) {
1996 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
1997 getName(), fParentsKnowState
);
1998 requestDomainPower( fDesiredPowerState
);
2002 // Drop the retain from notifyChild().
2004 whichParent
->release();
2008 //*********************************************************************************
2009 // [private] setParentInfo
2011 // Set our connection data for one specific parent, and then combine all the parent
2013 //*********************************************************************************
2016 IOService::setParentInfo(
2017 IOPMPowerFlags newPowerFlags
,
2018 IOPowerConnection
* whichParent
,
2023 IOPowerConnection
* conn
;
2025 PM_ASSERT_IN_GATE();
2027 // set our connection data
2028 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
2029 whichParent
->setParentKnowsState(knowsState
);
2031 // recompute our parent info
2032 fParentsCurrentPowerFlags
= 0;
2033 fParentsKnowState
= true;
2035 iter
= getParentIterator(gIOPowerPlane
);
2037 while ((next
= iter
->getNextObject())) {
2038 if ((conn
= OSDynamicCast(IOPowerConnection
, next
))) {
2039 fParentsKnowState
&= conn
->parentKnowsState();
2040 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
2047 //******************************************************************************
2048 // [private] trackSystemSleepPreventers
2049 //******************************************************************************
2052 IOService::trackSystemSleepPreventers(
2053 IOPMPowerStateIndex oldPowerState
,
2054 IOPMPowerStateIndex newPowerState
,
2055 IOPMPowerChangeFlags changeFlags __unused
)
2057 IOPMPowerFlags oldCapability
, newCapability
;
2059 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2060 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2061 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2062 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2064 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
) {
2067 if (oldCapability
== newCapability
) {
2071 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
) {
2072 bool enablePrevention
= ((oldCapability
& kIOPMPreventIdleSleep
) == 0);
2073 bool idleCancelAllowed
= getPMRootDomain()->updatePreventIdleSleepList(
2074 this, enablePrevention
);
2075 #if SUPPORT_IDLE_CANCEL
2076 if (idleCancelAllowed
&& enablePrevention
) {
2077 IOPMRequest
* cancelRequest
;
2079 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2080 if (cancelRequest
) {
2081 submitPMRequest( cancelRequest
);
2087 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
) {
2088 getPMRootDomain()->updatePreventSystemSleepList(this,
2089 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2093 //*********************************************************************************
2094 // [public] requestPowerDomainState
2096 // Called on a power parent when a child's power requirement changes.
2097 //*********************************************************************************
2100 IOService::requestPowerDomainState(
2101 IOPMPowerFlags childRequestPowerFlags
,
2102 IOPowerConnection
* childConnection
,
2103 unsigned long specification
)
2105 IOPMPowerStateIndex order
, powerState
;
2106 IOPMPowerFlags outputPowerFlags
;
2108 IOPMRequest
* subRequest
;
2109 bool adjustPower
= false;
2112 return IOPMNotYetInitialized
;
2115 if (gIOPMWorkLoop
->onThread() == false) {
2116 PM_LOG("%s::requestPowerDomainState\n", getName());
2117 return kIOReturnSuccess
;
2120 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2122 if (!isChild(childConnection
, gIOPowerPlane
)) {
2123 return kIOReturnNotAttached
;
2126 if (!fControllingDriver
|| !fNumberOfPowerStates
) {
2127 return kIOReturnNotReady
;
2130 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2133 // Remove flags from child request which we can't possibly supply
2134 childRequestPowerFlags
&= fMergedOutputPowerFlags
;
2136 // Merge in the power flags contributed by this power parent
2137 // at its current or impending power state.
2139 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2140 if (fMachineState
!= kIOPM_Finished
) {
2141 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
) {
2142 // Use the lower power state when dropping power.
2143 // Must be careful since a power drop can be cancelled
2144 // from the following states:
2145 // - kIOPM_OurChangeTellClientsPowerDown
2146 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2148 // The child must not wait for this parent to raise power
2149 // if the power drop was cancelled. The solution is to cancel
2150 // the power drop if possible, then schedule an adjustment to
2151 // re-evaluate the parent's power state.
2153 // Root domain is excluded to avoid idle sleep issues. And allow
2154 // root domain children to pop up when system is going to sleep.
2156 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2157 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)) {
2158 fDoNotPowerDown
= true; // cancel power drop
2159 adjustPower
= true;// schedule an adjustment
2160 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2161 getName(), fMachineState
, child
->getName());
2163 // Beyond cancellation point, report the impending state.
2165 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2167 } else if (IS_POWER_RISE
) {
2168 // When raising power, must report the output power flags from
2169 // child's perspective. A child power request may arrive while
2170 // parent is transitioning upwards. If a request arrives after
2171 // setParentInfo() has already recorded the output power flags
2172 // for the next power state, then using the power supplied by
2173 // fCurrentPowerState is incorrect, and might cause the child
2174 // to wait when it should not.
2176 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2179 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2181 // Map child's requested power flags to one of our power state.
2183 for (order
= 0; order
< fNumberOfPowerStates
; order
++) {
2184 powerState
= fPowerStates
[order
].stateOrderToIndex
;
2185 if ((fPowerStates
[powerState
].outputPowerFlags
& childRequestPowerFlags
)
2186 == childRequestPowerFlags
) {
2190 if (order
>= fNumberOfPowerStates
) {
2191 powerState
= kPowerStateZero
;
2194 // Conditions that warrants a power adjustment on this parent.
2195 // Adjust power will also propagate any changes to the child's
2196 // prevent idle/sleep flags towards the root domain.
2198 if (!childConnection
->childHasRequestedPower() ||
2199 (powerState
!= childConnection
->getDesiredDomainState())) {
2203 #if ENABLE_DEBUG_LOGS
2205 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2206 getName(), child
->getName(),
2207 !childConnection
->childHasRequestedPower(),
2208 (uint32_t) childConnection
->getDesiredDomainState(),
2209 (uint32_t) powerState
);
2213 // Record the child's desires on the connection.
2214 childConnection
->setChildHasRequestedPower();
2215 childConnection
->setDesiredDomainState( powerState
);
2217 // Schedule a request to re-evaluate all children desires and
2218 // adjust power state. Submit a request if one wasn't pending,
2219 // or if the current request is part of a call tree.
2221 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2222 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest())) {
2223 subRequest
= acquirePMRequest(
2224 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2226 submitPMRequest( subRequest
);
2227 fAdjustPowerScheduled
= true;
2231 return kIOReturnSuccess
;
2234 //*********************************************************************************
2235 // [public] temporaryPowerClampOn
2237 // A power domain wants to clamp its power on till it has children which
2238 // will thendetermine the power domain state.
2240 // We enter the highest state until addPowerChild is called.
2241 //*********************************************************************************
2244 IOService::temporaryPowerClampOn( void )
2246 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2249 //*********************************************************************************
2250 // [public] makeUsable
2252 // Some client of our device is asking that we become usable. Although
2253 // this has not come from a subclassed device object, treat it exactly
2254 // as if it had. In this way, subsequent requests for lower power from
2255 // a subclassed device object will pre-empt this request.
2257 // We treat this as a subclass object request to switch to the
2258 // highest power state.
2259 //*********************************************************************************
2262 IOService::makeUsable( void )
2264 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2265 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2268 //*********************************************************************************
2269 // [public] currentCapability
2270 //*********************************************************************************
2273 IOService::currentCapability( void )
2276 return IOPMNotPowerManaged
;
2279 return fCurrentCapabilityFlags
;
2282 //*********************************************************************************
2283 // [public] changePowerStateTo
2285 // Called by our power-controlling driver to change power state. The new desired
2286 // power state is computed and compared against the current power state. If those
2287 // power states differ, then a power state change is initiated.
2288 //*********************************************************************************
2291 IOService::changePowerStateTo( unsigned long ordinal
)
2293 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2294 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2297 //*********************************************************************************
2298 // [protected] changePowerStateToPriv
2300 // Called by our driver subclass to change power state. The new desired power
2301 // state is computed and compared against the current power state. If those
2302 // power states differ, then a power state change is initiated.
2303 //*********************************************************************************
2306 IOService::changePowerStateToPriv( unsigned long ordinal
)
2308 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2309 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2312 //*********************************************************************************
2313 // [public] changePowerStateWithOverrideTo
2315 // Called by our driver subclass to change power state. The new desired power
2316 // state is computed and compared against the current power state. If those
2317 // power states differ, then a power state change is initiated.
2318 // Override enforced - Children and Driver desires are ignored.
2319 //*********************************************************************************
2322 IOService::changePowerStateWithOverrideTo( IOPMPowerStateIndex ordinal
,
2323 IOPMRequestTag tag
)
2325 IOPMRequest
* request
;
2328 return kIOPMNotYetInitialized
;
2331 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2333 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2335 return kIOReturnNoMemory
;
2338 gIOPMPowerClientDevice
->retain();
2339 request
->fRequestTag
= tag
;
2340 request
->fArg0
= (void *) ordinal
;
2341 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2345 request
->installCompletionAction( action
, target
, param
);
2349 // Prevent needless downwards power transitions by clamping power
2350 // until the scheduled request is executed.
2352 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
)) {
2353 fTempClampPowerState
= StateMax(fTempClampPowerState
, ordinal
);
2355 fOverrideMaxPowerState
= ordinal
;
2356 request
->fArg2
= (void *) (uintptr_t) true;
2359 submitPMRequest( request
);
2363 //*********************************************************************************
2364 // [public] changePowerStateForRootDomain
2366 // Adjust the root domain's power desire on the target
2367 //*********************************************************************************
2370 IOService::changePowerStateForRootDomain( IOPMPowerStateIndex ordinal
)
2372 OUR_PMLog(kPMLogChangeStateForRootDomain
, ordinal
, 0);
2373 return requestPowerState( gIOPMPowerClientRootDomain
, ordinal
);
2376 //*********************************************************************************
2377 // [public for PMRD] quiescePowerTree
2379 // For root domain to issue a request to quiesce the power tree.
2380 // Supplied callback invoked upon completion.
2381 //*********************************************************************************
2384 IOService::quiescePowerTree(
2385 void * target
, IOPMCompletionAction action
, void * param
)
2387 IOPMRequest
* request
;
2390 return kIOPMNotYetInitialized
;
2392 if (!target
|| !action
) {
2393 return kIOReturnBadArgument
;
2396 OUR_PMLog(kPMLogQuiescePowerTree
, 0, 0);
2398 // Target the root node instead of root domain. This is to avoid blocking
2399 // the quiesce request behind an existing root domain request in the work
2400 // queue. Root parent and root domain requests in the work queue must not
2401 // block the completion of the quiesce request.
2403 request
= acquirePMRequest(gIOPMRootNode
, kIOPMRequestTypeQuiescePowerTree
);
2405 return kIOReturnNoMemory
;
2408 request
->installCompletionAction(target
, action
, param
);
2410 // Submit through the normal request flow. This will make sure any request
2411 // already in the request queue will get pushed over to the work queue for
2412 // execution. Any request submitted after this request may not be serviced.
2414 submitPMRequest( request
);
2415 return kIOReturnSuccess
;
2418 //*********************************************************************************
2419 // [private] requestPowerState
2420 //*********************************************************************************
2423 IOService::requestPowerState(
2424 const OSSymbol
* client
,
2427 IOPMRequest
* request
;
2430 return kIOReturnBadArgument
;
2433 return kIOPMNotYetInitialized
;
2436 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2438 return kIOReturnNoMemory
;
2442 request
->fArg0
= (void *)(uintptr_t) state
;
2443 request
->fArg1
= (void *) client
;
2447 request
->installCompletionAction( action
, target
, param
);
2451 // Prevent needless downwards power transitions by clamping power
2452 // until the scheduled request is executed.
2454 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
)) {
2455 fTempClampPowerState
= StateMax(fTempClampPowerState
, state
);
2457 request
->fArg2
= (void *) (uintptr_t) true;
2460 submitPMRequest( request
);
2464 //*********************************************************************************
2465 // [private] handleRequestPowerState
2466 //*********************************************************************************
2469 IOService::handleRequestPowerState( IOPMRequest
* request
)
2471 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2472 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2474 PM_ASSERT_IN_GATE();
2475 if (request
->fArg2
) {
2476 assert(fTempClampCount
!= 0);
2477 if (fTempClampCount
) {
2480 if (!fTempClampCount
) {
2481 fTempClampPowerState
= kPowerStateZero
;
2485 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
)) {
2486 state
= fHighestPowerState
;
2489 // The power suppression due to changePowerStateWithOverrideTo() expires
2490 // upon the next "device" power request - changePowerStateToPriv().
2492 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2493 (client
== gIOPMPowerClientDevice
)) {
2494 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2497 if ((state
== kPowerStateZero
) &&
2498 (client
!= gIOPMPowerClientDevice
) &&
2499 (client
!= gIOPMPowerClientDriver
) &&
2500 (client
!= gIOPMPowerClientChildProxy
)) {
2501 removePowerClient(client
);
2503 updatePowerClient(client
, state
);
2510 //*********************************************************************************
2511 // [private] Helper functions to update/remove power clients.
2512 //*********************************************************************************
2515 IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2517 IOPMPowerStateIndex oldPowerState
= kPowerStateZero
;
2519 if (!fPowerClients
) {
2520 fPowerClients
= OSDictionary::withCapacity(4);
2522 if (fPowerClients
&& client
) {
2523 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2525 oldPowerState
= num
->unsigned32BitValue();
2526 num
->setValue(powerState
);
2528 num
= OSNumber::withNumber(powerState
, 32);
2530 fPowerClients
->setObject(client
, num
);
2535 PM_ACTION_3(actionUpdatePowerClient
, client
, oldPowerState
, powerState
);
2540 IOService::removePowerClient( const OSSymbol
* client
)
2542 if (fPowerClients
&& client
) {
2543 fPowerClients
->removeObject(client
);
2548 IOService::getPowerStateForClient( const OSSymbol
* client
)
2550 uint32_t powerState
= kPowerStateZero
;
2552 if (fPowerClients
&& client
) {
2553 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2555 powerState
= num
->unsigned32BitValue();
2561 //*********************************************************************************
2562 // [protected] powerOverrideOnPriv
2563 //*********************************************************************************
2566 IOService::powerOverrideOnPriv( void )
2568 IOPMRequest
* request
;
2571 return IOPMNotYetInitialized
;
2574 if (gIOPMWorkLoop
->inGate()) {
2575 fDeviceOverrideEnabled
= true;
2579 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2581 return kIOReturnNoMemory
;
2584 submitPMRequest( request
);
2588 //*********************************************************************************
2589 // [protected] powerOverrideOffPriv
2590 //*********************************************************************************
2593 IOService::powerOverrideOffPriv( void )
2595 IOPMRequest
* request
;
2598 return IOPMNotYetInitialized
;
2601 if (gIOPMWorkLoop
->inGate()) {
2602 fDeviceOverrideEnabled
= false;
2606 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2608 return kIOReturnNoMemory
;
2611 submitPMRequest( request
);
2615 //*********************************************************************************
2616 // [private] handlePowerOverrideChanged
2617 //*********************************************************************************
2620 IOService::handlePowerOverrideChanged( IOPMRequest
* request
)
2622 PM_ASSERT_IN_GATE();
2623 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
) {
2624 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2625 fDeviceOverrideEnabled
= true;
2627 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2628 fDeviceOverrideEnabled
= false;
2634 //*********************************************************************************
2635 // [private] computeDesiredState
2636 //*********************************************************************************
2639 IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2643 IOPowerConnection
* connection
;
2644 uint32_t desiredState
= kPowerStateZero
;
2645 uint32_t newPowerState
= kPowerStateZero
;
2646 bool hasChildren
= false;
2648 // Desired power state is always 0 without a controlling driver.
2650 if (!fNumberOfPowerStates
) {
2651 fDesiredPowerState
= kPowerStateZero
;
2655 // Examine the children's desired power state.
2657 iter
= getChildIterator(gIOPowerPlane
);
2659 while ((next
= iter
->getNextObject())) {
2660 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
2661 if (connection
->getReadyFlag() == false) {
2662 PM_LOG3("[%s] %s: connection not ready\n",
2663 getName(), __FUNCTION__
);
2666 if (connection
->childHasRequestedPower()) {
2669 desiredState
= StateMax(connection
->getDesiredDomainState(), desiredState
);
2675 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2677 removePowerClient(gIOPMPowerClientChildren
);
2680 // Iterate through all power clients to determine the min power state.
2682 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2684 const OSSymbol
* client
;
2685 while ((client
= (const OSSymbol
*) iter
->getNextObject())) {
2686 // Ignore child and driver when override is in effect.
2687 if ((fDeviceOverrideEnabled
||
2688 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2689 ((client
== gIOPMPowerClientChildren
) ||
2690 (client
== gIOPMPowerClientDriver
))) {
2694 // Ignore child proxy when children are present.
2695 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
)) {
2699 // Advisory tickles are irrelevant unless system is in full wake
2700 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2701 !gIOPMAdvisoryTickleEnabled
) {
2705 desiredState
= getPowerStateForClient(client
);
2706 assert(desiredState
< fNumberOfPowerStates
);
2708 desiredState
, client
->getCStringNoCopy());
2710 newPowerState
= StateMax(newPowerState
, desiredState
);
2712 if (client
== gIOPMPowerClientDevice
) {
2713 fDeviceDesire
= desiredState
;
2719 // Factor in the temporary power desires.
2721 newPowerState
= StateMax(newPowerState
, localClamp
);
2722 newPowerState
= StateMax(newPowerState
, fTempClampPowerState
);
2724 // Limit check against max power override.
2726 newPowerState
= StateMin(newPowerState
, fOverrideMaxPowerState
);
2728 // Limit check against number of power states.
2730 if (newPowerState
>= fNumberOfPowerStates
) {
2731 newPowerState
= fHighestPowerState
;
2734 fDesiredPowerState
= newPowerState
;
2736 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2737 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2738 (uint32_t) fCurrentPowerState
, newPowerState
);
2741 // Restart idle timer if possible when device desire has increased.
2742 // Or if an advisory desire exists.
2744 if (fIdleTimerPeriod
&& fIdleTimerStopped
) {
2748 // Invalidate cached tickle power state when desires change, and not
2749 // due to a tickle request. In case the driver has requested a lower
2750 // power state, but the tickle is caching a higher power state which
2751 // will drop future tickles until the cached value is lowered or in-
2752 // validated. The invalidation must occur before the power transition
2753 // to avoid dropping a necessary tickle.
2755 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2756 (fActivityTicklePowerState
!= kInvalidTicklePowerState
)) {
2757 IOLockLock(fActivityLock
);
2758 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2759 IOLockUnlock(fActivityLock
);
2764 //*********************************************************************************
2765 // [public] currentPowerConsumption
2767 //*********************************************************************************
2770 IOService::currentPowerConsumption( void )
2773 return kIOPMUnknown
;
2776 return fCurrentPowerConsumption
;
2779 //*********************************************************************************
2780 // [deprecated] getPMworkloop
2781 //*********************************************************************************
2785 IOService::getPMworkloop( void )
2787 return gIOPMWorkLoop
;
2793 //*********************************************************************************
2794 // Power Parent/Children Applier
2795 //*********************************************************************************
2798 applyToPowerChildren(
2799 IOService
* service
,
2800 IOServiceApplierFunction applier
,
2802 IOOptionBits options
)
2804 PM_ASSERT_IN_GATE();
2806 IORegistryEntry
* entry
;
2807 IORegistryIterator
* iter
;
2808 IOPowerConnection
* connection
;
2811 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2813 while ((entry
= iter
->getNextObject())) {
2814 // Get child of IOPowerConnection objects
2815 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
))) {
2816 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2818 (*applier
)(child
, context
);
2829 IOService
* service
,
2830 IOServiceApplierFunction applier
,
2832 IOOptionBits options
)
2834 PM_ASSERT_IN_GATE();
2836 IORegistryEntry
* entry
;
2837 IORegistryIterator
* iter
;
2838 IOPowerConnection
* connection
;
2841 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2842 options
| kIORegistryIterateParents
);
2844 while ((entry
= iter
->getNextObject())) {
2845 // Get child of IOPowerConnection objects
2846 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
))) {
2847 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2849 (*applier
)(parent
, context
);
2858 #endif /* NOT_YET */
2861 // MARK: Activity Tickle & Idle Timer
2864 IOService::setAdvisoryTickleEnable( bool enable
)
2866 gIOPMAdvisoryTickleEnabled
= enable
;
2869 //*********************************************************************************
2870 // [public] activityTickle
2872 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2873 // flag to be set, and the device state checked. If the device has been
2874 // powered down, it is powered up again.
2875 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2876 // should be intercepted by a subclass.
2877 //*********************************************************************************
2880 IOService::activityTickle( unsigned long type
, unsigned long stateNumber
)
2882 IOPMRequest
* request
;
2883 bool noPowerChange
= true;
2884 uint32_t tickleFlags
;
2887 return true; // no power change
2889 if ((type
== kIOPMSuperclassPolicy1
) && StateOrder(stateNumber
)) {
2890 IOLockLock(fActivityLock
);
2892 // Record device activity for the idle timer handler.
2894 fDeviceWasActive
= true;
2895 fActivityTickleCount
++;
2896 clock_get_uptime(&fDeviceActiveTimestamp
);
2898 PM_ACTION_0(actionActivityTickle
);
2900 // Record the last tickle power state.
2901 // This helps to filter out redundant tickles as
2902 // this function may be called from the data path.
2904 if ((fActivityTicklePowerState
== kInvalidTicklePowerState
)
2905 || StateOrder(fActivityTicklePowerState
) < StateOrder(stateNumber
)) {
2906 fActivityTicklePowerState
= stateNumber
;
2907 noPowerChange
= false;
2909 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2910 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2912 request
->fArg0
= (void *) stateNumber
;
2913 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2914 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2915 submitPMRequest(request
);
2919 IOLockUnlock(fActivityLock
);
2920 } else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2921 ((stateNumber
= fDeviceUsablePowerState
) != kPowerStateZero
)) {
2922 IOLockLock(fActivityLock
);
2924 fAdvisoryTickled
= true;
2926 if (fAdvisoryTicklePowerState
!= stateNumber
) {
2927 fAdvisoryTicklePowerState
= stateNumber
;
2928 noPowerChange
= false;
2930 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2931 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 // Returns false if the activityTickle might cause a transition to a
2944 // higher powered state, true otherwise.
2946 return noPowerChange
;
2949 //*********************************************************************************
2950 // [private] handleActivityTickle
2951 //*********************************************************************************
2954 IOService::handleActivityTickle( IOPMRequest
* request
)
2956 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2957 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
2958 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
2959 bool adjustPower
= false;
2961 PM_ASSERT_IN_GATE();
2962 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
)) {
2963 // Drivers that don't want power restored on wake will drop any
2964 // tickles that pre-dates the current system wake. The model is
2965 // that each wake is a fresh start, with power state depressed
2966 // until a new tickle or an explicit power up request from the
2967 // driver. It is possible for the PM work loop to enter the
2968 // system sleep path with tickle requests queued.
2973 if (tickleFlags
& kTickleTypeActivity
) {
2974 IOPMPowerStateIndex deviceDesireOrder
= StateOrder(fDeviceDesire
);
2975 uint32_t idleTimerGeneration
= ticklePowerState
; // kTickleTypePowerDrop
2977 if (tickleFlags
& kTickleTypePowerRise
) {
2978 if ((StateOrder(ticklePowerState
) > deviceDesireOrder
) &&
2979 (ticklePowerState
< fNumberOfPowerStates
)) {
2980 fIdleTimerMinPowerState
= ticklePowerState
;
2981 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2984 } else if ((deviceDesireOrder
> StateOrder(fIdleTimerMinPowerState
)) &&
2985 (idleTimerGeneration
== fIdleTimerGeneration
)) {
2986 // Power drop due to idle timer expiration.
2987 // Do not allow idle timer to reduce power below tickle power.
2988 // This prevents the idle timer from decreasing the device desire
2989 // to zero and cancelling the effect of a pre-sleep tickle when
2990 // system wakes up to doze state, while the device is unable to
2991 // raise its power state to satisfy the tickle.
2993 deviceDesireOrder
--;
2994 if (deviceDesireOrder
< fNumberOfPowerStates
) {
2995 ticklePowerState
= fPowerStates
[deviceDesireOrder
].stateOrderToIndex
;
2996 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
3000 } else { // advisory tickle
3001 if (tickleFlags
& kTickleTypePowerRise
) {
3002 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
3003 (ticklePowerState
< fNumberOfPowerStates
)) {
3004 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
3005 fHasAdvisoryDesire
= true;
3006 fAdvisoryTickleUsed
= true;
3009 IOLockLock(fActivityLock
);
3010 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3011 IOLockUnlock(fActivityLock
);
3013 } else if (fHasAdvisoryDesire
) {
3014 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
3015 fHasAdvisoryDesire
= false;
3025 //******************************************************************************
3026 // [public] setIdleTimerPeriod
3028 // A subclass policy-maker is using our standard idleness detection service.
3029 // Start the idle timer. Period is in seconds.
3030 //******************************************************************************
3033 IOService::setIdleTimerPeriod( unsigned long period
)
3036 return IOPMNotYetInitialized
;
3039 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
3041 IOPMRequest
* request
=
3042 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
3044 return kIOReturnNoMemory
;
3047 request
->fArg0
= (void *) period
;
3048 submitPMRequest( request
);
3050 return kIOReturnSuccess
;
3054 IOService::setIgnoreIdleTimer( bool ignore
)
3057 return IOPMNotYetInitialized
;
3060 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
3062 IOPMRequest
* request
=
3063 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
3065 return kIOReturnNoMemory
;
3068 request
->fArg0
= (void *) ignore
;
3069 submitPMRequest( request
);
3071 return kIOReturnSuccess
;
3074 //******************************************************************************
3075 // [public] nextIdleTimeout
3077 // Returns how many "seconds from now" the device should idle into its
3078 // next lowest power state.
3079 //******************************************************************************
3082 IOService::nextIdleTimeout(
3083 AbsoluteTime currentTime
,
3084 AbsoluteTime lastActivity
,
3085 unsigned int powerState
)
3092 // Calculate time difference using funky macro from clock.h.
3093 delta
= currentTime
;
3094 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
3096 // Figure it in seconds.
3097 absolutetime_to_nanoseconds(delta
, &delta_ns
);
3098 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
3100 // Be paranoid about delta somehow exceeding timer period.
3101 if (delta_secs
< (int) fIdleTimerPeriod
) {
3102 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3104 delay_secs
= (int) fIdleTimerPeriod
;
3107 return (SInt32
)delay_secs
;
3110 //*********************************************************************************
3111 // [public] start_PM_idle_timer
3112 //*********************************************************************************
3115 IOService::start_PM_idle_timer( void )
3117 static const int maxTimeout
= 100000;
3118 static const int minTimeout
= 1;
3119 AbsoluteTime uptime
, deadline
;
3123 if (!initialized
|| !fIdleTimerPeriod
) {
3127 IOLockLock(fActivityLock
);
3129 clock_get_uptime(&uptime
);
3131 // Subclasses may modify idle sleep algorithm
3132 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3134 // Check for out-of range responses
3135 if (idle_in
> maxTimeout
) {
3136 // use standard implementation
3137 idle_in
= IOService::nextIdleTimeout(uptime
,
3138 fDeviceActiveTimestamp
,
3139 fCurrentPowerState
);
3140 } else if (idle_in
< minTimeout
) {
3141 idle_in
= fIdleTimerPeriod
;
3144 IOLockUnlock(fActivityLock
);
3146 fNextIdleTimerPeriod
= idle_in
;
3147 fIdleTimerStartTime
= uptime
;
3150 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3151 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3152 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3158 //*********************************************************************************
3159 // [private] restartIdleTimer
3160 //*********************************************************************************
3163 IOService::restartIdleTimer( void )
3165 if (fDeviceDesire
!= kPowerStateZero
) {
3166 fIdleTimerStopped
= false;
3167 fActivityTickleCount
= 0;
3168 start_PM_idle_timer();
3169 } else if (fHasAdvisoryDesire
) {
3170 fIdleTimerStopped
= false;
3171 start_PM_idle_timer();
3173 fIdleTimerStopped
= true;
3177 //*********************************************************************************
3178 // idle_timer_expired
3179 //*********************************************************************************
3183 thread_call_param_t arg0
, thread_call_param_t arg1
)
3185 IOService
* me
= (IOService
*) arg0
;
3187 if (gIOPMWorkLoop
) {
3188 gIOPMWorkLoop
->runAction(
3189 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3190 &IOService::idleTimerExpired
),
3197 //*********************************************************************************
3198 // [private] idleTimerExpired
3200 // The idle timer has expired. If there has been activity since the last
3201 // expiration, just restart the timer and return. If there has not been
3202 // activity, switch to the next lower power state and restart the timer.
3203 //*********************************************************************************
3206 IOService::idleTimerExpired( void )
3208 IOPMRequest
* request
;
3209 bool restartTimer
= true;
3210 uint32_t tickleFlags
;
3212 if (!initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3213 fLockedFlags
.PMStop
) {
3217 fIdleTimerStartTime
= 0;
3219 IOLockLock(fActivityLock
);
3221 // Check for device activity (tickles) over last timer period.
3223 if (fDeviceWasActive
) {
3224 // Device was active - do not drop power, restart timer.
3225 fDeviceWasActive
= false;
3226 } else if (!fIdleTimerIgnored
) {
3227 // No device activity - drop power state by one level.
3228 // Decrement the cached tickle power state when possible.
3229 // This value may be kInvalidTicklePowerState before activityTickle()
3230 // is called, but the power drop request must be issued regardless.
3232 if ((fActivityTicklePowerState
!= kInvalidTicklePowerState
) &&
3233 (fActivityTicklePowerState
!= kPowerStateZero
)) {
3234 fActivityTicklePowerState
--;
3237 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3238 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3240 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3241 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3242 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3243 submitPMRequest( request
);
3245 // Do not restart timer until after the tickle request has been
3248 restartTimer
= false;
3252 if (fAdvisoryTickled
) {
3253 fAdvisoryTickled
= false;
3254 } else if (fHasAdvisoryDesire
) {
3255 // Want new tickles to turn into pm request after we drop the lock
3256 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3258 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3259 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3261 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3262 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3263 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3264 submitPMRequest( request
);
3266 // Do not restart timer until after the tickle request has been
3269 restartTimer
= false;
3273 IOLockUnlock(fActivityLock
);
3276 start_PM_idle_timer();
3281 //*********************************************************************************
3282 // [deprecated] PM_idle_timer_expiration
3283 //*********************************************************************************
3286 IOService::PM_idle_timer_expiration( void )
3290 //*********************************************************************************
3291 // [deprecated] command_received
3292 //*********************************************************************************
3295 IOService::command_received( void *statePtr
, void *, void *, void * )
3298 #endif /* !__LP64__ */
3300 //*********************************************************************************
3301 // [public] setAggressiveness
3303 // Pass on the input parameters to all power domain children. All those which are
3304 // power domains will pass it on to their children, etc.
3305 //*********************************************************************************
3308 IOService::setAggressiveness( unsigned long type
, unsigned long newLevel
)
3310 return kIOReturnSuccess
;
3313 //*********************************************************************************
3314 // [public] getAggressiveness
3316 // Called by the user client.
3317 //*********************************************************************************
3320 IOService::getAggressiveness( unsigned long type
, unsigned long * currentLevel
)
3322 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3325 return kIOReturnNotReady
;
3328 return rootDomain
->getAggressiveness( type
, currentLevel
);
3331 //*********************************************************************************
3332 // [public] getPowerState
3334 //*********************************************************************************
3337 IOService::getPowerState( void )
3340 return kPowerStateZero
;
3343 return fCurrentPowerState
;
3347 //*********************************************************************************
3348 // [deprecated] systemWake
3350 // Pass this to all power domain children. All those which are
3351 // power domains will pass it on to their children, etc.
3352 //*********************************************************************************
3355 IOService::systemWake( void )
3359 IOPowerConnection
* connection
;
3360 IOService
* theChild
;
3362 iter
= getChildIterator(gIOPowerPlane
);
3364 while ((next
= iter
->getNextObject())) {
3365 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
3366 if (connection
->getReadyFlag() == false) {
3367 PM_LOG3("[%s] %s: connection not ready\n",
3368 getName(), __FUNCTION__
);
3372 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3374 theChild
->systemWake();
3375 theChild
->release();
3382 if (fControllingDriver
!= NULL
) {
3383 if (fControllingDriver
->didYouWakeSystem()) {
3391 //*********************************************************************************
3392 // [deprecated] temperatureCriticalForZone
3393 //*********************************************************************************
3396 IOService::temperatureCriticalForZone( IOService
* whichZone
)
3398 IOService
* theParent
;
3401 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3403 if (inPlane(gIOPowerPlane
) && !IS_PM_ROOT
) {
3404 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3406 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3409 theParent
->temperatureCriticalForZone(whichZone
);
3410 theParent
->release();
3416 #endif /* !__LP64__ */
3419 // MARK: Power Change (Common)
3421 //*********************************************************************************
3422 // [private] startPowerChange
3424 // All power state changes starts here.
3425 //*********************************************************************************
3428 IOService::startPowerChange(
3429 IOPMPowerChangeFlags changeFlags
,
3430 IOPMPowerStateIndex powerState
,
3431 IOPMPowerFlags domainFlags
,
3432 IOPowerConnection
* parentConnection
,
3433 IOPMPowerFlags parentFlags
)
3435 PM_ASSERT_IN_GATE();
3436 assert( fMachineState
== kIOPM_Finished
);
3437 assert( powerState
< fNumberOfPowerStates
);
3439 if (powerState
>= fNumberOfPowerStates
) {
3440 return IOPMAckImplied
;
3443 fIsPreChange
= true;
3444 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3446 if (changeFlags
& kIOPMExpireIdleTimer
) {
3447 // Root domain requested removal of tickle influence
3448 if (StateOrder(fDeviceDesire
) > StateOrder(powerState
)) {
3449 // Reset device desire down to the clamped power state
3450 updatePowerClient(gIOPMPowerClientDevice
, powerState
);
3451 computeDesiredState(kPowerStateZero
, true);
3453 // Invalidate tickle cache so the next tickle will issue a request
3454 IOLockLock(fActivityLock
);
3455 fDeviceWasActive
= false;
3456 fActivityTicklePowerState
= kInvalidTicklePowerState
;
3457 IOLockUnlock(fActivityLock
);
3459 fIdleTimerMinPowerState
= kPowerStateZero
;
3463 // Root domain's override handler may cancel the power change by
3464 // setting the kIOPMNotDone flag.
3466 if (changeFlags
& kIOPMNotDone
) {
3467 return IOPMAckImplied
;
3470 // Forks to either Driver or Parent initiated power change paths.
3472 fHeadNoteChangeFlags
= changeFlags
;
3473 fHeadNotePowerState
= powerState
;
3474 fHeadNotePowerArrayEntry
= &fPowerStates
[powerState
];
3475 fHeadNoteParentConnection
= NULL
;
3477 if (changeFlags
& kIOPMSelfInitiated
) {
3478 if (changeFlags
& kIOPMSynchronize
) {
3485 assert(changeFlags
& kIOPMParentInitiated
);
3486 fHeadNoteDomainFlags
= domainFlags
;
3487 fHeadNoteParentFlags
= parentFlags
;
3488 fHeadNoteParentConnection
= parentConnection
;
3489 return ParentChangeStart();
3493 //*********************************************************************************
3494 // [private] notifyInterestedDrivers
3495 //*********************************************************************************
3498 IOService::notifyInterestedDrivers( void )
3500 IOPMinformee
* informee
;
3501 IOPMinformeeList
* list
= fInterestedDrivers
;
3502 DriverCallParam
* param
;
3504 IOItemCount skipCnt
= 0;
3506 PM_ASSERT_IN_GATE();
3507 assert( fDriverCallParamCount
== 0 );
3508 assert( fHeadNotePendingAcks
== 0 );
3510 fHeadNotePendingAcks
= 0;
3512 count
= list
->numberOfItems();
3514 goto done
; // no interested drivers
3516 // Allocate an array of interested drivers and their return values
3517 // for the callout thread. Everything else is still "owned" by the
3518 // PM work loop, which can run to process acknowledgePowerChange()
3521 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3522 if (count
> fDriverCallParamSlots
) {
3523 if (fDriverCallParamSlots
) {
3524 assert(fDriverCallParamPtr
);
3525 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3526 fDriverCallParamPtr
= 0;
3527 fDriverCallParamSlots
= 0;
3530 param
= IONew(DriverCallParam
, count
);
3532 goto done
; // no memory
3534 fDriverCallParamPtr
= (void *) param
;
3535 fDriverCallParamSlots
= count
;
3538 informee
= list
->firstInList();
3540 for (IOItemCount i
= 0; i
< count
; i
++) {
3541 if (fInitialSetPowerState
|| (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)) {
3542 // Skip notifying self, if 'kIOPMInitialDeviceState' is set and
3543 // this is the initial power state change
3544 if ((this == informee
->whatObject
) &&
3545 (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)) {
3550 informee
->timer
= -1;
3551 param
[i
].Target
= informee
;
3553 informee
= list
->nextInList( informee
);
3560 fDriverCallParamCount
= count
;
3561 fHeadNotePendingAcks
= count
;
3563 // Block state machine and wait for callout completion.
3564 assert(!fDriverCallBusy
);
3565 fDriverCallBusy
= true;
3566 thread_call_enter( fDriverCallEntry
);
3570 // Return false if there are no interested drivers or could not schedule
3571 // callout thread due to error.
3575 //*********************************************************************************
3576 // [private] notifyInterestedDriversDone
3577 //*********************************************************************************
3580 IOService::notifyInterestedDriversDone( void )
3582 IOPMinformee
* informee
;
3584 DriverCallParam
* param
;
3588 PM_ASSERT_IN_GATE();
3589 assert( fDriverCallBusy
== false );
3590 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3592 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3593 count
= fDriverCallParamCount
;
3595 if (param
&& count
) {
3596 for (IOItemCount i
= 0; i
< count
; i
++, param
++) {
3597 informee
= (IOPMinformee
*) param
->Target
;
3598 result
= param
->Result
;
3600 if ((result
== IOPMAckImplied
) || (result
< 0)) {
3601 // Interested driver return IOPMAckImplied.
3602 // If informee timer is zero, it must have de-registered
3603 // interest during the thread callout. That also drops
3604 // the pending ack count.
3606 if (fHeadNotePendingAcks
&& informee
->timer
) {
3607 fHeadNotePendingAcks
--;
3610 informee
->timer
= 0;
3611 } else if (informee
->timer
) {
3612 assert(informee
->timer
== -1);
3614 // Driver has not acked, and has returned a positive result.
3615 // Enforce a minimum permissible timeout value.
3616 // Make the min value large enough so timeout is less likely
3617 // to occur if a driver misinterpreted that the return value
3618 // should be in microsecond units. And make it large enough
3619 // to be noticeable if a driver neglects to ack.
3621 if (result
< kMinAckTimeoutTicks
) {
3622 result
= kMinAckTimeoutTicks
;
3625 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3626 if (result
> maxTimeout
) {
3627 maxTimeout
= result
;
3630 // else, child has already acked or driver has removed interest,
3631 // and head_note_pendingAcks decremented.
3632 // informee may have been removed from the interested drivers list,
3633 // thus the informee must be retained across the callout.
3635 informee
->release();
3638 fDriverCallParamCount
= 0;
3640 if (fHeadNotePendingAcks
) {
3641 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3643 getPMRootDomain()->reset_watchdog_timer(this, maxTimeout
/ USEC_PER_SEC
+ 1);
3647 MS_POP(); // pop the machine state passed to notifyAll()
3649 // If interest acks are outstanding, block the state machine until
3650 // fHeadNotePendingAcks drops to zero before notifying root domain.
3651 // Otherwise notify root domain directly.
3653 if (!fHeadNotePendingAcks
) {
3656 MS_PUSH(fMachineState
);
3657 fMachineState
= kIOPM_NotifyChildrenStart
;
3661 //*********************************************************************************
3662 // [private] notifyRootDomain
3663 //*********************************************************************************
3666 IOService::notifyRootDomain( void )
3668 assert( fDriverCallBusy
== false );
3670 // Only for root domain in the will-change phase
3671 if (!IS_ROOT_DOMAIN
|| (fMachineState
!= kIOPM_OurChangeSetPowerState
)) {
3676 MS_PUSH(fMachineState
); // push notifyAll() machine state
3677 fMachineState
= kIOPM_DriverThreadCallDone
;
3679 // Call IOPMrootDomain::willNotifyPowerChildren() on a thread call
3680 // to avoid a deadlock.
3681 fDriverCallReason
= kRootDomainInformPreChange
;
3682 fDriverCallBusy
= true;
3683 thread_call_enter( fDriverCallEntry
);
3687 IOService::notifyRootDomainDone( void )
3689 assert( fDriverCallBusy
== false );
3690 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3692 MS_POP(); // pop notifyAll() machine state
3696 //*********************************************************************************
3697 // [private] notifyChildren
3698 //*********************************************************************************
3701 IOService::notifyChildren( void )
3705 IOPowerConnection
* connection
;
3706 OSArray
* children
= 0;
3707 IOPMrootDomain
* rootDomain
;
3708 bool delayNotify
= false;
3710 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3711 (IS_POWER_DROP
== fIsPreChange
) &&
3712 ((rootDomain
= getPMRootDomain()) == this)) {
3713 rootDomain
->tracePoint( IS_POWER_DROP
?
3714 kIOPMTracePointSleepPowerPlaneDrivers
:
3715 kIOPMTracePointWakePowerPlaneDrivers
);
3718 if (fStrictTreeOrder
) {
3719 children
= OSArray::withCapacity(8);
3722 // Sum child power consumption in notifyChild()
3723 fHeadNotePowerArrayEntry
->staticPower
= 0;
3725 iter
= getChildIterator(gIOPowerPlane
);
3727 while ((next
= iter
->getNextObject())) {
3728 if ((connection
= OSDynamicCast(IOPowerConnection
, next
))) {
3729 if (connection
->getReadyFlag() == false) {
3730 PM_LOG3("[%s] %s: connection not ready\n",
3731 getName(), __FUNCTION__
);
3735 // Mechanism to postpone the did-change notification to
3736 // certain power children to order those children last.
3737 // Cannot be used together with strict tree ordering.
3739 if (!fIsPreChange
&&
3740 connection
->delayChildNotification
&&
3741 getPMRootDomain()->shouldDelayChildNotification(this)) {
3743 children
= OSArray::withCapacity(8);
3749 children
->setObject( connection
);
3754 if (!delayNotify
&& children
) {
3755 children
->setObject( connection
);
3757 notifyChild( connection
);
3764 if (children
&& (children
->getCount() == 0)) {
3765 children
->release();
3769 assert(fNotifyChildArray
== 0);
3770 fNotifyChildArray
= children
;
3771 MS_PUSH(fMachineState
);
3774 // Block until all non-delayed children have acked their
3775 // notification. Then notify the remaining delayed child
3776 // in the array. This is used to hold off graphics child
3777 // notification while the rest of the system powers up.
3778 // If a hid tickle arrives during this time, the delayed
3779 // children are immediately notified and root domain will
3780 // not clamp power for dark wake.
3782 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3783 PM_LOG2("%s: %d children in delayed array\n",
3784 getName(), children
->getCount());
3786 // Child array created to support strict notification order.
3787 // Notify children in the array one at a time.
3789 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3794 //*********************************************************************************
3795 // [private] notifyChildrenOrdered
3796 //*********************************************************************************
3799 IOService::notifyChildrenOrdered( void )
3801 PM_ASSERT_IN_GATE();
3802 assert(fNotifyChildArray
);
3803 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3805 // Notify one child, wait for it to ack, then repeat for next child.
3806 // This is a workaround for some drivers with multiple instances at
3807 // the same branch in the power tree, but the driver is slow to power
3808 // up unless the tree ordering is observed. Problem observed only on
3809 // system wake, not on system sleep.
3811 // We have the ability to power off in reverse child index order.
3812 // That works nicely on some machines, but not on all HW configs.
3814 if (fNotifyChildArray
->getCount()) {
3815 IOPowerConnection
* connection
;
3816 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3817 notifyChild( connection
);
3818 fNotifyChildArray
->removeObject(0);
3820 fNotifyChildArray
->release();
3821 fNotifyChildArray
= 0;
3823 MS_POP(); // pushed by notifyChildren()
3827 //*********************************************************************************
3828 // [private] notifyChildrenDelayed
3829 //*********************************************************************************
3832 IOService::notifyChildrenDelayed( void )
3834 IOPowerConnection
* connection
;
3836 PM_ASSERT_IN_GATE();
3837 assert(fNotifyChildArray
);
3838 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3840 // Wait after all non-delayed children and interested drivers have ack'ed,
3841 // then notify all delayed children. If notify delay is canceled, child
3842 // acks may be outstanding with PM blocked on fHeadNotePendingAcks != 0.
3843 // But the handling for either case is identical.
3845 for (int i
= 0;; i
++) {
3846 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3851 notifyChild( connection
);
3854 PM_LOG2("%s: notified delayed children\n", getName());
3855 fNotifyChildArray
->release();
3856 fNotifyChildArray
= 0;
3858 MS_POP(); // pushed by notifyChildren()
3861 //*********************************************************************************
3862 // [private] notifyAll
3863 //*********************************************************************************
3866 IOService::notifyAll( uint32_t nextMS
)
3868 // Save the machine state to be restored by notifyInterestedDriversDone()
3870 PM_ASSERT_IN_GATE();
3872 fMachineState
= kIOPM_DriverThreadCallDone
;
3873 fDriverCallReason
= fIsPreChange
?
3874 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3876 if (!notifyInterestedDrivers()) {
3877 notifyInterestedDriversDone();
3880 return IOPMWillAckLater
;
3883 //*********************************************************************************
3884 // [private, static] pmDriverCallout
3886 // Thread call context
3887 //*********************************************************************************
3890 IOService::actionDriverCalloutDone(
3892 void * arg0
, void * arg1
,
3893 void * arg2
, void * arg3
)
3895 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3897 assert( fDriverCallBusy
);
3898 fDriverCallBusy
= false;
3900 assert(gIOPMWorkQueue
);
3901 gIOPMWorkQueue
->signalWorkAvailable();
3903 return kIOReturnSuccess
;
3907 IOService::pmDriverCallout( IOService
* from
)
3910 switch (from
->fDriverCallReason
) {
3911 case kDriverCallSetPowerState
:
3912 from
->driverSetPowerState();
3915 case kDriverCallInformPreChange
:
3916 case kDriverCallInformPostChange
:
3917 from
->driverInformPowerChange();
3920 case kRootDomainInformPreChange
:
3921 getPMRootDomain()->willNotifyPowerChildren(from
->fHeadNotePowerState
);
3925 panic("IOService::pmDriverCallout bad machine state %x",
3926 from
->fDriverCallReason
);
3929 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3931 /* arg0 */ (void *) from
->pwrMgt
);
3934 //*********************************************************************************
3935 // [private] driverSetPowerState
3937 // Thread call context
3938 //*********************************************************************************
3941 IOService::driverSetPowerState( void )
3943 IOPMPowerStateIndex powerState
;
3944 DriverCallParam
* param
;
3945 IOPMDriverCallEntry callEntry
;
3948 uint32_t oldPowerState
= getPowerState();
3950 assert( fDriverCallBusy
);
3951 assert( fDriverCallParamPtr
);
3952 assert( fDriverCallParamCount
== 1 );
3954 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3955 powerState
= fHeadNotePowerState
;
3957 callEntry
.callMethod
= OSMemberFunctionCast(const void *, fControllingDriver
, &IOService::setPowerState
);
3958 if (assertPMDriverCall(&callEntry
)) {
3959 OUR_PMLogFuncStart(kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3960 start_spindump_timer("SetState");
3961 clock_get_uptime(&fDriverCallStartTime
);
3962 result
= fControllingDriver
->setPowerState( powerState
, this );
3963 clock_get_uptime(&end
);
3964 stop_spindump_timer();
3965 OUR_PMLogFuncEnd(kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3967 deassertPMDriverCall(&callEntry
);
3969 // Record the most recent max power state residency timings.
3970 // Use with DeviceActiveTimestamp to diagnose tickle issues.
3971 if (powerState
== fHighestPowerState
) {
3972 fMaxPowerStateEntryTime
= end
;
3973 } else if (oldPowerState
== fHighestPowerState
) {
3974 fMaxPowerStateExitTime
= end
;
3978 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
3979 fName
, OBFUSCATE(this), fCurrentPowerState
, powerState
, result
);
3983 if ((result
== IOPMAckImplied
) || (result
< 0)) {
3986 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
3987 absolutetime_to_nanoseconds(end
, &nsec
);
3988 if (nsec
> LOG_SETPOWER_TIMES
) {
3989 getPMRootDomain()->pmStatsRecordApplicationResponse(
3990 gIOPMStatsDriverPSChangeSlow
,
3991 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
3996 result
= kIOPMAckImplied
;
3999 param
->Result
= result
;
4002 //*********************************************************************************
4003 // [private] driverInformPowerChange
4005 // Thread call context
4006 //*********************************************************************************
4009 IOService::driverInformPowerChange( void )
4011 IOPMinformee
* informee
;
4013 DriverCallParam
* param
;
4014 IOPMDriverCallEntry callEntry
;
4015 IOPMPowerFlags powerFlags
;
4016 IOPMPowerStateIndex powerState
;
4021 assert( fDriverCallBusy
);
4022 assert( fDriverCallParamPtr
);
4023 assert( fDriverCallParamCount
);
4025 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4026 count
= fDriverCallParamCount
;
4028 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4029 powerState
= fHeadNotePowerState
;
4031 for (IOItemCount i
= 0; i
< count
; i
++) {
4032 informee
= (IOPMinformee
*) param
->Target
;
4033 driver
= informee
->whatObject
;
4035 if (fDriverCallReason
== kDriverCallInformPreChange
) {
4036 callEntry
.callMethod
= OSMemberFunctionCast(const void *, driver
, &IOService::powerStateWillChangeTo
);
4038 callEntry
.callMethod
= OSMemberFunctionCast(const void *, driver
, &IOService::powerStateDidChangeTo
);
4040 if (assertPMDriverCall(&callEntry
, 0, informee
)) {
4041 if (fDriverCallReason
== kDriverCallInformPreChange
) {
4042 OUR_PMLogFuncStart(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
4043 start_spindump_timer("WillChange");
4044 clock_get_uptime(&informee
->startTime
);
4045 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
4046 clock_get_uptime(&end
);
4047 stop_spindump_timer();
4048 OUR_PMLogFuncEnd(kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
4050 OUR_PMLogFuncStart(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
4051 start_spindump_timer("DidChange");
4052 clock_get_uptime(&informee
->startTime
);
4053 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
4054 clock_get_uptime(&end
);
4055 stop_spindump_timer();
4056 OUR_PMLogFuncEnd(kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
4059 deassertPMDriverCall(&callEntry
);
4062 if ((result
== IOPMAckImplied
) || (result
< 0)) {
4065 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
4066 absolutetime_to_nanoseconds(end
, &nsec
);
4067 if (nsec
> LOG_SETPOWER_TIMES
) {
4068 getPMRootDomain()->pmStatsRecordApplicationResponse(
4069 gIOPMStatsDriverPSChangeSlow
, driver
->getName(),
4070 fDriverCallReason
, NS_TO_MS(nsec
), driver
->getRegistryEntryID(),
4075 result
= kIOPMAckImplied
;
4078 param
->Result
= result
;
4083 //*********************************************************************************
4084 // [private] notifyChild
4086 // Notify a power domain child of an upcoming power change.
4087 // If the object acknowledges the current change, we return TRUE.
4088 //*********************************************************************************
4091 IOService::notifyChild( IOPowerConnection
* theNub
)
4093 IOReturn ret
= IOPMAckImplied
;
4094 unsigned long childPower
;
4095 IOService
* theChild
;
4096 IOPMRequest
* childRequest
;
4097 IOPMPowerChangeFlags requestArg2
;
4100 PM_ASSERT_IN_GATE();
4101 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
4106 // Unless the child handles the notification immediately and returns
4107 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4108 fHeadNotePendingAcks
++;
4109 theNub
->setAwaitingAck(true);
4111 requestArg2
= fHeadNoteChangeFlags
;
4112 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
)) {
4113 requestArg2
|= kIOPMDomainPowerDrop
;
4116 requestType
= fIsPreChange
?
4117 kIOPMRequestTypePowerDomainWillChange
:
4118 kIOPMRequestTypePowerDomainDidChange
;
4120 childRequest
= acquirePMRequest( theChild
, requestType
);
4123 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4124 childRequest
->fArg1
= (void *) theNub
;
4125 childRequest
->fArg2
= (void *)(uintptr_t) requestArg2
;
4126 theChild
->submitPMRequest( childRequest
);
4127 ret
= IOPMWillAckLater
;
4129 ret
= IOPMAckImplied
;
4130 fHeadNotePendingAcks
--;
4131 theNub
->setAwaitingAck(false);
4132 childPower
= theChild
->currentPowerConsumption();
4133 if (childPower
== kIOPMUnknown
) {
4134 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4136 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
) {
4137 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4142 theChild
->release();
4143 return IOPMAckImplied
== ret
;
4146 //*********************************************************************************
4147 // [private] notifyControllingDriver
4148 //*********************************************************************************
4151 IOService::notifyControllingDriver( void )
4153 DriverCallParam
* param
;
4155 PM_ASSERT_IN_GATE();
4156 assert( fDriverCallParamCount
== 0 );
4157 assert( fControllingDriver
);
4159 if (fInitialSetPowerState
) {
4160 fInitialSetPowerState
= false;
4161 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4163 // Driver specified flag to skip the inital setPowerState()
4164 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
) {
4169 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4171 param
= IONew(DriverCallParam
, 1);
4173 return false; // no memory
4175 fDriverCallParamPtr
= (void *) param
;
4176 fDriverCallParamSlots
= 1;
4179 param
->Target
= fControllingDriver
;
4180 fDriverCallParamCount
= 1;
4183 // Block state machine and wait for callout completion.
4184 assert(!fDriverCallBusy
);
4185 fDriverCallBusy
= true;
4186 thread_call_enter( fDriverCallEntry
);
4191 //*********************************************************************************
4192 // [private] notifyControllingDriverDone
4193 //*********************************************************************************
4196 IOService::notifyControllingDriverDone( void )
4198 DriverCallParam
* param
;
4201 PM_ASSERT_IN_GATE();
4202 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4204 assert( fDriverCallBusy
== false );
4205 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4207 if (param
&& fDriverCallParamCount
) {
4208 assert(fDriverCallParamCount
== 1);
4210 // the return value from setPowerState()
4211 result
= param
->Result
;
4213 if ((result
== IOPMAckImplied
) || (result
< 0)) {
4215 } else if (fDriverTimer
) {
4216 assert(fDriverTimer
== -1);
4218 // Driver has not acked, and has returned a positive result.
4219 // Enforce a minimum permissible timeout value.
4220 // Make the min value large enough so timeout is less likely
4221 // to occur if a driver misinterpreted that the return value
4222 // should be in microsecond units. And make it large enough
4223 // to be noticeable if a driver neglects to ack.
4225 if (result
< kMinAckTimeoutTicks
) {
4226 result
= kMinAckTimeoutTicks
;
4229 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4231 // else, child has already acked and driver_timer reset to 0.
4233 fDriverCallParamCount
= 0;
4236 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4238 getPMRootDomain()->reset_watchdog_timer(this, result
/ USEC_PER_SEC
+ 1);
4242 MS_POP(); // pushed by OurChangeSetPowerState()
4243 fIsPreChange
= false;
4246 //*********************************************************************************
4247 // [private] all_done
4249 // A power change is done.
4250 //*********************************************************************************
4253 IOService::all_done( void )
4255 IOPMPowerStateIndex prevPowerState
;
4256 const IOPMPSEntry
* powerStatePtr
;
4257 IOPMDriverCallEntry callEntry
;
4258 uint32_t prevMachineState
= fMachineState
;
4259 bool actionCalled
= false;
4262 fMachineState
= kIOPM_Finished
;
4264 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4265 ((prevMachineState
== kIOPM_Finished
) ||
4266 (prevMachineState
== kIOPM_SyncFinish
))) {
4267 // Sync operation and no power change occurred.
4268 // Do not inform driver and clients about this request completion,
4269 // except for the originator (root domain).
4271 PM_ACTION_2(actionPowerChangeDone
,
4272 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4274 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
) {
4275 powerChangeDone(fCurrentPowerState
);
4276 } else if (fAdvisoryTickleUsed
) {
4277 // Not root domain and advisory tickle target.
4278 // Re-adjust power after power tree sync at the 'did' pass
4279 // to recompute desire and adjust power state between dark
4280 // and full wake transitions. Root domain is responsible
4281 // for calling setAdvisoryTickleEnable() before starting
4282 // the kIOPMSynchronize power change.
4284 if (!fAdjustPowerScheduled
&&
4285 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
)) {
4286 IOPMRequest
* request
;
4287 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4289 submitPMRequest( request
);
4290 fAdjustPowerScheduled
= true;
4299 if (fHeadNoteChangeFlags
& kIOPMSelfInitiated
) {
4300 // power state changed
4301 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0) {
4302 trackSystemSleepPreventers(
4303 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4305 // we changed, tell our parent
4306 requestDomainPower(fHeadNotePowerState
);
4308 // yes, did power raise?
4309 if (StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
)) {
4310 // yes, inform clients and apps
4311 tellChangeUp(fHeadNotePowerState
);
4313 prevPowerState
= fCurrentPowerState
;
4315 fCurrentPowerState
= fHeadNotePowerState
;
4318 ts
= mach_absolute_time();
4319 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4323 fPMVars
->myCurrentState
= fCurrentPowerState
;
4325 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4326 PM_ACTION_2(actionPowerChangeDone
,
4327 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4328 actionCalled
= true;
4330 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4331 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4332 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
) {
4333 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4336 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
) {
4337 // Bump tickle generation count once the entire tree is down
4338 gIOPMTickleGeneration
++;
4341 // inform subclass policy-maker
4342 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4343 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
)) {
4344 powerChangeDone(prevPowerState
);
4345 deassertPMDriverCall(&callEntry
);
4347 } else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
) {
4348 // changePowerStateWithOverrideTo() was cancelled
4349 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4353 // parent-initiated power change
4354 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
4355 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
) {
4356 ParentChangeRootChangeDown();
4359 // power state changed
4360 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0) {
4361 trackSystemSleepPreventers(
4362 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4365 if (StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
)) {
4366 // yes, inform clients and apps
4367 tellChangeUp(fHeadNotePowerState
);
4370 prevPowerState
= fCurrentPowerState
;
4371 fCurrentPowerState
= fHeadNotePowerState
;
4374 ts
= mach_absolute_time();
4375 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4379 fPMVars
->myCurrentState
= fCurrentPowerState
;
4382 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4383 PM_ACTION_2(actionPowerChangeDone
,
4384 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4385 actionCalled
= true;
4387 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4388 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4389 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
) {
4390 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4393 // inform subclass policy-maker
4394 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4395 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
)) {
4396 powerChangeDone(prevPowerState
);
4397 deassertPMDriverCall(&callEntry
);
4402 // When power rises enough to satisfy the tickle's desire for more power,
4403 // the condition preventing idle-timer from dropping power is removed.
4405 if (StateOrder(fCurrentPowerState
) >= StateOrder(fIdleTimerMinPowerState
)) {
4406 fIdleTimerMinPowerState
= kPowerStateZero
;
4409 if (!actionCalled
) {
4410 PM_ACTION_2(actionPowerChangeDone
,
4411 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4416 // MARK: Power Change Initiated by Driver
4418 //*********************************************************************************
4419 // [private] OurChangeStart
4421 // Begin the processing of a power change initiated by us.
4422 //*********************************************************************************
4425 IOService::OurChangeStart( void )
4427 PM_ASSERT_IN_GATE();
4428 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4430 // fMaxPowerState is our maximum possible power state based on the current
4431 // power state of our parents. If we are trying to raise power beyond the
4432 // maximum, send an async request for more power to all parents.
4434 if (!IS_PM_ROOT
&& (StateOrder(fMaxPowerState
) < StateOrder(fHeadNotePowerState
))) {
4435 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4436 requestDomainPower(fHeadNotePowerState
);
4441 // Redundant power changes skips to the end of the state machine.
4443 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
)) {
4447 fInitialPowerChange
= false;
4449 // Change started, but may not complete...
4450 // Can be canceled (power drop) or deferred (power rise).
4452 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4454 // Two separate paths, depending if power is being raised or lowered.
4455 // Lowering power is subject to approval by clients of this service.
4457 if (IS_POWER_DROP
) {
4458 fDoNotPowerDown
= false;
4460 // Ask for persmission to drop power state
4461 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4462 fOutOfBandParameter
= kNotifyApps
;
4463 askChangeDown(fHeadNotePowerState
);
4465 // This service is raising power and parents are able to support the
4466 // new power state. However a parent may have already committed to
4467 // drop power, which might force this object to temporarily drop power.
4468 // This results in "oscillations" before the state machines converge
4469 // to a steady state.
4471 // To prevent this, a child must make a power reservation against all
4472 // parents before raising power. If the reservation fails, indicating
4473 // that the child will be unable to sustain the higher power state,
4474 // then the child will signal the parent to adjust power, and the child
4475 // will defer its power change.
4479 // Reserve parent power necessary to achieve fHeadNotePowerState.
4480 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4481 if (ret
!= kIOReturnSuccess
) {
4482 // Reservation failed, defer power rise.
4483 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4488 OurChangeTellCapabilityWillChange();
4492 //*********************************************************************************
4493 // [private] requestDomainPowerApplier
4495 // Call requestPowerDomainState() on all power parents.
4496 //*********************************************************************************
4498 struct IOPMRequestDomainPowerContext
{
4499 IOService
* child
; // the requesting child
4500 IOPMPowerFlags requestPowerFlags
;// power flags requested by child
4504 requestDomainPowerApplier(
4505 IORegistryEntry
* entry
,
4508 IOPowerConnection
* connection
;
4510 IOPMRequestDomainPowerContext
* context
;
4512 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0) {
4515 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4521 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4523 if (connection
->parentKnowsState() && connection
->getReadyFlag()) {
4524 parent
->requestPowerDomainState(
4525 context
->requestPowerFlags
,
4533 //*********************************************************************************
4534 // [private] requestDomainPower
4536 // Called by a power child to broadcast its desired power state to all parents.
4537 // If the child self-initiates a power change, it must call this function to
4538 // allow its parents to adjust power state.
4539 //*********************************************************************************
4542 IOService::requestDomainPower(
4543 IOPMPowerStateIndex ourPowerState
,
4544 IOOptionBits options
)
4546 IOPMPowerFlags requestPowerFlags
;
4547 IOPMPowerStateIndex maxPowerState
;
4548 IOPMRequestDomainPowerContext context
;
4550 PM_ASSERT_IN_GATE();
4551 assert(ourPowerState
< fNumberOfPowerStates
);
4552 if (ourPowerState
>= fNumberOfPowerStates
) {
4553 return kIOReturnBadArgument
;
4556 return kIOReturnSuccess
;
4559 // Fetch our input power flags for the requested power state.
4560 // Parent request is stated in terms of required power flags.
4562 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4564 // Disregard the "previous request" for power reservation.
4566 if (((options
& kReserveDomainPower
) == 0) &&
4567 (fPreviousRequestPowerFlags
== requestPowerFlags
)) {
4568 // skip if domain already knows our requirements
4571 fPreviousRequestPowerFlags
= requestPowerFlags
;
4573 // The results will be collected by fHeadNoteDomainTargetFlags
4574 context
.child
= this;
4575 context
.requestPowerFlags
= requestPowerFlags
;
4576 fHeadNoteDomainTargetFlags
= 0;
4577 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4579 if (options
& kReserveDomainPower
) {
4580 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4581 fHeadNoteDomainTargetFlags
);
4583 if (StateOrder(maxPowerState
) < StateOrder(ourPowerState
)) {
4584 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4586 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4587 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4588 return kIOReturnNoPower
;
4593 return kIOReturnSuccess
;
4596 //*********************************************************************************
4597 // [private] OurSyncStart
4598 //*********************************************************************************
4601 IOService::OurSyncStart( void )
4603 PM_ASSERT_IN_GATE();
4605 if (fInitialPowerChange
) {
4609 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4611 if (fHeadNoteChangeFlags
& kIOPMNotDone
) {
4616 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
) {
4617 fDoNotPowerDown
= false;
4619 // Ask for permission to drop power state
4620 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4621 fOutOfBandParameter
= kNotifyApps
;
4622 askChangeDown(fHeadNotePowerState
);
4624 // Only inform capability app and clients.
4625 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4629 //*********************************************************************************
4630 // [private] OurChangeTellClientsPowerDown
4632 // All applications and kernel clients have acknowledged our permission to drop
4633 // power. Here we notify them that we will lower the power and wait for acks.
4634 //*********************************************************************************
4637 IOService::OurChangeTellClientsPowerDown( void )
4639 if (!IS_ROOT_DOMAIN
) {
4640 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4642 fMachineState
= kIOPM_OurChangeTellUserPMPolicyPowerDown
;
4644 tellChangeDown1(fHeadNotePowerState
);
4647 //*********************************************************************************
4648 // [private] OurChangeTellUserPMPolicyPowerDown
4650 // All applications and kernel clients have acknowledged our permission to drop
4651 // power. Here we notify power management policy in user-space and wait for acks
4652 // one last time before we lower power
4653 //*********************************************************************************
4655 IOService::OurChangeTellUserPMPolicyPowerDown( void )
4657 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4658 fOutOfBandParameter
= kNotifyApps
;
4660 tellClientsWithResponse(kIOPMMessageLastCallBeforeSleep
);
4663 //*********************************************************************************
4664 // [private] OurChangeTellPriorityClientsPowerDown
4666 // All applications and kernel clients have acknowledged our intention to drop
4667 // power. Here we notify "priority" clients that we are lowering power.
4668 //*********************************************************************************
4671 IOService::OurChangeTellPriorityClientsPowerDown( void )
4673 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4674 tellChangeDown2(fHeadNotePowerState
);
4677 //*********************************************************************************
4678 // [private] OurChangeTellCapabilityWillChange
4680 // Extra stage for root domain to notify apps and drivers about the
4681 // system capability change when raising power state.
4682 //*********************************************************************************
4685 IOService::OurChangeTellCapabilityWillChange( void )
4687 if (!IS_ROOT_DOMAIN
) {
4688 return OurChangeNotifyInterestedDriversWillChange();
4691 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4694 //*********************************************************************************
4695 // [private] OurChangeNotifyInterestedDriversWillChange
4697 // All applications and kernel clients have acknowledged our power state change.
4698 // Here we notify interested drivers pre-change.
4699 //*********************************************************************************
4702 IOService::OurChangeNotifyInterestedDriversWillChange( void )
4704 IOPMrootDomain
* rootDomain
;
4705 if ((rootDomain
= getPMRootDomain()) == this) {
4706 if (IS_POWER_DROP
) {
4707 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4709 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4713 notifyAll( kIOPM_OurChangeSetPowerState
);
4716 //*********************************************************************************
4717 // [private] OurChangeSetPowerState
4719 // Instruct our controlling driver to program the hardware for the power state
4720 // change. Wait for async completions.
4721 //*********************************************************************************
4724 IOService::OurChangeSetPowerState( void )
4726 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4727 fMachineState
= kIOPM_DriverThreadCallDone
;
4728 fDriverCallReason
= kDriverCallSetPowerState
;
4730 if (notifyControllingDriver() == false) {
4731 notifyControllingDriverDone();
4735 //*********************************************************************************
4736 // [private] OurChangeWaitForPowerSettle
4738 // Our controlling driver has completed the power state change we initiated.
4739 // Wait for the driver specified settle time to expire.
4740 //*********************************************************************************
4743 IOService::OurChangeWaitForPowerSettle( void )
4745 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4749 //*********************************************************************************
4750 // [private] OurChangeNotifyInterestedDriversDidChange
4752 // Power has settled on a power change we initiated. Here we notify
4753 // all our interested drivers post-change.
4754 //*********************************************************************************
4757 IOService::OurChangeNotifyInterestedDriversDidChange( void )
4759 IOPMrootDomain
* rootDomain
;
4760 if ((rootDomain
= getPMRootDomain()) == this) {
4761 rootDomain
->tracePoint( IS_POWER_DROP
?
4762 kIOPMTracePointSleepDidChangeInterests
:
4763 kIOPMTracePointWakeDidChangeInterests
);
4766 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4769 //*********************************************************************************
4770 // [private] OurChangeTellCapabilityDidChange
4772 // For root domain to notify capability power-change.
4773 //*********************************************************************************
4776 IOService::OurChangeTellCapabilityDidChange( void )
4778 if (!IS_ROOT_DOMAIN
) {
4779 return OurChangeFinish();
4782 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4783 kIOPMTracePointSleepCapabilityClients
:
4784 kIOPMTracePointWakeCapabilityClients
);
4786 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4789 //*********************************************************************************
4790 // [private] OurChangeFinish
4792 // Done with this self-induced power state change.
4793 //*********************************************************************************
4796 IOService::OurChangeFinish( void )
4802 // MARK: Power Change Initiated by Parent
4804 //*********************************************************************************
4805 // [private] ParentChangeStart
4807 // Here we begin the processing of a power change initiated by our parent.
4808 //*********************************************************************************
4811 IOService::ParentChangeStart( void )
4813 PM_ASSERT_IN_GATE();
4814 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4816 // Root power domain has transitioned to its max power state
4817 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4818 (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) {
4819 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4820 if (fIdleTimerPeriod
&& fIdleTimerStopped
) {
4825 // Power domain is forcing us to lower power
4826 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
)) {
4827 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4829 // Tell apps and kernel clients
4830 fInitialPowerChange
= false;
4831 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4832 tellChangeDown1(fHeadNotePowerState
);
4833 return IOPMWillAckLater
;
4836 // Power domain is allowing us to raise power up to fHeadNotePowerState
4837 if (StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
)) {
4838 if (StateOrder(fDesiredPowerState
) > StateOrder(fCurrentPowerState
)) {
4839 if (StateOrder(fDesiredPowerState
) < StateOrder(fHeadNotePowerState
)) {
4840 // We power up, but not all the way
4841 fHeadNotePowerState
= fDesiredPowerState
;
4842 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4843 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4846 // We don't need to change
4847 fHeadNotePowerState
= fCurrentPowerState
;
4848 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4849 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4853 if (fHeadNoteChangeFlags
& kIOPMDomainDidChange
) {
4854 if (StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
)) {
4855 PM_ACTION_2(actionPowerChangeStart
,
4856 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4858 // Parent did change up - start our change up
4859 fInitialPowerChange
= false;
4860 ParentChangeTellCapabilityWillChange();
4861 return IOPMWillAckLater
;
4862 } else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
) {
4863 // No need to change power state, but broadcast change
4865 fMachineState
= kIOPM_SyncNotifyDidChange
;
4866 fDriverCallReason
= kDriverCallInformPreChange
;
4867 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4869 return IOPMWillAckLater
;
4873 // No power state change necessary
4874 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4877 return IOPMAckImplied
;
4880 //******************************************************************************
4881 // [private] ParentChangeRootChangeDown
4883 // Root domain has finished the transition to the system sleep state. And all
4884 // drivers in the power plane should have powered down. Cancel the idle timer,
4885 // and also reset the device desire for those drivers that don't want power
4886 // automatically restored on wake.
4887 //******************************************************************************
4890 IOService::ParentChangeRootChangeDown( void )
4892 // Always stop the idle timer before root power down
4893 if (fIdleTimerPeriod
&& !fIdleTimerStopped
) {
4894 fIdleTimerStopped
= true;
4895 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
)) {
4900 if (fResetPowerStateOnWake
) {
4901 // Reset device desire down to the lowest power state.
4902 // Advisory tickle desire is intentionally untouched since
4903 // it has no effect until system is promoted to full wake.
4905 if (fDeviceDesire
!= kPowerStateZero
) {
4906 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4907 computeDesiredState(kPowerStateZero
, true);
4908 requestDomainPower( fDesiredPowerState
);
4909 PM_LOG1("%s: tickle desire removed\n", fName
);
4912 // Invalidate tickle cache so the next tickle will issue a request
4913 IOLockLock(fActivityLock
);
4914 fDeviceWasActive
= false;
4915 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4916 IOLockUnlock(fActivityLock
);
4918 fIdleTimerMinPowerState
= kPowerStateZero
;
4919 } else if (fAdvisoryTickleUsed
) {
4920 // Less aggressive mechanism to accelerate idle timer expiration
4921 // before system sleep. May not always allow the driver to wake
4922 // up from system sleep in the min power state.
4926 bool dropTickleDesire
= false;
4928 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
4929 (fIdleTimerMinPowerState
== kPowerStateZero
) &&
4930 (fDeviceDesire
!= kPowerStateZero
)) {
4931 IOLockLock(fActivityLock
);
4933 if (!fDeviceWasActive
) {
4934 // No tickles since the last idle timer expiration.
4935 // Safe to drop the device desire to zero.
4936 dropTickleDesire
= true;
4938 // Was tickled since the last idle timer expiration,
4939 // but not in the last minute.
4940 clock_get_uptime(&now
);
4941 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
4942 absolutetime_to_nanoseconds(now
, &nsec
);
4943 if (nsec
>= kNoTickleCancelWindow
) {
4944 dropTickleDesire
= true;
4948 if (dropTickleDesire
) {
4949 // Force the next tickle to raise power state
4950 fDeviceWasActive
= false;
4951 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4954 IOLockUnlock(fActivityLock
);
4957 if (dropTickleDesire
) {
4958 // Advisory tickle desire is intentionally untouched since
4959 // it has no effect until system is promoted to full wake.
4961 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4962 computeDesiredState(kPowerStateZero
, true);
4963 PM_LOG1("%s: tickle desire dropped\n", fName
);
4968 //*********************************************************************************
4969 // [private] ParentChangeTellPriorityClientsPowerDown
4971 // All applications and kernel clients have acknowledged our intention to drop
4972 // power. Here we notify "priority" clients that we are lowering power.
4973 //*********************************************************************************
4976 IOService::ParentChangeTellPriorityClientsPowerDown( void )
4978 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
4979 tellChangeDown2(fHeadNotePowerState
);
4982 //*********************************************************************************
4983 // [private] ParentChangeTellCapabilityWillChange
4985 // All (legacy) applications and kernel clients have acknowledged, extra stage for
4986 // root domain to notify apps and drivers about the system capability change.
4987 //*********************************************************************************
4990 IOService::ParentChangeTellCapabilityWillChange( void )
4992 if (!IS_ROOT_DOMAIN
) {
4993 return ParentChangeNotifyInterestedDriversWillChange();
4996 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
4999 //*********************************************************************************
5000 // [private] ParentChangeNotifyInterestedDriversWillChange
5002 // All applications and kernel clients have acknowledged our power state change.
5003 // Here we notify interested drivers pre-change.
5004 //*********************************************************************************
5007 IOService::ParentChangeNotifyInterestedDriversWillChange( void )
5009 notifyAll( kIOPM_ParentChangeSetPowerState
);
5012 //*********************************************************************************
5013 // [private] ParentChangeSetPowerState
5015 // Instruct our controlling driver to program the hardware for the power state
5016 // change. Wait for async completions.
5017 //*********************************************************************************
5020 IOService::ParentChangeSetPowerState( void )
5022 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
5023 fMachineState
= kIOPM_DriverThreadCallDone
;
5024 fDriverCallReason
= kDriverCallSetPowerState
;
5026 if (notifyControllingDriver() == false) {
5027 notifyControllingDriverDone();
5031 //*********************************************************************************
5032 // [private] ParentChangeWaitForPowerSettle
5034 // Our controlling driver has completed the power state change initiated by our
5035 // parent. Wait for the driver specified settle time to expire.
5036 //*********************************************************************************
5039 IOService::ParentChangeWaitForPowerSettle( void )
5041 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
5045 //*********************************************************************************
5046 // [private] ParentChangeNotifyInterestedDriversDidChange
5048 // Power has settled on a power change initiated by our parent. Here we notify
5049 // all our interested drivers post-change.
5050 //*********************************************************************************
5053 IOService::ParentChangeNotifyInterestedDriversDidChange( void )
5055 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
5058 //*********************************************************************************
5059 // [private] ParentChangeTellCapabilityDidChange
5061 // For root domain to notify capability power-change.
5062 //*********************************************************************************
5065 IOService::ParentChangeTellCapabilityDidChange( void )
5067 if (!IS_ROOT_DOMAIN
) {
5068 return ParentChangeAcknowledgePowerChange();
5071 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
5074 //*********************************************************************************
5075 // [private] ParentAcknowledgePowerChange
5077 // Acknowledge our power parent that our power change is done.
5078 //*********************************************************************************
5081 IOService::ParentChangeAcknowledgePowerChange( void )
5083 IORegistryEntry
* nub
;
5086 nub
= fHeadNoteParentConnection
;
5089 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
5091 parent
->acknowledgePowerChange((IOService
*)nub
);
5098 // MARK: Ack and Settle timers
5100 //*********************************************************************************
5101 // [private] settleTimerExpired
5103 // Power has settled after our last change. Notify interested parties that
5104 // there is a new power state.
5105 //*********************************************************************************
5108 IOService::settleTimerExpired( void )
5111 gIOPMWorkQueue
->signalWorkAvailable();
5114 //*********************************************************************************
5115 // settle_timer_expired
5117 // Holds a retain while the settle timer callout is in flight.
5118 //*********************************************************************************
5121 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5123 IOService
* me
= (IOService
*) arg0
;
5125 if (gIOPMWorkLoop
&& gIOPMWorkQueue
) {
5126 gIOPMWorkLoop
->runAction(
5127 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5133 //*********************************************************************************
5134 // [private] startSettleTimer
5136 // Calculate a power-settling delay in microseconds and start a timer.
5137 //*********************************************************************************
5140 IOService::startSettleTimer( void )
5143 // This function is broken and serves no useful purpose since it never
5144 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5145 // yet it starts a delay timer. It appears no driver relies on a delay
5146 // from settleUpTime and settleDownTime in the power state table.
5148 AbsoluteTime deadline
;
5149 IOPMPowerStateIndex stateIndex
;
5150 IOPMPowerStateIndex currentOrder
, newOrder
, i
;
5151 uint32_t settleTime
= 0;
5154 PM_ASSERT_IN_GATE();
5156 currentOrder
= StateOrder(fCurrentPowerState
);
5157 newOrder
= StateOrder(fHeadNotePowerState
);
5162 if (newOrder
< currentOrder
) {
5163 while (i
> newOrder
) {
5164 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
5165 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleDownTime
;
5171 if (newOrder
> currentOrder
) {
5172 while (i
< newOrder
) {
5173 stateIndex
= fPowerStates
[i
+ 1].stateOrderToIndex
;
5174 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleUpTime
;
5181 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5182 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5190 //*********************************************************************************
5191 // [private] ackTimerTick
5193 // The acknowledgement timeout periodic timer has ticked.
5194 // If we are awaiting acks for a power change notification,
5195 // we decrement the timer word of each interested driver which hasn't acked.
5196 // If a timer word becomes zero, we pretend the driver aknowledged.
5197 // If we are waiting for the controlling driver to change the power
5198 // state of the hardware, we decrement its timer word, and if it becomes
5199 // zero, we pretend the driver acknowledged.
5201 // Returns true if the timer tick made it possible to advance to the next
5202 // machine state, false otherwise.
5203 //*********************************************************************************
5207 IOService::ack_timer_ticked( void )
5211 #endif /* !__LP64__ */
5214 IOService::ackTimerTick( void )
5216 IOPMinformee
* nextObject
;
5219 PM_ASSERT_IN_GATE();
5220 switch (fMachineState
) {
5221 case kIOPM_OurChangeWaitForPowerSettle
:
5222 case kIOPM_ParentChangeWaitForPowerSettle
:
5223 // are we waiting for controlling driver to acknowledge?
5224 if (fDriverTimer
> 0) {
5225 // yes, decrement timer tick
5227 if (fDriverTimer
== 0) {
5228 // controlling driver is tardy
5229 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5230 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
5231 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
5232 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5233 fName
, OBFUSCATE(this), fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5235 #if DEBUG && CONFIG_EMBEDDED
5236 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5237 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5239 if (gIOKitDebug
& kIOLogDebugPower
) {
5240 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5241 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5243 // Unblock state machine and pretend driver has acked.
5247 getPMRootDomain()->reset_watchdog_timer(this, 0);
5249 // still waiting, set timer again
5255 case kIOPM_NotifyChildrenStart
:
5256 // are we waiting for interested parties to acknowledge?
5257 if (fHeadNotePendingAcks
!= 0) {
5258 // yes, go through the list of interested drivers
5259 nextObject
= fInterestedDrivers
->firstInList();
5260 // and check each one
5261 while (nextObject
!= NULL
) {
5262 if (nextObject
->timer
> 0) {
5263 nextObject
->timer
--;
5264 // this one should have acked by now
5265 if (nextObject
->timer
== 0) {
5266 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5267 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5268 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5269 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5270 nextObject
->whatObject
->getName(),
5271 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5272 OBFUSCATE(nextObject
->whatObject
), fName
, fCurrentPowerState
, fHeadNotePowerState
,
5275 // Pretend driver has acked.
5276 fHeadNotePendingAcks
--;
5279 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5282 // is that the last?
5283 if (fHeadNotePendingAcks
== 0) {
5284 // yes, we can continue
5287 // no, set timer again
5293 // TODO: aggreggate this
5294 case kIOPM_OurChangeTellClientsPowerDown
:
5295 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
5296 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5297 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5298 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5299 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5300 case kIOPM_SyncTellClientsPowerDown
:
5301 case kIOPM_SyncTellPriorityClientsPowerDown
:
5302 case kIOPM_SyncNotifyWillChange
:
5303 case kIOPM_TellCapabilityChangeDone
:
5304 // apps didn't respond in time
5305 cleanClientResponses(true);
5306 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5307 // tardy equates to approval
5312 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5313 getName(), fMachineState
);
5319 //*********************************************************************************
5320 // [private] start_watchdog_timer
5321 //*********************************************************************************
5323 IOService::start_watchdog_timer( void )
5328 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5332 IOLockLock(fWatchdogLock
);
5334 timeout
= getPMRootDomain()->getWatchdogTimeout();
5335 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5336 fWatchdogDeadline
= deadline
;
5337 start_watchdog_timer(deadline
);
5338 IOLockUnlock(fWatchdogLock
);
5342 IOService::start_watchdog_timer(uint64_t deadline
)
5344 IOLockAssert(fWatchdogLock
, kIOLockAssertOwned
);
5346 if (!thread_call_isactive(fWatchdogTimer
)) {
5347 thread_call_enter_delayed(fWatchdogTimer
, deadline
);
5351 //*********************************************************************************
5352 // [private] stop_watchdog_timer
5353 //*********************************************************************************
5356 IOService::stop_watchdog_timer( void )
5358 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5362 IOLockLock(fWatchdogLock
);
5364 thread_call_cancel(fWatchdogTimer
);
5365 fWatchdogDeadline
= 0;
5367 while (fBlockedArray
->getCount()) {
5368 IOService
*obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(0));
5370 PM_ERROR("WDOG:Object %s unexpected in blocked array\n", obj
->fName
);
5371 fBlockedArray
->removeObject(0);
5375 IOLockUnlock(fWatchdogLock
);
5378 //*********************************************************************************
5379 // reset_watchdog_timer
5380 //*********************************************************************************
5383 IOService::reset_watchdog_timer(IOService
*blockedObject
, int pendingResponseTimeout
)
5389 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
)) {
5394 IOLockLock(fWatchdogLock
);
5395 if (!fWatchdogDeadline
) {
5399 i
= fBlockedArray
->getNextIndexOfObject(blockedObject
, 0);
5400 if (pendingResponseTimeout
== 0) {
5401 blockedObject
->fPendingResponseDeadline
= 0;
5402 if (i
== (unsigned int)-1) {
5405 fBlockedArray
->removeObject(i
);
5407 // Set deadline 2secs after the expected response timeout to allow
5408 // ack timer to handle the timeout.
5409 clock_interval_to_deadline(pendingResponseTimeout
+ 2, kSecondScale
, &deadline
);
5411 if (i
!= (unsigned int)-1) {
5412 PM_ERROR("WDOG:Object %s is already blocked for responses. Ignoring timeout %d\n",
5413 fName
, pendingResponseTimeout
);
5418 for (i
= 0; i
< fBlockedArray
->getCount(); i
++) {
5419 obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(i
));
5420 if (obj
&& (obj
->fPendingResponseDeadline
< deadline
)) {
5421 blockedObject
->fPendingResponseDeadline
= deadline
;
5422 fBlockedArray
->setObject(i
, blockedObject
);
5426 if (i
== fBlockedArray
->getCount()) {
5427 blockedObject
->fPendingResponseDeadline
= deadline
;
5428 fBlockedArray
->setObject(blockedObject
);
5432 obj
= OSDynamicCast(IOService
, fBlockedArray
->getObject(0));
5434 int timeout
= getPMRootDomain()->getWatchdogTimeout();
5435 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5437 deadline
= obj
->fPendingResponseDeadline
;
5440 thread_call_cancel(fWatchdogTimer
);
5441 start_watchdog_timer(deadline
);
5444 IOLockUnlock(fWatchdogLock
);
5448 //*********************************************************************************
5449 // [static] watchdog_timer_expired
5451 // Inside PM work loop's gate.
5452 //*********************************************************************************
5455 IOService::watchdog_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5457 IOService
* me
= (IOService
*) arg0
;
5460 gIOPMWatchDogThread
= current_thread();
5461 getPMRootDomain()->sleepWakeDebugTrig(true);
5462 gIOPMWatchDogThread
= 0;
5463 thread_call_free(me
->fWatchdogTimer
);
5464 me
->fWatchdogTimer
= 0;
5471 IOService::getIOPMWorkloop( void )
5473 return gIOPMWorkLoop
;
5478 //*********************************************************************************
5479 // [private] start_ack_timer
5480 //*********************************************************************************
5483 IOService::start_ack_timer( void )
5485 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5489 IOService::start_ack_timer( UInt32 interval
, UInt32 scale
)
5491 AbsoluteTime deadline
;
5494 clock_interval_to_deadline(interval
, scale
, &deadline
);
5497 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5503 //*********************************************************************************
5504 // [private] stop_ack_timer
5505 //*********************************************************************************
5508 IOService::stop_ack_timer( void )
5512 pending
= thread_call_cancel(fAckTimer
);
5518 //*********************************************************************************
5519 // [static] actionAckTimerExpired
5521 // Inside PM work loop's gate.
5522 //*********************************************************************************
5525 IOService::actionAckTimerExpired(
5527 void * arg0
, void * arg1
,
5528 void * arg2
, void * arg3
)
5530 IOService
* me
= (IOService
*) target
;
5533 // done will be true if the timer tick unblocks the machine state,
5534 // otherwise no need to signal the work loop.
5536 done
= me
->ackTimerTick();
5537 if (done
&& gIOPMWorkQueue
) {
5538 gIOPMWorkQueue
->signalWorkAvailable();
5541 return kIOReturnSuccess
;
5544 //*********************************************************************************
5545 // ack_timer_expired
5547 // Thread call function. Holds a retain while the callout is in flight.
5548 //*********************************************************************************
5551 IOService::ack_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5553 IOService
* me
= (IOService
*) arg0
;
5555 if (gIOPMWorkLoop
) {
5556 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5561 //*********************************************************************************
5562 // [private] start_spindump_timer
5563 //*********************************************************************************
5566 IOService::start_spindump_timer( const char * delay_type
)
5568 AbsoluteTime deadline
;
5571 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
)) {
5575 if (gIOSpinDumpKextName
[0] == '\0' &&
5576 !(PE_parse_boot_argn("swd_kext_name", &gIOSpinDumpKextName
,
5577 sizeof(gIOSpinDumpKextName
)))) {
5581 if (strncmp(gIOSpinDumpKextName
, fName
, sizeof(gIOSpinDumpKextName
)) != 0) {
5585 if (gIOSpinDumpDelayType
[0] == '\0' &&
5586 !(PE_parse_boot_argn("swd_delay_type", &gIOSpinDumpDelayType
,
5587 sizeof(gIOSpinDumpDelayType
)))) {
5588 strncpy(gIOSpinDumpDelayType
, "SetState", sizeof(gIOSpinDumpDelayType
));
5591 if (strncmp(delay_type
, gIOSpinDumpDelayType
, sizeof(gIOSpinDumpDelayType
)) != 0) {
5595 if (gIOSpinDumpDelayDuration
== 0 &&
5596 !(PE_parse_boot_argn("swd_delay_duration", &gIOSpinDumpDelayDuration
,
5597 sizeof(gIOSpinDumpDelayDuration
)))) {
5598 gIOSpinDumpDelayDuration
= 300;
5601 clock_interval_to_deadline(gIOSpinDumpDelayDuration
, kMillisecondScale
, &deadline
);
5604 pending
= thread_call_enter_delayed(fSpinDumpTimer
, deadline
);
5610 //*********************************************************************************
5611 // [private] stop_spindump_timer
5612 //*********************************************************************************
5615 IOService::stop_spindump_timer( void )
5619 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
)) {
5623 pending
= thread_call_cancel(fSpinDumpTimer
);
5630 //*********************************************************************************
5631 // [static] actionSpinDumpTimerExpired
5633 // Inside PM work loop's gate.
5634 //*********************************************************************************
5637 IOService::actionSpinDumpTimerExpired(
5639 void * arg0
, void * arg1
,
5640 void * arg2
, void * arg3
)
5642 getPMRootDomain()->takeStackshot(false, false, true);
5644 return kIOReturnSuccess
;
5647 //*********************************************************************************
5648 // spindump_timer_expired
5650 // Thread call function. Holds a retain while the callout is in flight.
5651 //*********************************************************************************
5654 IOService::spindump_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5656 IOService
* me
= (IOService
*) arg0
;
5658 if (gIOPMWorkLoop
) {
5659 gIOPMWorkLoop
->runAction(&actionSpinDumpTimerExpired
, me
);
5665 // MARK: Client Messaging
5667 //*********************************************************************************
5668 // [private] tellSystemCapabilityChange
5669 //*********************************************************************************
5672 IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5675 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5676 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5679 // Notify app first on pre-change.
5680 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5682 // Notify kernel clients first on post-change.
5683 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5686 tellClientsWithResponse( fOutOfBandMessage
);
5689 //*********************************************************************************
5690 // [public] askChangeDown
5692 // Ask registered applications and kernel clients if we can change to a lower
5695 // Subclass can override this to send a different message type. Parameter is
5696 // the destination state number.
5698 // Return true if we don't have to wait for acknowledgements
5699 //*********************************************************************************
5702 IOService::askChangeDown( unsigned long stateNum
)
5704 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5707 //*********************************************************************************
5708 // [private] tellChangeDown1
5710 // Notify registered applications and kernel clients that we are definitely
5713 // Return true if we don't have to wait for acknowledgements
5714 //*********************************************************************************
5717 IOService::tellChangeDown1( unsigned long stateNum
)
5719 fOutOfBandParameter
= kNotifyApps
;
5720 return tellChangeDown(stateNum
);
5723 //*********************************************************************************
5724 // [private] tellChangeDown2
5726 // Notify priority clients that we are definitely dropping power.
5728 // Return true if we don't have to wait for acknowledgements
5729 //*********************************************************************************
5732 IOService::tellChangeDown2( unsigned long stateNum
)
5734 fOutOfBandParameter
= kNotifyPriority
;
5735 return tellChangeDown(stateNum
);
5738 //*********************************************************************************
5739 // [public] tellChangeDown
5741 // Notify registered applications and kernel clients that we are definitely
5744 // Subclass can override this to send a different message type. Parameter is
5745 // the destination state number.
5747 // Return true if we don't have to wait for acknowledgements
5748 //*********************************************************************************
5751 IOService::tellChangeDown( unsigned long stateNum
)
5753 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5756 //*********************************************************************************
5757 // cleanClientResponses
5759 //*********************************************************************************
5762 logAppTimeouts( OSObject
* object
, void * arg
)
5764 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5766 unsigned int clientIndex
;
5770 if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
5771 // Discover the 'counter' value or index assigned to this client
5772 // when it was notified, by searching for the array index of the
5773 // client in an array holding the cached interested clients.
5775 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5777 if ((clientIndex
!= (unsigned int) -1) &&
5778 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5779 (flag
!= kOSBooleanTrue
)) {
5780 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5784 pid
= clientID
->unsigned32BitValue();
5785 proc_name(pid
, name
, sizeof(name
));
5786 clientID
->release();
5789 PM_ERROR(context
->errorLog
, pid
, name
);
5791 // TODO: record message type if possible
5792 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5793 gIOPMStatsResponseTimedOut
,
5794 name
, 0, (30 * 1000), pid
, object
);
5800 IOService::cleanClientResponses( bool logErrors
)
5802 if (logErrors
&& fResponseArray
) {
5803 switch (fOutOfBandParameter
) {
5805 case kNotifyCapabilityChangeApps
:
5806 if (fNotifyClientArray
) {
5807 IOPMInterestContext context
;
5809 context
.responseArray
= fResponseArray
;
5810 context
.notifyClients
= fNotifyClientArray
;
5811 context
.serialNumber
= fSerialNumber
;
5812 context
.messageType
= kIOMessageCopyClientID
;
5813 context
.notifyType
= kNotifyApps
;
5814 context
.isPreChange
= fIsPreChange
;
5815 context
.enableTracing
= false;
5817 context
.maxTimeRequested
= 0;
5818 context
.stateNumber
= fHeadNotePowerState
;
5819 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5820 context
.changeFlags
= fHeadNoteChangeFlags
;
5821 context
.errorLog
= "PM notification timeout (pid %d, %s)\n";
5823 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5828 // kNotifyPriority, kNotifyCapabilityChangePriority
5829 // TODO: identify the priority client that has not acked
5830 PM_ERROR("PM priority notification timeout\n");
5831 if (gIOKitDebug
& kIOLogDebugPower
) {
5832 panic("PM priority notification timeout");
5838 if (IS_ROOT_DOMAIN
) {
5839 getPMRootDomain()->reset_watchdog_timer(this, 0);
5841 if (fResponseArray
) {
5842 fResponseArray
->release();
5843 fResponseArray
= NULL
;
5845 if (fNotifyClientArray
) {
5846 fNotifyClientArray
->release();
5847 fNotifyClientArray
= NULL
;
5851 //*********************************************************************************
5852 // [protected] tellClientsWithResponse
5854 // Notify registered applications and kernel clients that we are definitely
5857 // Return true if we don't have to wait for acknowledgements
5858 //*********************************************************************************
5861 IOService::tellClientsWithResponse( int messageType
)
5863 IOPMInterestContext context
;
5864 bool isRootDomain
= IS_ROOT_DOMAIN
;
5865 uint32_t maxTimeOut
= kMaxTimeRequested
;
5867 PM_ASSERT_IN_GATE();
5868 assert( fResponseArray
== NULL
);
5869 assert( fNotifyClientArray
== NULL
);
5871 if (messageType
== (int)kIOPMMessageLastCallBeforeSleep
) {
5872 RD_LOG("tellClientsWithResponse( kIOPMMessageLastCallBeforeSleep, %d )\n",
5873 fOutOfBandParameter
);
5875 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5876 getIOMessageString(messageType
), fOutOfBandParameter
);
5879 fResponseArray
= OSArray::withCapacity( 1 );
5880 if (!fResponseArray
) {
5884 fResponseArray
->setCapacityIncrement(8);
5885 if (++fSerialNumber
== 0) {
5889 context
.responseArray
= fResponseArray
;
5890 context
.notifyClients
= 0;
5891 context
.serialNumber
= fSerialNumber
;
5892 context
.messageType
= messageType
;
5893 context
.notifyType
= fOutOfBandParameter
;
5894 context
.isPreChange
= fIsPreChange
;
5895 context
.enableTracing
= false;
5897 context
.maxTimeRequested
= 0;
5898 context
.stateNumber
= fHeadNotePowerState
;
5899 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5900 context
.changeFlags
= fHeadNoteChangeFlags
;
5901 context
.messageFilter
= (isRootDomain
) ?
5902 OSMemberFunctionCast(
5905 &IOPMrootDomain::systemMessageFilter
) : 0;
5907 switch (fOutOfBandParameter
) {
5909 applyToInterested( gIOAppPowerStateInterest
,
5910 pmTellAppWithResponse
, (void *) &context
);
5913 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5914 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
) &&
5915 (context
.messageType
!= kIOPMMessageLastCallBeforeSleep
)) {
5916 // Notify capability app for tellChangeDown1()
5917 // but not for askChangeDown().
5918 context
.notifyType
= kNotifyCapabilityChangeApps
;
5919 context
.messageType
= kIOMessageSystemCapabilityChange
;
5920 applyToInterested( gIOAppPowerStateInterest
,
5921 pmTellCapabilityAppWithResponse
, (void *) &context
);
5922 context
.notifyType
= fOutOfBandParameter
;
5923 context
.messageType
= messageType
;
5925 if (context
.messageType
== kIOMessageCanSystemSleep
) {
5926 maxTimeOut
= kCanSleepMaxTimeReq
;
5927 if (gCanSleepTimeout
) {
5928 maxTimeOut
= (gCanSleepTimeout
* us_per_s
);
5931 context
.maxTimeRequested
= maxTimeOut
;
5932 context
.enableTracing
= isRootDomain
;
5933 applyToInterested( gIOGeneralInterest
,
5934 pmTellClientWithResponse
, (void *) &context
);
5938 case kNotifyPriority
:
5939 context
.enableTracing
= isRootDomain
;
5940 applyToInterested( gIOPriorityPowerStateInterest
,
5941 pmTellClientWithResponse
, (void *) &context
);
5944 // Notify capability clients for tellChangeDown2().
5945 context
.notifyType
= kNotifyCapabilityChangePriority
;
5946 context
.messageType
= kIOMessageSystemCapabilityChange
;
5947 applyToInterested( gIOPriorityPowerStateInterest
,
5948 pmTellCapabilityClientWithResponse
, (void *) &context
);
5952 case kNotifyCapabilityChangeApps
:
5953 applyToInterested( gIOAppPowerStateInterest
,
5954 pmTellCapabilityAppWithResponse
, (void *) &context
);
5955 if (context
.messageType
== kIOMessageCanSystemSleep
) {
5956 maxTimeOut
= kCanSleepMaxTimeReq
;
5957 if (gCanSleepTimeout
) {
5958 maxTimeOut
= (gCanSleepTimeout
* us_per_s
);
5961 context
.maxTimeRequested
= maxTimeOut
;
5964 case kNotifyCapabilityChangePriority
:
5965 context
.enableTracing
= isRootDomain
;
5966 applyToInterested( gIOPriorityPowerStateInterest
,
5967 pmTellCapabilityClientWithResponse
, (void *) &context
);
5970 fNotifyClientArray
= context
.notifyClients
;
5972 // do we have to wait for somebody?
5973 if (!checkForDone()) {
5974 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5975 if (context
.enableTracing
) {
5976 getPMRootDomain()->traceDetail(context
.messageType
, 0, context
.maxTimeRequested
/ 1000);
5977 getPMRootDomain()->reset_watchdog_timer(this, context
.maxTimeRequested
/ USEC_PER_SEC
+ 1);
5979 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5984 // everybody responded
5985 if (fResponseArray
) {
5986 fResponseArray
->release();
5987 fResponseArray
= NULL
;
5989 if (fNotifyClientArray
) {
5990 fNotifyClientArray
->release();
5991 fNotifyClientArray
= NULL
;
5997 //*********************************************************************************
5998 // [static private] pmTellAppWithResponse
6000 // We send a message to an application, and we expect a response, so we compute a
6001 // cookie we can identify the response with.
6002 //*********************************************************************************
6005 IOService::pmTellAppWithResponse( OSObject
* object
, void * arg
)
6007 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6008 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6009 uint32_t msgIndex
, msgRef
, msgType
;
6010 OSNumber
*clientID
= NULL
;
6012 boolean_t proc_suspended
= FALSE
;
6013 OSObject
* waitForReply
= kOSBooleanTrue
;
6014 #if LOG_APP_RESPONSE_TIMES
6018 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
6022 if (context
->us
== getPMRootDomain()) {
6023 if ((clientID
= copyClientIDForNotification(object
, context
))) {
6024 uint32_t clientPID
= clientID
->unsigned32BitValue();
6025 clientID
->release();
6026 proc
= proc_find(clientPID
);
6029 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6032 if (proc_suspended
) {
6033 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
6040 if (context
->messageFilter
&&
6041 !context
->messageFilter(context
->us
, object
, context
, 0, &waitForReply
)) {
6042 if (kIOLogDebugPower
& gIOKitDebug
) {
6043 logClientIDForNotification(object
, context
, "DROP App");
6048 // Create client array (for tracking purposes) only if the service
6049 // has app clients. Usually only root domain does.
6050 if (0 == context
->notifyClients
) {
6051 context
->notifyClients
= OSArray::withCapacity( 32 );
6054 msgType
= context
->messageType
;
6055 msgIndex
= context
->responseArray
->getCount();
6056 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6058 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6059 if (kIOLogDebugPower
& gIOKitDebug
) {
6060 logClientIDForNotification(object
, context
, "MESG App");
6063 if (waitForReply
== kOSBooleanTrue
) {
6065 clock_get_uptime(&now
);
6066 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6068 context
->responseArray
->setObject(msgIndex
, num
);
6071 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6074 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6075 if (kIOLogDebugPower
& gIOKitDebug
) {
6076 logClientIDForNotification(object
, context
, "App response ignored");
6080 if (context
->notifyClients
) {
6081 context
->notifyClients
->setObject(msgIndex
, object
);
6084 context
->us
->messageClient(msgType
, object
, (void *)(uintptr_t) msgRef
);
6087 //*********************************************************************************
6088 // [static private] pmTellClientWithResponse
6090 // We send a message to an in-kernel client, and we expect a response,
6091 // so we compute a cookie we can identify the response with.
6092 //*********************************************************************************
6095 IOService::pmTellClientWithResponse( OSObject
* object
, void * arg
)
6097 IOPowerStateChangeNotification notify
;
6098 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6099 OSObject
* replied
= kOSBooleanTrue
;
6100 _IOServiceInterestNotifier
* notifier
;
6101 uint32_t msgIndex
, msgRef
, msgType
;
6103 AbsoluteTime start
, end
;
6106 if (context
->messageFilter
&&
6107 !context
->messageFilter(context
->us
, object
, context
, 0, 0)) {
6108 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6109 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6110 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6111 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6112 context
->us
->getName(),
6113 getIOMessageString(context
->messageType
),
6114 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6119 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6120 msgType
= context
->messageType
;
6121 msgIndex
= context
->responseArray
->getCount();
6122 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6124 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6125 if (gIOKitDebug
& kIOLogPower
) {
6126 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6127 if (OSDynamicCast(IOService
, object
)) {
6128 const char *who
= ((IOService
*) object
)->getName();
6129 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6130 } else if (notifier
) {
6131 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6134 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
) {
6135 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6136 context
->us
->getName(),
6137 getIOMessageString(msgType
),
6138 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6141 if (0 == context
->notifyClients
) {
6142 context
->notifyClients
= OSArray::withCapacity( 32 );
6145 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
6146 notify
.returnValue
= 0;
6147 notify
.stateNumber
= context
->stateNumber
;
6148 notify
.stateFlags
= context
->stateFlags
;
6150 if (context
->enableTracing
&& (notifier
!= 0)) {
6151 getPMRootDomain()->traceDetail(notifier
, true);
6154 clock_get_uptime(&start
);
6155 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
6156 clock_get_uptime(&end
);
6158 if (context
->enableTracing
&& (notifier
!= NULL
)) {
6159 getPMRootDomain()->traceDetail(notifier
, false);
6163 if (kIOReturnSuccess
== retCode
) {
6164 if (0 == notify
.returnValue
) {
6165 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6166 context
->responseArray
->setObject(msgIndex
, replied
);
6168 replied
= kOSBooleanFalse
;
6169 if (notify
.returnValue
> context
->maxTimeRequested
) {
6170 if (notify
.returnValue
> kPriorityClientMaxWait
) {
6171 context
->maxTimeRequested
= kPriorityClientMaxWait
;
6172 PM_ERROR("%s: client %p returned %llu for %s\n",
6173 context
->us
->getName(),
6174 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6175 (uint64_t) notify
.returnValue
,
6176 getIOMessageString(msgType
));
6178 context
->maxTimeRequested
= notify
.returnValue
;
6182 // Track time taken to ack, by storing the timestamp of
6183 // callback completion
6185 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6187 context
->responseArray
->setObject(msgIndex
, num
);
6190 context
->responseArray
->setObject(msgIndex
, replied
);
6194 if (context
->enableTracing
) {
6195 SUB_ABSOLUTETIME(&end
, &start
);
6196 absolutetime_to_nanoseconds(end
, &nsec
);
6198 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (notify
.returnValue
!= 0)) {
6199 getPMRootDomain()->traceAckDelay(notifier
, notify
.returnValue
/ 1000, NS_TO_MS(nsec
));
6203 // not a client of ours
6204 // so we won't be waiting for response
6205 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6206 context
->responseArray
->setObject(msgIndex
, replied
);
6208 if (context
->notifyClients
) {
6209 context
->notifyClients
->setObject(msgIndex
, object
);
6213 //*********************************************************************************
6214 // [static private] pmTellCapabilityAppWithResponse
6215 //*********************************************************************************
6218 IOService::pmTellCapabilityAppWithResponse( OSObject
* object
, void * arg
)
6220 IOPMSystemCapabilityChangeParameters msgArg
;
6221 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6222 OSObject
* replied
= kOSBooleanTrue
;
6223 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6224 uint32_t msgIndex
, msgRef
, msgType
;
6225 #if LOG_APP_RESPONSE_TIMES
6229 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
6233 memset(&msgArg
, 0, sizeof(msgArg
));
6234 if (context
->messageFilter
&&
6235 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
)) {
6239 // Create client array (for tracking purposes) only if the service
6240 // has app clients. Usually only root domain does.
6241 if (0 == context
->notifyClients
) {
6242 context
->notifyClients
= OSArray::withCapacity( 32 );
6245 msgType
= context
->messageType
;
6246 msgIndex
= context
->responseArray
->getCount();
6247 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6249 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6250 if (kIOLogDebugPower
& gIOKitDebug
) {
6251 // Log client pid/name and client array index.
6252 OSNumber
* clientID
= NULL
;
6253 OSString
* clientIDString
= NULL
;;
6254 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6256 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6259 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
6260 context
->us
->getName(),
6261 msgIndex
, getIOMessageString(msgType
),
6262 (replied
!= kOSBooleanTrue
),
6263 clientIDString
? clientIDString
->getCStringNoCopy() : "");
6265 clientID
->release();
6267 if (clientIDString
) {
6268 clientIDString
->release();
6272 msgArg
.notifyRef
= msgRef
;
6273 msgArg
.maxWaitForReply
= 0;
6275 if (replied
== kOSBooleanTrue
) {
6276 msgArg
.notifyRef
= 0;
6277 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6278 if (context
->notifyClients
) {
6279 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
6283 clock_get_uptime(&now
);
6284 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6286 context
->responseArray
->setObject(msgIndex
, num
);
6289 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6292 if (context
->notifyClients
) {
6293 context
->notifyClients
->setObject(msgIndex
, object
);
6297 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6300 //*********************************************************************************
6301 // [static private] pmTellCapabilityClientWithResponse
6302 //*********************************************************************************
6305 IOService::pmTellCapabilityClientWithResponse(
6306 OSObject
* object
, void * arg
)
6308 IOPMSystemCapabilityChangeParameters msgArg
;
6309 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6310 OSObject
* replied
= kOSBooleanTrue
;
6311 _IOServiceInterestNotifier
* notifier
;
6312 uint32_t msgIndex
, msgRef
, msgType
;
6314 AbsoluteTime start
, end
;
6317 memset(&msgArg
, 0, sizeof(msgArg
));
6318 if (context
->messageFilter
&&
6319 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, 0)) {
6320 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6321 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6322 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6323 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6324 context
->us
->getName(),
6325 getIOMessageString(context
->messageType
),
6326 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6331 if (0 == context
->notifyClients
) {
6332 context
->notifyClients
= OSArray::withCapacity( 32 );
6334 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6335 msgType
= context
->messageType
;
6336 msgIndex
= context
->responseArray
->getCount();
6337 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6339 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6340 if (gIOKitDebug
& kIOLogPower
) {
6341 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6342 if (OSDynamicCast(IOService
, object
)) {
6343 const char *who
= ((IOService
*) object
)->getName();
6344 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6345 } else if (notifier
) {
6346 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6349 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
) {
6350 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6351 context
->us
->getName(),
6352 getIOMessageString(msgType
),
6353 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6356 msgArg
.notifyRef
= msgRef
;
6357 msgArg
.maxWaitForReply
= 0;
6359 if (context
->enableTracing
&& (notifier
!= 0)) {
6360 getPMRootDomain()->traceDetail(notifier
, true);
6363 clock_get_uptime(&start
);
6364 retCode
= context
->us
->messageClient(
6365 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6366 clock_get_uptime(&end
);
6367 if (context
->enableTracing
&& (notifier
!= NULL
)) {
6368 getPMRootDomain()->traceDetail(notifier
, false);
6371 if (kIOReturnSuccess
== retCode
) {
6372 if (0 == msgArg
.maxWaitForReply
) {
6373 // client doesn't want time to respond
6374 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6375 context
->responseArray
->setObject(msgIndex
, replied
);
6377 replied
= kOSBooleanFalse
;
6378 if (msgArg
.maxWaitForReply
> context
->maxTimeRequested
) {
6379 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
) {
6380 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
6381 PM_ERROR("%s: client %p returned %u for %s\n",
6382 context
->us
->getName(),
6383 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6384 msgArg
.maxWaitForReply
,
6385 getIOMessageString(msgType
));
6387 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6391 // Track time taken to ack, by storing the timestamp of
6392 // callback completion
6394 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&end
), sizeof(uint64_t) * 8);
6396 context
->responseArray
->setObject(msgIndex
, num
);
6399 context
->responseArray
->setObject(msgIndex
, replied
);
6403 if (context
->enableTracing
) {
6404 SUB_ABSOLUTETIME(&end
, &start
);
6405 absolutetime_to_nanoseconds(end
, &nsec
);
6407 if ((nsec
> LOG_KEXT_RESPONSE_TIMES
) || (msgArg
.maxWaitForReply
!= 0)) {
6408 getPMRootDomain()->traceAckDelay(notifier
, msgArg
.maxWaitForReply
/ 1000, NS_TO_MS(nsec
));
6412 // not a client of ours
6413 // so we won't be waiting for response
6414 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6415 context
->responseArray
->setObject(msgIndex
, replied
);
6417 if (context
->notifyClients
) {
6418 context
->notifyClients
->setObject(msgIndex
, object
);
6422 //*********************************************************************************
6423 // [public] tellNoChangeDown
6425 // Notify registered applications and kernel clients that we are not
6428 // Subclass can override this to send a different message type. Parameter is
6429 // the aborted destination state number.
6430 //*********************************************************************************
6433 IOService::tellNoChangeDown( unsigned long )
6435 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6438 //*********************************************************************************
6439 // [public] tellChangeUp
6441 // Notify registered applications and kernel clients that we are raising power.
6443 // Subclass can override this to send a different message type. Parameter is
6444 // the aborted destination state number.
6445 //*********************************************************************************
6448 IOService::tellChangeUp( unsigned long )
6450 return tellClients( kIOMessageDeviceHasPoweredOn
);
6453 //*********************************************************************************
6454 // [protected] tellClients
6456 // Notify registered applications and kernel clients of something.
6457 //*********************************************************************************
6460 IOService::tellClients( int messageType
)
6462 IOPMInterestContext context
;
6464 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6466 memset(&context
, 0, sizeof(context
));
6467 context
.messageType
= messageType
;
6468 context
.isPreChange
= fIsPreChange
;
6470 context
.stateNumber
= fHeadNotePowerState
;
6471 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6472 context
.changeFlags
= fHeadNoteChangeFlags
;
6473 context
.enableTracing
= IS_ROOT_DOMAIN
;
6474 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6475 OSMemberFunctionCast(
6478 &IOPMrootDomain::systemMessageFilter
) : 0;
6480 context
.notifyType
= kNotifyPriority
;
6481 applyToInterested( gIOPriorityPowerStateInterest
,
6482 tellKernelClientApplier
, (void *) &context
);
6484 context
.notifyType
= kNotifyApps
;
6485 applyToInterested( gIOAppPowerStateInterest
,
6486 tellAppClientApplier
, (void *) &context
);
6488 applyToInterested( gIOGeneralInterest
,
6489 tellKernelClientApplier
, (void *) &context
);
6492 //*********************************************************************************
6493 // [private] tellKernelClientApplier
6495 // Message a kernel client.
6496 //*********************************************************************************
6499 tellKernelClientApplier( OSObject
* object
, void * arg
)
6501 IOPowerStateChangeNotification notify
;
6502 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6504 if (context
->messageFilter
&&
6505 !context
->messageFilter(context
->us
, object
, context
, 0, 0)) {
6506 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6507 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6508 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6509 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6510 context
->us
->getName(),
6511 IOService::getIOMessageString(context
->messageType
),
6512 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6517 notify
.powerRef
= (void *) 0;
6518 notify
.returnValue
= 0;
6519 notify
.stateNumber
= context
->stateNumber
;
6520 notify
.stateFlags
= context
->stateFlags
;
6522 if (context
->enableTracing
&& object
) {
6523 IOService::getPMRootDomain()->traceDetail(object
, true);
6525 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6526 if (context
->enableTracing
&& object
) {
6527 IOService::getPMRootDomain()->traceDetail(object
, false);
6532 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6533 (OSDynamicCast(_IOServiceInterestNotifier
, object
))) {
6534 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6535 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6536 context
->us
->getName(),
6537 IOService::getIOMessageString(context
->messageType
),
6538 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6543 copyClientIDForNotification(
6545 IOPMInterestContext
*context
)
6547 OSNumber
*clientID
= NULL
;
6548 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6553 logClientIDForNotification(
6555 IOPMInterestContext
*context
,
6556 const char *logString
)
6558 OSString
*logClientID
= NULL
;
6559 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6563 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6566 PM_LOG("%s %s %s, %s\n",
6567 context
->us
->getName(), logString
,
6568 IOService::getIOMessageString(context
->messageType
),
6569 logClientID
? logClientID
->getCStringNoCopy() : "");
6572 logClientID
->release();
6577 clientID
->release();
6584 tellAppClientApplier( OSObject
* object
, void * arg
)
6586 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6587 OSNumber
* clientID
= NULL
;
6589 boolean_t proc_suspended
= FALSE
;
6591 if (context
->us
== IOService::getPMRootDomain()) {
6592 if ((clientID
= copyClientIDForNotification(object
, context
))) {
6593 uint32_t clientPID
= clientID
->unsigned32BitValue();
6594 clientID
->release();
6595 proc
= proc_find(clientPID
);
6598 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6601 if (proc_suspended
) {
6602 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6609 if (context
->messageFilter
&&
6610 !context
->messageFilter(context
->us
, object
, context
, 0, 0)) {
6611 if (kIOLogDebugPower
& gIOKitDebug
) {
6612 logClientIDForNotification(object
, context
, "DROP App");
6617 if (kIOLogDebugPower
& gIOKitDebug
) {
6618 logClientIDForNotification(object
, context
, "MESG App");
6621 context
->us
->messageClient(context
->messageType
, object
, 0);
6624 //*********************************************************************************
6625 // [private] checkForDone
6626 //*********************************************************************************
6629 IOService::checkForDone( void )
6634 if (fResponseArray
== NULL
) {
6639 theFlag
= fResponseArray
->getObject(i
);
6641 if (NULL
== theFlag
) {
6645 if (kOSBooleanTrue
!= theFlag
) {
6652 //*********************************************************************************
6653 // [public] responseValid
6654 //*********************************************************************************
6657 IOService::responseValid( uint32_t refcon
, int pid
)
6659 UInt16 serialComponent
;
6660 UInt16 ordinalComponent
;
6662 OSObject
*object
= 0;
6664 serialComponent
= (refcon
>> 16) & 0xFFFF;
6665 ordinalComponent
= (refcon
& 0xFFFF);
6667 if (serialComponent
!= fSerialNumber
) {
6671 if (fResponseArray
== NULL
) {
6675 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6681 if (fNotifyClientArray
) {
6682 object
= fNotifyClientArray
->getObject(ordinalComponent
);
6686 if ((num
= OSDynamicCast(OSNumber
, theFlag
))) {
6692 clock_get_uptime(&now
);
6693 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6694 SUB_ABSOLUTETIME(&now
, &start
);
6695 absolutetime_to_nanoseconds(now
, &nsec
);
6699 proc_name(pid
, name
, sizeof(name
));
6701 if (nsec
> LOG_APP_RESPONSE_TIMES
) {
6702 IOLog("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec
),
6707 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
) {
6708 // TODO: populate the messageType argument
6709 getPMRootDomain()->pmStatsRecordApplicationResponse(
6710 gIOPMStatsResponseSlow
,
6711 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6713 getPMRootDomain()->pmStatsRecordApplicationResponse(
6714 gIOPMStatsResponsePrompt
,
6715 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6718 getPMRootDomain()->traceAckDelay(object
, 0, NS_TO_MS(nsec
));
6721 if (kIOLogDebugPower
& gIOKitDebug
) {
6722 PM_LOG("Ack(%u) %u ms\n",
6723 (uint32_t) ordinalComponent
,
6726 theFlag
= kOSBooleanFalse
;
6727 } else if (object
) {
6728 getPMRootDomain()->pmStatsRecordApplicationResponse(
6729 gIOPMStatsResponsePrompt
,
6730 0, 0, 0, pid
, object
);
6733 if (kOSBooleanFalse
== theFlag
) {
6734 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6740 //*********************************************************************************
6741 // [public] allowPowerChange
6743 // Our power state is about to lower, and we have notified applications
6744 // and kernel clients, and one of them has acknowledged. If this is the last to do
6745 // so, and all acknowledgements are positive, we continue with the power change.
6746 //*********************************************************************************
6749 IOService::allowPowerChange( unsigned long refcon
)
6751 IOPMRequest
* request
;
6755 return kIOReturnSuccess
;
6758 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6760 return kIOReturnNoMemory
;
6763 request
->fArg0
= (void *) refcon
;
6764 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6765 request
->fArg2
= (void *) 0;
6766 submitPMRequest( request
);
6768 return kIOReturnSuccess
;
6773 IOService::serializedAllowPowerChange2( unsigned long refcon
)
6775 // [deprecated] public
6776 return kIOReturnUnsupported
;
6778 #endif /* !__LP64__ */
6780 //*********************************************************************************
6781 // [public] cancelPowerChange
6783 // Our power state is about to lower, and we have notified applications
6784 // and kernel clients, and one of them has vetoed the change. If this is the last
6785 // client to respond, we abandon the power change.
6786 //*********************************************************************************
6789 IOService::cancelPowerChange( unsigned long refcon
)
6791 IOPMRequest
* request
;
6793 pid_t pid
= proc_selfpid();
6797 return kIOReturnSuccess
;
6801 proc_name(pid
, name
, sizeof(name
));
6802 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid
, name
);
6804 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6806 return kIOReturnNoMemory
;
6809 request
->fArg0
= (void *) refcon
;
6810 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6811 request
->fArg2
= (void *) OSString::withCString(name
);
6812 submitPMRequest( request
);
6814 return kIOReturnSuccess
;
6819 IOService::serializedCancelPowerChange2( unsigned long refcon
)
6821 // [deprecated] public
6822 return kIOReturnUnsupported
;
6825 //*********************************************************************************
6826 // PM_Clamp_Timer_Expired
6828 // called when clamp timer expires...set power state to 0.
6829 //*********************************************************************************
6832 IOService::PM_Clamp_Timer_Expired( void )
6836 //*********************************************************************************
6839 // Set to highest available power state for a minimum of duration milliseconds
6840 //*********************************************************************************
6843 IOService::clampPowerOn( unsigned long duration
)
6846 #endif /* !__LP64__ */
6848 //*********************************************************************************
6849 // configurePowerStateReport
6851 // Configures the IOStateReport for kPMPowerStateChannel
6852 //*********************************************************************************
6854 IOService::configurePowerStatesReport( IOReportConfigureAction action
, void *result
)
6856 IOReturn rc
= kIOReturnSuccess
;
6862 return kIOReturnUnsupported
;
6865 if (!fNumberOfPowerStates
) {
6866 return kIOReturnSuccess
; // For drivers which are in power plane, but haven't called registerPowerDriver()
6871 case kIOReportEnable
:
6876 reportSize
= STATEREPORT_BUFSIZE(fNumberOfPowerStates
);
6877 fReportBuf
= IOMalloc(reportSize
);
6879 rc
= kIOReturnNoMemory
;
6882 memset(fReportBuf
, 0, reportSize
);
6884 STATEREPORT_INIT(fNumberOfPowerStates
, fReportBuf
, reportSize
,
6885 getRegistryEntryID(), kPMPowerStatesChID
, kIOReportCategoryPower
);
6887 for (i
= 0; i
< fNumberOfPowerStates
; i
++) {
6890 if (fPowerStates
[i
].capabilityFlags
& kIOPMPowerOn
) {
6891 bits
|= kPMReportPowerOn
;
6893 if (fPowerStates
[i
].capabilityFlags
& kIOPMDeviceUsable
) {
6894 bits
|= kPMReportDeviceUsable
;
6896 if (fPowerStates
[i
].capabilityFlags
& kIOPMLowPower
) {
6897 bits
|= kPMReportLowPower
;
6900 STATEREPORT_SETSTATEID(fReportBuf
, i
, ((bits
& 0xff) << 8) |
6901 ((StateOrder(fMaxPowerState
) & 0xf) << 4) | (StateOrder(i
) & 0xf));
6903 ts
= mach_absolute_time();
6904 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
6907 case kIOReportDisable
:
6908 if (fReportClientCnt
== 0) {
6909 rc
= kIOReturnBadArgument
;
6912 if (fReportClientCnt
== 1) {
6913 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
6919 case kIOReportGetDimensions
:
6921 STATEREPORT_UPDATERES(fReportBuf
, kIOReportGetDimensions
, result
);
6931 //*********************************************************************************
6932 // updatePowerStateReport
6934 // Updates the IOStateReport for kPMPowerStateChannel
6935 //*********************************************************************************
6937 IOService::updatePowerStatesReport( IOReportConfigureAction action
, void *result
, void *destination
)
6942 IOReturn rc
= kIOReturnSuccess
;
6943 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6947 return kIOReturnUnsupported
;
6949 if (!fNumberOfPowerStates
) {
6950 return kIOReturnSuccess
;
6953 if (!result
|| !dest
) {
6954 return kIOReturnBadArgument
;
6959 case kIOReportCopyChannelData
:
6961 rc
= kIOReturnNotOpen
;
6965 ts
= mach_absolute_time();
6966 STATEREPORT_UPDATEPREP(fReportBuf
, ts
, data2cpy
, size2cpy
);
6967 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
6968 rc
= kIOReturnOverrun
;
6972 STATEREPORT_UPDATERES(fReportBuf
, kIOReportCopyChannelData
, result
);
6973 dest
->appendBytes(data2cpy
, size2cpy
);
6985 //*********************************************************************************
6986 // configureSimplePowerReport
6988 // Configures the IOSimpleReport for given channel id
6989 //*********************************************************************************
6991 IOService::configureSimplePowerReport(IOReportConfigureAction action
, void *result
)
6993 IOReturn rc
= kIOReturnSuccess
;
6996 return kIOReturnUnsupported
;
6999 if (!fNumberOfPowerStates
) {
7004 case kIOReportEnable
:
7005 case kIOReportDisable
:
7008 case kIOReportGetDimensions
:
7009 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
7017 //*********************************************************************************
7018 // updateSimplePowerReport
7020 // Updates the IOSimpleReport for the given chanel id
7021 //*********************************************************************************
7023 IOService::updateSimplePowerReport( IOReportConfigureAction action
, void *result
, void *destination
)
7027 uint64_t buf
[SIMPLEREPORT_BUFSIZE
/ sizeof(uint64_t) + 1]; // Force a 8-byte alignment
7028 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
7029 IOReturn rc
= kIOReturnSuccess
;
7034 return kIOReturnUnsupported
;
7036 if (!result
|| !dest
) {
7037 return kIOReturnBadArgument
;
7040 if (!fNumberOfPowerStates
) {
7046 case kIOReportCopyChannelData
:
7048 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), kPMCurrStateChID
, kIOReportCategoryPower
);
7050 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMPowerOn
) {
7051 bits
|= kPMReportPowerOn
;
7053 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMDeviceUsable
) {
7054 bits
|= kPMReportDeviceUsable
;
7056 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMLowPower
) {
7057 bits
|= kPMReportLowPower
;
7061 SIMPLEREPORT_SETVALUE(buf
, ((bits
& 0xff) << 8) | ((StateOrder(fMaxPowerState
) & 0xf) << 4) |
7062 (StateOrder(fCurrentPowerState
) & 0xf));
7064 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
7065 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
7066 rc
= kIOReturnOverrun
;
7070 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
7071 dest
->appendBytes(data2cpy
, size2cpy
);
7080 return kIOReturnSuccess
;
7086 // MARK: Driver Overrides
7088 //*********************************************************************************
7089 // [public] setPowerState
7091 // Does nothing here. This should be implemented in a subclass driver.
7092 //*********************************************************************************
7095 IOService::setPowerState(
7096 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
7101 //*********************************************************************************
7102 // [public] maxCapabilityForDomainState
7104 // Finds the highest power state in the array whose input power requirement
7105 // is equal to the input parameter. Where a more intelligent decision is
7106 // possible, override this in the subclassed driver.
7107 //*********************************************************************************
7110 IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags
)
7112 IOPMPowerStateIndex stateIndex
;
7114 if (!fNumberOfPowerStates
) {
7115 return kPowerStateZero
;
7118 for (int order
= fNumberOfPowerStates
- 1; order
>= 0; order
--) {
7119 stateIndex
= fPowerStates
[order
].stateOrderToIndex
;
7121 if ((flags
& fPowerStates
[stateIndex
].inputPowerFlags
) ==
7122 fPowerStates
[stateIndex
].inputPowerFlags
) {
7126 return kPowerStateZero
;
7130 IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState
)
7132 return getPowerStateForDomainFlags(domainState
);
7135 //*********************************************************************************
7136 // [public] initialPowerStateForDomainState
7138 // Called to query the power state for the initial power transition.
7139 //*********************************************************************************
7142 IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState
)
7144 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
)) {
7145 // Return lowest power state for any root power domain changes
7146 return kPowerStateZero
;
7149 return getPowerStateForDomainFlags(domainState
);
7152 //*********************************************************************************
7153 // [public] powerStateForDomainState
7155 // This method is not called from PM.
7156 //*********************************************************************************
7159 IOService::powerStateForDomainState( IOPMPowerFlags domainState
)
7161 return getPowerStateForDomainFlags(domainState
);
7165 //*********************************************************************************
7166 // [deprecated] didYouWakeSystem
7168 // Does nothing here. This should be implemented in a subclass driver.
7169 //*********************************************************************************
7172 IOService::didYouWakeSystem( void )
7176 #endif /* !__LP64__ */
7178 //*********************************************************************************
7179 // [public] powerStateWillChangeTo
7181 // Does nothing here. This should be implemented in a subclass driver.
7182 //*********************************************************************************
7185 IOService::powerStateWillChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7187 return kIOPMAckImplied
;
7190 //*********************************************************************************
7191 // [public] powerStateDidChangeTo
7193 // Does nothing here. This should be implemented in a subclass driver.
7194 //*********************************************************************************
7197 IOService::powerStateDidChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7199 return kIOPMAckImplied
;
7202 //*********************************************************************************
7203 // [protected] powerChangeDone
7205 // Called from PM work loop thread.
7206 // Does nothing here. This should be implemented in a subclass policy-maker.
7207 //*********************************************************************************
7210 IOService::powerChangeDone( unsigned long )
7215 //*********************************************************************************
7216 // [deprecated] newTemperature
7218 // Does nothing here. This should be implemented in a subclass driver.
7219 //*********************************************************************************
7222 IOService::newTemperature( long currentTemp
, IOService
* whichZone
)
7226 #endif /* !__LP64__ */
7228 //*********************************************************************************
7229 // [public] systemWillShutdown
7231 // System shutdown and restart notification.
7232 //*********************************************************************************
7235 IOService::systemWillShutdown( IOOptionBits specifier
)
7237 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
7239 rootDomain
->acknowledgeSystemWillShutdown( this );
7244 // MARK: PM State Machine
7246 //*********************************************************************************
7247 // [private static] acquirePMRequest
7248 //*********************************************************************************
7251 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
7252 IOPMRequest
* active
)
7254 IOPMRequest
* request
;
7258 request
= IOPMRequest::create();
7260 request
->init( target
, requestType
);
7262 IOPMRequest
* root
= active
->getRootRequest();
7264 request
->attachRootRequest(root
);
7268 PM_ERROR("%s: No memory for PM request type 0x%x\n",
7269 target
->getName(), (uint32_t) requestType
);
7274 //*********************************************************************************
7275 // [private static] releasePMRequest
7276 //*********************************************************************************
7279 IOService::releasePMRequest( IOPMRequest
* request
)
7287 //*********************************************************************************
7288 // [private static] submitPMRequest
7289 //*********************************************************************************
7292 IOService::submitPMRequest( IOPMRequest
* request
)
7295 assert( gIOPMReplyQueue
);
7296 assert( gIOPMRequestQueue
);
7298 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7299 (long)request
->getType(), OBFUSCATE(request
),
7300 OBFUSCATE(request
->getTarget()), request
->getTarget()->getName(),
7301 OBFUSCATE(request
->fArg0
),
7302 OBFUSCATE(request
->fArg1
), OBFUSCATE(request
->fArg2
));
7304 if (request
->isReplyType()) {
7305 gIOPMReplyQueue
->queuePMRequest( request
);
7307 gIOPMRequestQueue
->queuePMRequest( request
);
7312 IOService::submitPMRequests( IOPMRequest
** requests
, IOItemCount count
)
7315 assert( count
> 0 );
7316 assert( gIOPMRequestQueue
);
7318 for (IOItemCount i
= 0; i
< count
; i
++) {
7319 IOPMRequest
* req
= requests
[i
];
7320 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7321 (long)req
->getType(), OBFUSCATE(req
),
7322 OBFUSCATE(req
->getTarget()), req
->getTarget()->getName(),
7323 OBFUSCATE(req
->fArg0
),
7324 OBFUSCATE(req
->fArg1
), OBFUSCATE(req
->fArg2
));
7327 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
7330 //*********************************************************************************
7331 // [private] actionPMRequestQueue
7333 // IOPMRequestQueue::checkForWork() passing a new request to the request target.
7334 //*********************************************************************************
7337 IOService::actionPMRequestQueue(
7338 IOPMRequest
* request
,
7339 IOPMRequestQueue
* queue
)
7344 // Work queue will immediately execute the request if the per-service
7345 // request queue is empty. Note pwrMgt is the target's IOServicePM.
7347 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
7349 // Calling PM without PMinit() is not allowed, fail the request.
7350 // Need to signal more when completing attached requests.
7352 PM_LOG("%s: PM not initialized\n", getName());
7353 PM_LOG1("[- %02x] %p [%p %s] !initialized\n",
7354 request
->getType(), OBFUSCATE(request
),
7355 OBFUSCATE(this), getName());
7357 more
= gIOPMCompletionQueue
->queuePMRequest(request
);
7359 gIOPMWorkQueue
->incrementProducerCount();
7366 //*********************************************************************************
7367 // [private] actionPMCompletionQueue
7369 // IOPMCompletionQueue::checkForWork() passing a completed request to the
7371 //*********************************************************************************
7374 IOService::actionPMCompletionQueue(
7375 IOPMRequest
* request
,
7376 IOPMCompletionQueue
* queue
)
7378 bool more
= (request
->getNextRequest() != 0);
7379 IOPMRequest
* root
= request
->getRootRequest();
7381 if (root
&& (root
!= request
)) {
7385 gIOPMWorkQueue
->incrementProducerCount();
7388 releasePMRequest( request
);
7392 //*********************************************************************************
7393 // [private] actionPMWorkQueueRetire
7395 // IOPMWorkQueue::checkForWork() passing a retired request to the request target.
7396 //*********************************************************************************
7399 IOService::actionPMWorkQueueRetire( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7401 assert(request
&& queue
);
7403 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7404 request
->getType(), OBFUSCATE(request
),
7405 OBFUSCATE(this), getName(),
7406 fMachineState
, gIOPMBusyRequestCount
);
7408 // Catch requests created by idleTimerExpired()
7409 if (request
->getType() == kIOPMRequestTypeActivityTickle
) {
7410 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
7412 if ((tickleFlags
& kTickleTypePowerDrop
) && fIdleTimerPeriod
) {
7414 } else if (tickleFlags
== (kTickleTypeActivity
| kTickleTypePowerRise
)) {
7415 // Invalidate any idle power drop that got queued while
7416 // processing this request.
7417 fIdleTimerGeneration
++;
7421 // When the completed request is linked, tell work queue there is
7422 // more work pending.
7424 return gIOPMCompletionQueue
->queuePMRequest( request
);
7427 //*********************************************************************************
7428 // [private] isPMBlocked
7430 // Check if machine state transition is blocked.
7431 //*********************************************************************************
7434 IOService::isPMBlocked( IOPMRequest
* request
, int count
)
7439 if (kIOPM_Finished
== fMachineState
) {
7443 if (kIOPM_DriverThreadCallDone
== fMachineState
) {
7444 // 5 = kDriverCallInformPreChange
7445 // 6 = kDriverCallInformPostChange
7446 // 7 = kDriverCallSetPowerState
7447 // 8 = kRootDomainInformPreChange
7448 if (fDriverCallBusy
) {
7449 reason
= 5 + fDriverCallReason
;
7454 // Waiting on driver's setPowerState() timeout.
7459 // Child or interested driver acks pending.
7460 if (fHeadNotePendingAcks
) {
7464 // Waiting on apps or priority power interest clients.
7465 if (fResponseArray
) {
7469 // Waiting on settle timer expiration.
7470 if (fSettleTimeUS
) {
7475 fWaitReason
= reason
;
7479 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7480 request
->getType(), OBFUSCATE(request
),
7481 OBFUSCATE(this), getName(),
7482 fMachineState
, reason
);
7491 //*********************************************************************************
7492 // [private] actionPMWorkQueueInvoke
7494 // IOPMWorkQueue::checkForWork() passing a request to the
7495 // request target for execution.
7496 //*********************************************************************************
7499 IOService::actionPMWorkQueueInvoke( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7504 assert(request
&& queue
);
7506 while (isPMBlocked(request
, loop
++) == false) {
7507 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7508 request
->getType(), OBFUSCATE(request
),
7509 OBFUSCATE(this), getName(), fMachineState
);
7511 gIOPMRequest
= request
;
7512 gIOPMWorkInvokeCount
++;
7514 // Every PM machine states must be handled in one of the cases below.
7516 switch (fMachineState
) {
7517 case kIOPM_Finished
:
7518 start_watchdog_timer();
7520 executePMRequest( request
);
7523 case kIOPM_OurChangeTellClientsPowerDown
:
7524 // Root domain might self cancel due to assertions.
7525 if (IS_ROOT_DOMAIN
) {
7526 bool cancel
= (bool) fDoNotPowerDown
;
7527 getPMRootDomain()->askChangeDownDone(
7528 &fHeadNoteChangeFlags
, &cancel
);
7529 fDoNotPowerDown
= cancel
;
7532 // askChangeDown() done, was it vetoed?
7533 if (!fDoNotPowerDown
) {
7534 // no, we can continue
7535 OurChangeTellClientsPowerDown();
7537 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7538 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7539 if (IS_ROOT_DOMAIN
) {
7540 // RootDomain already sent "WillSleep" to its clients
7541 tellChangeUp(fCurrentPowerState
);
7543 tellNoChangeDown(fHeadNotePowerState
);
7545 // mark the change note un-actioned
7546 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7552 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
7553 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7554 if (fDoNotPowerDown
) {
7555 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7556 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7557 if (IS_ROOT_DOMAIN
) {
7558 // RootDomain already sent "WillSleep" to its clients
7559 tellChangeUp(fCurrentPowerState
);
7561 tellNoChangeDown(fHeadNotePowerState
);
7563 // mark the change note un-actioned
7564 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7568 OurChangeTellUserPMPolicyPowerDown();
7572 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
7573 // PMRD: LastCallBeforeSleep notify done
7574 // Non-PMRD: tellChangeDown/kNotifyApps done
7575 if (fDoNotPowerDown
) {
7576 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7577 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7578 // no, tell clients we're back in the old state
7579 tellChangeUp(fCurrentPowerState
);
7580 // mark the change note un-actioned
7581 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7585 // yes, we can continue
7586 OurChangeTellPriorityClientsPowerDown();
7590 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
7591 OurChangeNotifyInterestedDriversWillChange();
7594 case kIOPM_OurChangeSetPowerState
:
7595 OurChangeSetPowerState();
7598 case kIOPM_OurChangeWaitForPowerSettle
:
7599 OurChangeWaitForPowerSettle();
7602 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
7603 OurChangeNotifyInterestedDriversDidChange();
7606 case kIOPM_OurChangeTellCapabilityDidChange
:
7607 OurChangeTellCapabilityDidChange();
7610 case kIOPM_OurChangeFinish
:
7614 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
7615 ParentChangeTellPriorityClientsPowerDown();
7618 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
7619 ParentChangeNotifyInterestedDriversWillChange();
7622 case kIOPM_ParentChangeSetPowerState
:
7623 ParentChangeSetPowerState();
7626 case kIOPM_ParentChangeWaitForPowerSettle
:
7627 ParentChangeWaitForPowerSettle();
7630 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7631 ParentChangeNotifyInterestedDriversDidChange();
7634 case kIOPM_ParentChangeTellCapabilityDidChange
:
7635 ParentChangeTellCapabilityDidChange();
7638 case kIOPM_ParentChangeAcknowledgePowerChange
:
7639 ParentChangeAcknowledgePowerChange();
7642 case kIOPM_DriverThreadCallDone
:
7643 switch (fDriverCallReason
) {
7644 case kDriverCallInformPreChange
:
7645 case kDriverCallInformPostChange
:
7646 notifyInterestedDriversDone();
7648 case kDriverCallSetPowerState
:
7649 notifyControllingDriverDone();
7651 case kRootDomainInformPreChange
:
7652 notifyRootDomainDone();
7655 panic("%s: bad call reason %x",
7656 getName(), fDriverCallReason
);
7660 case kIOPM_NotifyChildrenOrdered
:
7661 notifyChildrenOrdered();
7664 case kIOPM_NotifyChildrenDelayed
:
7665 notifyChildrenDelayed();
7668 case kIOPM_NotifyChildrenStart
:
7669 // pop notifyAll() state saved by notifyInterestedDriversDone()
7674 case kIOPM_SyncTellClientsPowerDown
:
7675 // Root domain might self cancel due to assertions.
7676 if (IS_ROOT_DOMAIN
) {
7677 bool cancel
= (bool) fDoNotPowerDown
;
7678 getPMRootDomain()->askChangeDownDone(
7679 &fHeadNoteChangeFlags
, &cancel
);
7680 fDoNotPowerDown
= cancel
;
7682 if (!fDoNotPowerDown
) {
7683 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7684 fOutOfBandParameter
= kNotifyApps
;
7685 tellChangeDown(fHeadNotePowerState
);
7687 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7688 // askChangeDown/kNotifyApps
7689 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7690 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7691 tellNoChangeDown(fHeadNotePowerState
);
7692 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7697 case kIOPM_SyncTellPriorityClientsPowerDown
:
7698 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7699 if (!fDoNotPowerDown
) {
7700 fMachineState
= kIOPM_SyncNotifyWillChange
;
7701 fOutOfBandParameter
= kNotifyPriority
;
7702 tellChangeDown(fHeadNotePowerState
);
7704 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7705 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7706 tellChangeUp(fCurrentPowerState
);
7707 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7712 case kIOPM_SyncNotifyWillChange
:
7713 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
) {
7714 fMachineState
= kIOPM_SyncFinish
;
7717 fMachineState
= kIOPM_SyncNotifyDidChange
;
7718 fDriverCallReason
= kDriverCallInformPreChange
;
7722 case kIOPM_SyncNotifyDidChange
:
7723 fIsPreChange
= false;
7725 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
7726 fMachineState
= kIOPM_SyncFinish
;
7728 assert(IS_ROOT_DOMAIN
);
7729 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7732 fDriverCallReason
= kDriverCallInformPostChange
;
7736 case kIOPM_SyncTellCapabilityDidChange
:
7737 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7740 case kIOPM_SyncFinish
:
7741 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
) {
7742 ParentChangeAcknowledgePowerChange();
7748 case kIOPM_TellCapabilityChangeDone
:
7750 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
) {
7751 MS_POP(); // tellSystemCapabilityChange()
7754 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7756 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
) {
7757 MS_POP(); // tellSystemCapabilityChange()
7760 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7762 tellClientsWithResponse( fOutOfBandMessage
);
7766 panic("PMWorkQueueInvoke: unknown machine state %x",
7772 if (fMachineState
== kIOPM_Finished
) {
7773 stop_watchdog_timer();
7782 //*********************************************************************************
7783 // [private] executePMRequest
7784 //*********************************************************************************
7787 IOService::executePMRequest( IOPMRequest
* request
)
7789 assert( kIOPM_Finished
== fMachineState
);
7791 switch (request
->getType()) {
7792 case kIOPMRequestTypePMStop
:
7793 handlePMstop( request
);
7796 case kIOPMRequestTypeAddPowerChild1
:
7797 addPowerChild1( request
);
7800 case kIOPMRequestTypeAddPowerChild2
:
7801 addPowerChild2( request
);
7804 case kIOPMRequestTypeAddPowerChild3
:
7805 addPowerChild3( request
);
7808 case kIOPMRequestTypeRegisterPowerDriver
:
7809 handleRegisterPowerDriver( request
);
7812 case kIOPMRequestTypeAdjustPowerState
:
7813 fAdjustPowerScheduled
= false;
7817 case kIOPMRequestTypePowerDomainWillChange
:
7818 handlePowerDomainWillChangeTo( request
);
7821 case kIOPMRequestTypePowerDomainDidChange
:
7822 handlePowerDomainDidChangeTo( request
);
7825 case kIOPMRequestTypeRequestPowerState
:
7826 case kIOPMRequestTypeRequestPowerStateOverride
:
7827 handleRequestPowerState( request
);
7830 case kIOPMRequestTypePowerOverrideOnPriv
:
7831 case kIOPMRequestTypePowerOverrideOffPriv
:
7832 handlePowerOverrideChanged( request
);
7835 case kIOPMRequestTypeActivityTickle
:
7836 handleActivityTickle( request
);
7839 case kIOPMRequestTypeSynchronizePowerTree
:
7840 handleSynchronizePowerTree( request
);
7843 case kIOPMRequestTypeSetIdleTimerPeriod
:
7845 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7846 fNextIdleTimerPeriod
= fIdleTimerPeriod
;
7847 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0)) {
7853 case kIOPMRequestTypeIgnoreIdleTimer
:
7854 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7857 case kIOPMRequestTypeQuiescePowerTree
:
7858 gIOPMWorkQueue
->finishQuiesceRequest(request
);
7862 panic("executePMRequest: unknown request type %x", request
->getType());
7866 //*********************************************************************************
7867 // [private] actionPMReplyQueue
7869 // IOPMRequestQueue::checkForWork() passing a reply-type request to the
7871 //*********************************************************************************
7874 IOService::actionPMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7878 assert( request
&& queue
);
7879 assert( request
->isReplyType());
7881 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7882 request
->getType(), OBFUSCATE(request
),
7883 OBFUSCATE(this), getName(), fMachineState
);
7885 switch (request
->getType()) {
7886 case kIOPMRequestTypeAllowPowerChange
:
7887 case kIOPMRequestTypeCancelPowerChange
:
7888 // Check if we are expecting this response.
7889 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7890 (int)(uintptr_t) request
->fArg1
)) {
7891 if (kIOPMRequestTypeCancelPowerChange
== request
->getType()) {
7892 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7893 // flag is set. Only root domain will set this flag.
7894 // However, there is one exception to this rule. User-space PM
7895 // policy may choose to cancel sleep even after all clients have
7896 // been notified that we will lower power.
7898 if ((fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7899 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7900 || ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0)) {
7901 fDoNotPowerDown
= true;
7903 OSString
* name
= (OSString
*) request
->fArg2
;
7904 getPMRootDomain()->pmStatsRecordApplicationResponse(
7905 gIOPMStatsResponseCancel
,
7906 name
? name
->getCStringNoCopy() : "", 0,
7907 0, (int)(uintptr_t) request
->fArg1
, 0);
7911 if (checkForDone()) {
7913 cleanClientResponses(false);
7917 // OSString containing app name in Arg2 must be released.
7918 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
) {
7919 OSObject
* obj
= (OSObject
*) request
->fArg2
;
7926 case kIOPMRequestTypeAckPowerChange
:
7927 more
= handleAcknowledgePowerChange( request
);
7930 case kIOPMRequestTypeAckSetPowerState
:
7931 if (fDriverTimer
== -1) {
7932 // driver acked while setPowerState() call is in-flight.
7933 // take this ack, return value from setPowerState() is irrelevant.
7934 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
7935 (uintptr_t) this, fDriverTimer
);
7937 } else if (fDriverTimer
> 0) {
7938 // expected ack, stop the timer
7941 getPMRootDomain()->reset_watchdog_timer(this, 0);
7943 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
7944 if (nsec
> LOG_SETPOWER_TIMES
) {
7945 getPMRootDomain()->pmStatsRecordApplicationResponse(
7946 gIOPMStatsDriverPSChangeSlow
,
7947 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
7948 NULL
, fHeadNotePowerState
);
7951 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
7956 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
7960 case kIOPMRequestTypeInterestChanged
:
7961 handleInterestChanged( request
);
7965 case kIOPMRequestTypeIdleCancel
:
7966 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
7967 || (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7968 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7969 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
7970 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
)) {
7971 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7972 PM_LOG2("%s: cancel from machine state %d\n",
7973 getName(), fMachineState
);
7974 fDoNotPowerDown
= true;
7975 // Stop waiting for app replys.
7976 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
7977 (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
) ||
7978 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
) ||
7979 (fMachineState
== kIOPM_SyncTellClientsPowerDown
)) {
7980 cleanClientResponses(false);
7986 case kIOPMRequestTypeChildNotifyDelayCancel
:
7987 if (fMachineState
== kIOPM_NotifyChildrenDelayed
) {
7988 PM_LOG2("%s: delay notify cancelled\n", getName());
7989 notifyChildrenDelayed();
7994 panic("PMReplyQueue: unknown reply type %x", request
->getType());
7997 more
|= gIOPMCompletionQueue
->queuePMRequest(request
);
7999 gIOPMWorkQueue
->incrementProducerCount();
8005 //*********************************************************************************
8006 // [private] assertPMDriverCall / deassertPMDriverCall
8007 //*********************************************************************************
8010 IOService::assertPMDriverCall(
8011 IOPMDriverCallEntry
* entry
,
8012 IOOptionBits options
,
8013 IOPMinformee
* inform
)
8015 IOService
* target
= 0;
8024 if (fLockedFlags
.PMStop
) {
8028 if (((options
& kIOPMADC_NoInactiveCheck
) == 0) && isInactive()) {
8033 if (!inform
->active
) {
8036 target
= inform
->whatObject
;
8037 if (target
->isInactive()) {
8042 entry
->thread
= current_thread();
8043 entry
->target
= target
;
8044 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8054 IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
8056 bool wakeup
= false;
8060 assert( !queue_empty(&fPMDriverCallQueue
));
8061 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8062 if (fLockedFlags
.PMDriverCallWait
) {
8069 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
8074 IOService::getBlockingDriverCall(thread_t
*thread
, const void **callMethod
)
8076 const IOPMDriverCallEntry
* entry
= NULL
;
8077 bool blocked
= false;
8083 if (current_thread() != gIOPMWatchDogThread
) {
8084 // Meant to be accessed only from watchdog thread
8089 entry
= qe_queue_first(&fPMDriverCallQueue
, IOPMDriverCallEntry
, link
);
8091 *thread
= entry
->thread
;
8092 *callMethod
= entry
->callMethod
;
8102 IOService::waitForPMDriverCall( IOService
* target
)
8104 const IOPMDriverCallEntry
* entry
;
8105 thread_t thread
= current_thread();
8106 AbsoluteTime deadline
;
8113 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
8115 // Target of interested driver call
8116 if (target
&& (target
!= entry
->target
)) {
8120 if (entry
->thread
== thread
) {
8122 PM_LOG("%s: %s(%s) on PM thread\n",
8123 fName
, __FUNCTION__
, target
? target
->getName() : "");
8124 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
8125 fName
, __FUNCTION__
, target
? target
->getName() : "");
8136 fLockedFlags
.PMDriverCallWait
= true;
8137 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
8138 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
8139 fLockedFlags
.PMDriverCallWait
= false;
8140 if (THREAD_TIMED_OUT
== waitResult
) {
8141 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
8148 //*********************************************************************************
8149 // [private] Debug helpers
8150 //*********************************************************************************
8153 IOService::getIOMessageString( uint32_t msg
)
8155 #define MSG_ENTRY(x) {(int) x, #x}
8157 static const IONamedValue msgNames
[] = {
8158 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
8159 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
8160 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
8161 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
8162 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
8163 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
8164 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
8165 MSG_ENTRY( kIOMessageCanSystemSleep
),
8166 MSG_ENTRY( kIOMessageSystemWillSleep
),
8167 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
8168 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
8169 MSG_ENTRY( kIOMessageSystemWillRestart
),
8170 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
8171 MSG_ENTRY( kIOMessageSystemCapabilityChange
),
8172 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep
),
8173 MSG_ENTRY( kIOMessageSystemPagingOff
),
8177 return IOFindNameForValue(msg
, msgNames
);
8182 // MARK: IOPMRequest
8184 //*********************************************************************************
8185 // IOPMRequest Class
8187 // Requests from PM clients, and also used for inter-object messaging within PM.
8188 //*********************************************************************************
8190 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
8193 IOPMRequest::create( void )
8195 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
8196 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
)) {
8204 IOPMRequest::init( IOService
* target
, IOOptionBits type
)
8206 if (!IOCommand::init()) {
8210 fRequestType
= type
;
8217 // Root node and root domain requests does not prevent the power tree from
8218 // becoming quiescent.
8220 fIsQuiesceBlocker
= ((fTarget
!= gIOPMRootNode
) &&
8221 (fTarget
!= IOService::getPMRootDomain()));
8227 IOPMRequest::reset( void )
8229 assert( fWorkWaitCount
== 0 );
8230 assert( fFreeWaitCount
== 0 );
8232 detachNextRequest();
8233 detachRootRequest();
8235 if (fCompletionAction
&& (fRequestType
== kIOPMRequestTypeQuiescePowerTree
)) {
8236 // Call the completion on PM work loop context
8237 fCompletionAction(fCompletionTarget
, fCompletionParam
);
8238 fCompletionAction
= 0;
8241 fRequestType
= kIOPMRequestTypeInvalid
;
8250 IOPMRequest::attachNextRequest( IOPMRequest
* next
)
8254 if (!fRequestNext
) {
8255 // Postpone the execution of the next request after
8257 fRequestNext
= next
;
8258 fRequestNext
->fWorkWaitCount
++;
8259 #if LOG_REQUEST_ATTACH
8260 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8261 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8262 fRequestNext
->fRequestType
,
8263 (uint32_t) fRequestNext
->fWorkWaitCount
,
8264 fTarget
->getName());
8272 IOPMRequest::detachNextRequest( void )
8277 assert(fRequestNext
->fWorkWaitCount
);
8278 if (fRequestNext
->fWorkWaitCount
) {
8279 fRequestNext
->fWorkWaitCount
--;
8281 #if LOG_REQUEST_ATTACH
8282 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8283 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8284 fRequestNext
->fRequestType
,
8285 (uint32_t) fRequestNext
->fWorkWaitCount
,
8286 fTarget
->getName());
8295 IOPMRequest::attachRootRequest( IOPMRequest
* root
)
8299 if (!fRequestRoot
) {
8300 // Delay the completion of the root request after
8302 fRequestRoot
= root
;
8303 fRequestRoot
->fFreeWaitCount
++;
8304 #if LOG_REQUEST_ATTACH
8305 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8306 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8307 (uint32_t) fRequestRoot
->fType
,
8308 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8309 fTarget
->getName());
8317 IOPMRequest::detachRootRequest( void )
8322 assert(fRequestRoot
->fFreeWaitCount
);
8323 if (fRequestRoot
->fFreeWaitCount
) {
8324 fRequestRoot
->fFreeWaitCount
--;
8326 #if LOG_REQUEST_ATTACH
8327 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8328 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8329 (uint32_t) fRequestRoot
->fType
,
8330 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8331 fTarget
->getName());
8340 // MARK: IOPMRequestQueue
8342 //*********************************************************************************
8343 // IOPMRequestQueue Class
8345 // Global queues. Queues are created once and never released.
8346 //*********************************************************************************
8348 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
8351 IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
8353 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
8354 if (me
&& !me
->init(inOwner
, inAction
)) {
8362 IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
8364 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
)) {
8368 queue_init(&fQueue
);
8369 fLock
= IOLockAlloc();
8374 IOPMRequestQueue::free( void )
8380 return IOEventSource::free();
8384 IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
8388 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8389 IOLockUnlock(fLock
);
8391 signalWorkAvailable();
8396 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
8400 assert(requests
&& count
);
8405 queue_enter(&fQueue
, next
, typeof(next
), fCommandChain
);
8407 IOLockUnlock(fLock
);
8409 signalWorkAvailable();
8414 IOPMRequestQueue::checkForWork( void )
8416 Action dqAction
= (Action
) action
;
8417 IOPMRequest
* request
;
8419 int dequeueCount
= 0;
8422 IOLockLock( fLock
);
8424 while (!queue_empty(&fQueue
)) {
8425 if (dequeueCount
++ >= kMaxDequeueCount
) {
8426 // Allow other queues a chance to work
8431 queue_remove_first(&fQueue
, request
, typeof(request
), fCommandChain
);
8432 IOLockUnlock(fLock
);
8433 target
= request
->getTarget();
8435 more
|= (*dqAction
)( target
, request
, this );
8436 IOLockLock( fLock
);
8439 IOLockUnlock( fLock
);
8444 // MARK: IOPMWorkQueue
8446 //*********************************************************************************
8447 // IOPMWorkQueue Class
8449 // Queue of IOServicePM objects, each with a queue of IOPMRequest sharing the
8451 //*********************************************************************************
8453 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
8456 IOPMWorkQueue::create( IOService
* inOwner
, Action invoke
, Action retire
)
8458 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
8459 if (me
&& !me
->init(inOwner
, invoke
, retire
)) {
8467 IOPMWorkQueue::init( IOService
* inOwner
, Action invoke
, Action retire
)
8469 if (!invoke
|| !retire
||
8470 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0)) {
8474 queue_init(&fWorkQueue
);
8476 fInvokeAction
= invoke
;
8477 fRetireAction
= retire
;
8478 fConsumerCount
= fProducerCount
= 0;
8484 IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
8486 queue_head_t
* requestQueue
;
8492 assert( onThread());
8493 assert( queue_next(&request
->fCommandChain
) ==
8494 queue_prev(&request
->fCommandChain
));
8496 gIOPMBusyRequestCount
++;
8498 if (request
->isQuiesceType()) {
8499 if ((request
->getTarget() == gIOPMRootNode
) && !fQuiesceStartTime
) {
8500 // Attach new quiesce request to all quiesce blockers in the queue
8501 fQuiesceStartTime
= mach_absolute_time();
8502 attachQuiesceRequest(request
);
8503 fQuiesceRequest
= request
;
8505 } else if (fQuiesceRequest
&& request
->isQuiesceBlocker()) {
8506 // Attach the new quiesce blocker to the blocked quiesce request
8507 request
->attachNextRequest(fQuiesceRequest
);
8510 // Add new request to the tail of the per-service request queue.
8511 // Then immediately check the request queue to minimize latency
8512 // if the queue was empty.
8514 requestQueue
= &pwrMgt
->RequestHead
;
8515 empty
= queue_empty(requestQueue
);
8516 queue_enter(requestQueue
, request
, typeof(request
), fCommandChain
);
8518 more
= checkRequestQueue(requestQueue
, &empty
);
8520 // Request just added is blocked, add its target IOServicePM
8521 // to the work queue.
8522 assert( queue_next(&pwrMgt
->WorkChain
) ==
8523 queue_prev(&pwrMgt
->WorkChain
));
8525 queue_enter(&fWorkQueue
, pwrMgt
, typeof(pwrMgt
), WorkChain
);
8527 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8528 fQueueLength
, pwrMgt
->Name
, OBFUSCATE(pwrMgt
));
8536 IOPMWorkQueue::checkRequestQueue( queue_head_t
* requestQueue
, bool * empty
)
8538 IOPMRequest
* request
;
8543 assert(!queue_empty(requestQueue
));
8545 request
= (typeof(request
))queue_first(requestQueue
);
8546 if (request
->isWorkBlocked()) {
8547 break; // request dispatch blocked on attached request
8549 target
= request
->getTarget();
8550 if (fInvokeAction
) {
8551 done
= (*fInvokeAction
)( target
, request
, this );
8553 PM_LOG("PM request 0x%x dropped\n", request
->getType());
8557 break; // PM state machine blocked
8559 assert(gIOPMBusyRequestCount
> 0);
8560 if (gIOPMBusyRequestCount
) {
8561 gIOPMBusyRequestCount
--;
8564 if (request
== fQuiesceRequest
) {
8565 fQuiesceRequest
= 0;
8568 queue_remove_first(requestQueue
, request
, typeof(request
), fCommandChain
);
8569 more
|= (*fRetireAction
)( target
, request
, this );
8570 done
= queue_empty(requestQueue
);
8576 // Retired a request that may unblock a previously visited request
8577 // that is still waiting on the work queue. Must trigger another
8586 IOPMWorkQueue::checkForWork( void )
8588 IOServicePM
* entry
;
8593 #if WORK_QUEUE_STATS
8594 fStatCheckForWork
++;
8597 // Iterate over all IOServicePM entries in the work queue,
8598 // and check each entry's request queue.
8600 while (fConsumerCount
!= fProducerCount
) {
8601 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8602 fProducerCount
, fConsumerCount
);
8604 fConsumerCount
= fProducerCount
;
8606 #if WORK_QUEUE_STATS
8607 if (queue_empty(&fWorkQueue
)) {
8612 uint32_t cachedWorkCount
= gIOPMWorkInvokeCount
;
8615 __IGNORE_WCASTALIGN(entry
= (typeof(entry
))queue_first(&fWorkQueue
));
8616 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
)) {
8617 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
8619 // Get next entry, points to head if current entry is last.
8620 __IGNORE_WCASTALIGN(next
= (typeof(next
))queue_next(&entry
->WorkChain
));
8622 // if request queue is empty, remove IOServicePM from work queue.
8624 assert(fQueueLength
);
8628 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8629 fQueueLength
, entry
->Name
, OBFUSCATE(entry
));
8630 queue_remove(&fWorkQueue
, entry
, typeof(entry
), WorkChain
);
8635 #if WORK_QUEUE_STATS
8636 if (cachedWorkCount
== gIOPMWorkInvokeCount
) {
8646 IOPMWorkQueue::signalWorkAvailable( void )
8649 IOEventSource::signalWorkAvailable();
8653 IOPMWorkQueue::incrementProducerCount( void )
8659 IOPMWorkQueue::attachQuiesceRequest( IOPMRequest
* quiesceRequest
)
8661 IOServicePM
* entry
;
8662 IOPMRequest
* request
;
8664 if (queue_empty(&fWorkQueue
)) {
8668 queue_iterate(&fWorkQueue
, entry
, typeof(entry
), WorkChain
)
8670 queue_iterate(&entry
->RequestHead
, request
, typeof(request
), fCommandChain
)
8672 // Attach the quiesce request to any request in the queue that
8673 // is not linked to a next request. These requests will block
8674 // the quiesce request.
8676 if (request
->isQuiesceBlocker()) {
8677 request
->attachNextRequest(quiesceRequest
);
8684 IOPMWorkQueue::finishQuiesceRequest( IOPMRequest
* quiesceRequest
)
8686 if (fQuiesceRequest
&& (quiesceRequest
== fQuiesceRequest
) &&
8687 (fQuiesceStartTime
!= 0)) {
8689 fQuiesceFinishTime
= mach_absolute_time();
8694 // MARK: IOPMCompletionQueue
8696 //*********************************************************************************
8697 // IOPMCompletionQueue Class
8698 //*********************************************************************************
8700 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
8702 IOPMCompletionQueue
*
8703 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
8705 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
8706 if (me
&& !me
->init(inOwner
, inAction
)) {
8714 IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
8716 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
)) {
8720 queue_init(&fQueue
);
8725 IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
8730 // unblock dependent request
8731 more
= request
->detachNextRequest();
8732 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8737 IOPMCompletionQueue::checkForWork( void )
8739 Action dqAction
= (Action
) action
;
8740 IOPMRequest
* request
;
8745 request
= (typeof(request
))queue_first(&fQueue
);
8746 while (!queue_end(&fQueue
, (queue_entry_t
) request
)) {
8747 next
= (typeof(next
))queue_next(&request
->fCommandChain
);
8748 if (!request
->isFreeBlocked()) {
8749 queue_remove(&fQueue
, request
, typeof(request
), fCommandChain
);
8750 target
= request
->getTarget();
8752 more
|= (*dqAction
)( target
, request
, this );
8761 // MARK: IOServicePM
8763 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8765 //*********************************************************************************
8768 // Serialize IOServicePM for debugging.
8769 //*********************************************************************************
8772 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8774 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8776 dict
->setObject(key
, num
);
8782 IOServicePM::gatedSerialize( OSSerialize
* s
) const
8784 OSDictionary
* dict
;
8786 int powerClamp
= -1;
8789 if (IdleTimerPeriod
) {
8793 if (PMActions
.parameter
& kPMActionsFlagLimitPower
) {
8796 if (PMActions
.parameter
&
8797 (kPMActionsFlagIsDisplayWrangler
| kPMActionsFlagIsGraphicsDevice
)) {
8802 #if WORK_QUEUE_STATS
8803 if (gIOPMRootNode
== ControllingDriver
) {
8809 dict
= OSDictionary::withDictionary(
8810 PowerClients
, PowerClients
->getCount() + dictSize
);
8812 dict
= OSDictionary::withCapacity(dictSize
);
8816 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8817 setPMProperty(dict
, "CapabilityFlags", CurrentCapabilityFlags
);
8818 if (NumberOfPowerStates
) {
8819 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
- 1);
8821 if (DesiredPowerState
!= CurrentPowerState
) {
8822 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8824 if (kIOPM_Finished
!= MachineState
) {
8825 setPMProperty(dict
, "MachineState", MachineState
);
8827 if (DeviceOverrideEnabled
) {
8828 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8830 if (powerClamp
>= 0) {
8831 setPMProperty(dict
, "PowerClamp", powerClamp
);
8834 if (IdleTimerPeriod
) {
8839 clock_get_uptime(&now
);
8841 // The idle timer period in milliseconds
8842 setPMProperty(dict
, "IdleTimerPeriod", NextIdleTimerPeriod
* 1000ULL);
8844 // Number of tickles since the last idle timer expiration
8845 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8847 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
)) {
8848 // Milliseconds since the last activity tickle
8850 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8851 absolutetime_to_nanoseconds(delta
, &nsecs
);
8852 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
8855 if (!IdleTimerStopped
&& AbsoluteTime_to_scalar(&IdleTimerStartTime
)) {
8856 // Idle timer elapsed time in milliseconds
8858 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
8859 absolutetime_to_nanoseconds(delta
, &nsecs
);
8860 setPMProperty(dict
, "IdleTimerElapsedTime", NS_TO_MS(nsecs
));
8864 #if WORK_QUEUE_STATS
8865 if (gIOPMRootNode
== Owner
) {
8866 setPMProperty(dict
, "WQ-CheckForWork",
8867 gIOPMWorkQueue
->fStatCheckForWork
);
8868 setPMProperty(dict
, "WQ-ScanEntries",
8869 gIOPMWorkQueue
->fStatScanEntries
);
8870 setPMProperty(dict
, "WQ-QueueEmpty",
8871 gIOPMWorkQueue
->fStatQueueEmpty
);
8872 setPMProperty(dict
, "WQ-NoWorkDone",
8873 gIOPMWorkQueue
->fStatNoWorkDone
);
8877 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
) {
8878 // Don't report advisory tickle when it has no influence
8879 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
8882 ok
= dict
->serialize(s
);
8886 return ok
? kIOReturnSuccess
: kIOReturnNoMemory
;
8890 IOServicePM::serialize( OSSerialize
* s
) const
8892 IOReturn ret
= kIOReturnNotReady
;
8894 if (gIOPMWatchDogThread
== current_thread()) {
8895 // Calling without lock as this data is collected for debug purpose, before reboot.
8896 // The workloop is probably already hung in state machine.
8897 ret
= gatedSerialize(s
);
8898 } else if (gIOPMWorkLoop
) {
8899 ret
= gIOPMWorkLoop
->runAction(
8900 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
8901 (OSObject
*) this, (void *) s
);
8904 return kIOReturnSuccess
== ret
;
8908 IOServicePM::pmPrint(
8911 uintptr_t param2
) const
8913 gPlatform
->PMLog(Name
, event
, param1
, param2
);
8917 IOServicePM::pmTrace(
8921 uintptr_t param2
) const
8923 uintptr_t nameAsArg
= 0;
8925 assert(event
< KDBG_CODE_MAX
);
8926 assert((eventFunc
& ~KDBG_FUNC_MASK
) == 0);
8928 // Copy the first characters of the name into an uintptr_t.
8929 // NULL termination is not required.
8930 strncpy((char*)&nameAsArg
, Name
, sizeof(nameAsArg
));
8932 IOTimeStampConstant(IODBG_POWER(event
) | eventFunc
, nameAsArg
, (uintptr_t)Owner
->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1
)), (uintptr_t)(OBFUSCATE(param2
)));