2 * Copyright (c) 1998-2016 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/assert.h>
30 #include <IOKit/IOKitDebug.h>
31 #include <IOKit/IOLib.h>
32 #include <IOKit/IOMessage.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IOEventSource.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/IOCommand.h>
38 #include <IOKit/IOTimeStamp.h>
39 #include <IOKit/IOReportMacros.h>
41 #include <IOKit/pwr_mgt/IOPMlog.h>
42 #include <IOKit/pwr_mgt/IOPMinformee.h>
43 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
44 #include <IOKit/pwr_mgt/IOPowerConnection.h>
45 #include <IOKit/pwr_mgt/RootDomain.h>
46 #include <IOKit/pwr_mgt/IOPMPrivate.h>
49 #include <sys/proc_internal.h>
50 #include <sys/sysctl.h>
51 #include <libkern/OSDebug.h>
52 #include <kern/thread.h>
54 // Required for notification instrumentation
55 #include "IOServicePrivate.h"
56 #include "IOServicePMPrivate.h"
57 #include "IOKitKernelInternal.h"
60 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
61 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
62 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
63 static void tellAppClientApplier(OSObject
* object
, void * arg
);
65 static uint64_t computeTimeDeltaNS( const AbsoluteTime
* start
)
70 clock_get_uptime(&now
);
71 SUB_ABSOLUTETIME(&now
, start
);
72 absolutetime_to_nanoseconds(now
, &nsec
);
77 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
80 //******************************************************************************
82 //******************************************************************************
84 static bool gIOPMInitialized
= false;
85 static uint32_t gIOPMBusyRequestCount
= 0;
86 static uint32_t gIOPMWorkInvokeCount
= 0;
87 static uint32_t gIOPMTickleGeneration
= 0;
88 static IOWorkLoop
* gIOPMWorkLoop
= 0;
89 static IOPMRequestQueue
* gIOPMRequestQueue
= 0;
90 static IOPMRequestQueue
* gIOPMReplyQueue
= 0;
91 static IOPMWorkQueue
* gIOPMWorkQueue
= 0;
92 static IOPMCompletionQueue
* gIOPMCompletionQueue
= 0;
93 static IOPMRequest
* gIOPMRequest
= 0;
94 static IOService
* gIOPMRootNode
= 0;
95 static IOPlatformExpert
* gPlatform
= 0;
97 static char gIOSpinDumpKextName
[128];
98 static char gIOSpinDumpDelayType
[16];
99 static uint32_t gIOSpinDumpDelayDuration
= 0;
101 static SYSCTL_STRING(_debug
, OID_AUTO
, swd_kext_name
,
102 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
103 &gIOSpinDumpKextName
, sizeof(gIOSpinDumpKextName
), "");
104 static SYSCTL_STRING(_debug
, OID_AUTO
, swd_delay_type
,
105 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
106 &gIOSpinDumpDelayType
, sizeof(gIOSpinDumpDelayType
), "");
107 static SYSCTL_INT(_debug
, OID_AUTO
, swd_delay_duration
,
108 CTLFLAG_RW
| CTLFLAG_KERN
| CTLFLAG_LOCKED
,
109 &gIOSpinDumpDelayDuration
, 0, "");
111 const OSSymbol
* gIOPMPowerClientDevice
= 0;
112 const OSSymbol
* gIOPMPowerClientDriver
= 0;
113 const OSSymbol
* gIOPMPowerClientChildProxy
= 0;
114 const OSSymbol
* gIOPMPowerClientChildren
= 0;
115 const OSSymbol
* gIOPMPowerClientRootDomain
= 0;
117 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= 0;
118 static bool gIOPMAdvisoryTickleEnabled
= true;
119 static thread_t gIOPMWatchDogThread
= NULL
;
120 uint32_t gCanSleepTimeout
= 0;
122 static uint32_t getPMRequestType( void )
124 uint32_t type
= kIOPMRequestTypeInvalid
;
126 type
= gIOPMRequest
->getType();
130 static IOPMRequestTag
getPMRequestTag( void )
132 IOPMRequestTag tag
= 0;
134 (gIOPMRequest
->getType() == kIOPMRequestTypeRequestPowerStateOverride
))
136 tag
= gIOPMRequest
->fRequestTag
;
141 SYSCTL_UINT(_kern
, OID_AUTO
, pmtimeout
, CTLFLAG_RW
| CTLFLAG_LOCKED
, &gCanSleepTimeout
, 0, "Power Management Timeout");
143 //******************************************************************************
145 //******************************************************************************
147 #define PM_ERROR(x...) do { kprintf(x);IOLog(x); \
149 #define PM_LOG(x...) do { kprintf(x); } while (false)
151 #define PM_LOG1(x...) do { \
152 if (kIOLogDebugPower & gIOKitDebug) \
153 kprintf(x); } while (false)
155 #define PM_LOG2(x...) do { \
156 if (kIOLogDebugPower & gIOKitDebug) \
157 kprintf(x); } while (false)
160 #define PM_LOG3(x...) do { kprintf(x); } while (false)
162 #define PM_LOG3(x...)
165 #define RD_LOG(x...) do { \
166 if ((kIOLogPMRootDomain & gIOKitDebug) && \
167 (getPMRootDomain() == this)) { \
168 kprintf("PMRD: " x); \
170 #define PM_ASSERT_IN_GATE(x) \
172 assert(gIOPMWorkLoop->inGate()); \
175 #define PM_LOCK() IOLockLock(fPMLock)
176 #define PM_UNLOCK() IOLockUnlock(fPMLock)
177 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
178 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
180 #define us_per_s 1000000
181 #define ns_per_us 1000
182 #define k30Seconds (30*us_per_s)
183 #define k5Seconds ( 5*us_per_s)
184 #define kCanSleepMaxTimeReq k30Seconds
185 #define kMaxTimeRequested k30Seconds
186 #define kMinAckTimeoutTicks (10*1000000)
187 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
188 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
189 #define kPwrMgtKey "IOPowerManagement"
191 #define OUR_PMLog(t, a, b) do { \
193 if (gIOKitDebug & kIOLogPower) \
194 pwrMgt->pmPrint(t, a, b); \
195 if (gIOKitTrace & kIOTracePowerMgmt) \
196 pwrMgt->pmTrace(t, DBG_FUNC_NONE, a, b); \
200 #define OUR_PMLogFuncStart(t, a, b) do { \
202 if (gIOKitDebug & kIOLogPower) \
203 pwrMgt->pmPrint(t, a, b); \
204 if (gIOKitTrace & kIOTracePowerMgmt) \
205 pwrMgt->pmTrace(t, DBG_FUNC_START, a, b); \
209 #define OUR_PMLogFuncEnd(t, a, b) do { \
211 if (gIOKitDebug & kIOLogPower) \
212 pwrMgt->pmPrint(-t, a, b); \
213 if (gIOKitTrace & kIOTracePowerMgmt) \
214 pwrMgt->pmTrace(t, DBG_FUNC_END, a, b); \
218 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
219 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
221 #define SUPPORT_IDLE_CANCEL 1
223 #define kIOPMPowerStateMax 0xFFFFFFFF
224 #define kInvalidTicklePowerState kIOPMPowerStateMax
226 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
228 #define IS_PM_ROOT (this == gIOPMRootNode)
229 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
230 #define IS_POWER_DROP (StateOrder(fHeadNotePowerState) < StateOrder(fCurrentPowerState))
231 #define IS_POWER_RISE (StateOrder(fHeadNotePowerState) > StateOrder(fCurrentPowerState))
233 // log setPowerStates longer than (ns):
234 #if defined(__i386__) || defined(__x86_64__)
235 #define LOG_SETPOWER_TIMES (300ULL * 1000ULL * 1000ULL)
237 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
239 // log app responses longer than (ns):
240 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
241 // use message tracer to log messages longer than (ns):
242 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
245 kReserveDomainPower
= 1
249 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
250 assert(kIOPM_BadMachineState != n); \
251 fSavedMachineState = n; } while (false)
254 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
255 fMachineState = fSavedMachineState; \
256 fSavedMachineState = kIOPM_BadMachineState; } while (false)
258 #define PM_ACTION_0(a) \
259 do { if (fPMActions.a) { \
260 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
263 #define PM_ACTION_2(a, x, y) \
264 do { if (fPMActions.a) { \
265 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, \
266 getPMRequestTag()); } \
269 #define PM_ACTION_3(a, x, y, z) \
270 do { if (fPMActions.a) { \
271 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, z); } \
274 static OSNumber
* copyClientIDForNotification(
276 IOPMInterestContext
*context
);
278 static void logClientIDForNotification(
280 IOPMInterestContext
*context
,
281 const char *logString
);
283 //*********************************************************************************
286 // Check kgmacros after modifying machine states.
287 //*********************************************************************************
292 kIOPM_OurChangeTellClientsPowerDown
= 1,
293 kIOPM_OurChangeTellUserPMPolicyPowerDown
= 2,
294 kIOPM_OurChangeTellPriorityClientsPowerDown
= 3,
295 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 4,
296 kIOPM_OurChangeSetPowerState
= 5,
297 kIOPM_OurChangeWaitForPowerSettle
= 6,
298 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 7,
299 kIOPM_OurChangeTellCapabilityDidChange
= 8,
300 kIOPM_OurChangeFinish
= 9,
302 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
303 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
304 kIOPM_ParentChangeSetPowerState
= 12,
305 kIOPM_ParentChangeWaitForPowerSettle
= 13,
306 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
307 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
308 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
310 kIOPM_NotifyChildrenStart
= 17,
311 kIOPM_NotifyChildrenOrdered
= 18,
312 kIOPM_NotifyChildrenDelayed
= 19,
313 kIOPM_SyncTellClientsPowerDown
= 20,
314 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
315 kIOPM_SyncNotifyWillChange
= 22,
316 kIOPM_SyncNotifyDidChange
= 23,
317 kIOPM_SyncTellCapabilityDidChange
= 24,
318 kIOPM_SyncFinish
= 25,
319 kIOPM_TellCapabilityChangeDone
= 26,
320 kIOPM_DriverThreadCallDone
= 27,
322 kIOPM_BadMachineState
= 0xFFFFFFFF
325 //*********************************************************************************
328 // Initialize power management.
329 //*********************************************************************************
331 void IOService::PMinit( void )
335 if ( !gIOPMInitialized
)
337 gPlatform
= getPlatform();
338 gIOPMWorkLoop
= IOWorkLoop::workLoop();
341 gIOPMRequestQueue
= IOPMRequestQueue::create(
342 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
343 this, &IOService::actionPMRequestQueue
));
345 gIOPMReplyQueue
= IOPMRequestQueue::create(
346 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
347 this, &IOService::actionPMReplyQueue
));
349 gIOPMWorkQueue
= IOPMWorkQueue::create(this,
350 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
351 &IOService::actionPMWorkQueueInvoke
),
352 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
353 &IOService::actionPMWorkQueueRetire
));
355 gIOPMCompletionQueue
= IOPMCompletionQueue::create(
356 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
357 this, &IOService::actionPMCompletionQueue
));
359 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
362 gIOPMRequestQueue
->release();
363 gIOPMRequestQueue
= 0;
366 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
369 gIOPMReplyQueue
->release();
373 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
376 gIOPMWorkQueue
->release();
380 // Must be added after the work queue, which pushes request
381 // to the completion queue without signaling the work loop.
382 if (gIOPMWorkLoop
->addEventSource(gIOPMCompletionQueue
) !=
385 gIOPMCompletionQueue
->release();
386 gIOPMCompletionQueue
= 0;
389 gIOPMPowerClientDevice
=
390 OSSymbol::withCStringNoCopy( "DevicePowerState" );
392 gIOPMPowerClientDriver
=
393 OSSymbol::withCStringNoCopy( "DriverPowerState" );
395 gIOPMPowerClientChildProxy
=
396 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
398 gIOPMPowerClientChildren
=
399 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
401 gIOPMPowerClientAdvisoryTickle
=
402 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
404 gIOPMPowerClientRootDomain
=
405 OSSymbol::withCStringNoCopy( "RootDomainPower" );
407 gIOSpinDumpKextName
[0] = '\0';
408 gIOSpinDumpDelayType
[0] = '\0';
411 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMCompletionQueue
)
412 gIOPMInitialized
= true;
414 if (!gIOPMInitialized
)
417 pwrMgt
= new IOServicePM
;
419 setProperty(kPwrMgtKey
, pwrMgt
);
421 queue_init(&pwrMgt
->WorkChain
);
422 queue_init(&pwrMgt
->RequestHead
);
423 queue_init(&pwrMgt
->PMDriverCallQueue
);
426 fPMLock
= IOLockAlloc();
427 fInterestedDrivers
= new IOPMinformeeList
;
428 fInterestedDrivers
->initialize();
429 fDesiredPowerState
= kPowerStateZero
;
430 fDeviceDesire
= kPowerStateZero
;
431 fInitialPowerChange
= true;
432 fInitialSetPowerState
= true;
433 fPreviousRequestPowerFlags
= 0;
434 fDeviceOverrideEnabled
= false;
435 fMachineState
= kIOPM_Finished
;
436 fSavedMachineState
= kIOPM_BadMachineState
;
437 fIdleTimerMinPowerState
= kPowerStateZero
;
438 fActivityLock
= IOLockAlloc();
439 fStrictTreeOrder
= false;
440 fActivityTicklePowerState
= kInvalidTicklePowerState
;
441 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
442 fControllingDriver
= NULL
;
444 fNumberOfPowerStates
= 0;
445 fCurrentPowerState
= kPowerStateZero
;
446 fParentsCurrentPowerFlags
= 0;
447 fMaxPowerState
= kPowerStateZero
;
449 fParentsKnowState
= false;
451 fResponseArray
= NULL
;
452 fNotifyClientArray
= NULL
;
453 fCurrentPowerConsumption
= kIOPMUnknown
;
454 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
456 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot()))
458 gIOPMRootNode
= this;
459 fParentsKnowState
= true;
461 else if (getProperty(kIOPMResetPowerStateOnWakeKey
) == kOSBooleanTrue
)
463 fResetPowerStateOnWake
= true;
468 fWatchdogTimer
= thread_call_allocate(
469 &IOService::watchdog_timer_expired
, (thread_call_param_t
)this);
472 fAckTimer
= thread_call_allocate(
473 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
474 fSettleTimer
= thread_call_allocate(
475 &settle_timer_expired
, (thread_call_param_t
)this);
476 fIdleTimer
= thread_call_allocate(
477 &idle_timer_expired
, (thread_call_param_t
)this);
478 fDriverCallEntry
= thread_call_allocate(
479 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
480 assert(fDriverCallEntry
);
481 if (kIOKextSpinDump
& gIOKitDebug
)
483 fSpinDumpTimer
= thread_call_allocate(
484 &IOService::spindump_timer_expired
, (thread_call_param_t
)this);
487 // Check for powerChangeDone override.
488 if (OSMemberFunctionCast(void (*)(void),
489 getResourceService(), &IOService::powerChangeDone
) !=
490 OSMemberFunctionCast(void (*)(void),
491 this, &IOService::powerChangeDone
))
493 fPCDFunctionOverride
= true;
497 IOPMprot
* prot
= new IOPMprot
;
501 prot
->ourName
= fName
;
502 prot
->thePlatform
= gPlatform
;
507 pm_vars
= (void *) (uintptr_t) true;
514 //*********************************************************************************
517 // Free the data created by PMinit. Only called from IOService::free().
518 //*********************************************************************************
520 void IOService::PMfree( void )
527 assert(fMachineState
== kIOPM_Finished
);
528 assert(fInsertInterestSet
== NULL
);
529 assert(fRemoveInterestSet
== NULL
);
530 assert(fNotifyChildArray
== NULL
);
531 assert(queue_empty(&pwrMgt
->RequestHead
));
532 assert(queue_empty(&fPMDriverCallQueue
));
534 if (fWatchdogTimer
) {
535 thread_call_cancel(fWatchdogTimer
);
536 thread_call_free(fWatchdogTimer
);
537 fWatchdogTimer
= NULL
;
540 if ( fSettleTimer
) {
541 thread_call_cancel(fSettleTimer
);
542 thread_call_free(fSettleTimer
);
546 thread_call_cancel(fAckTimer
);
547 thread_call_free(fAckTimer
);
551 thread_call_cancel(fIdleTimer
);
552 thread_call_free(fIdleTimer
);
555 if ( fDriverCallEntry
) {
556 thread_call_free(fDriverCallEntry
);
557 fDriverCallEntry
= NULL
;
559 if ( fSpinDumpTimer
) {
560 thread_call_cancel(fSpinDumpTimer
);
561 thread_call_free(fSpinDumpTimer
);
562 fSpinDumpTimer
= NULL
;
568 if ( fActivityLock
) {
569 IOLockFree(fActivityLock
);
570 fActivityLock
= NULL
;
572 if ( fInterestedDrivers
) {
573 fInterestedDrivers
->release();
574 fInterestedDrivers
= NULL
;
576 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
577 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
578 fDriverCallParamPtr
= 0;
579 fDriverCallParamSlots
= 0;
581 if ( fResponseArray
) {
582 fResponseArray
->release();
583 fResponseArray
= NULL
;
585 if ( fNotifyClientArray
) {
586 fNotifyClientArray
->release();
587 fNotifyClientArray
= NULL
;
589 if (fPowerStates
&& fNumberOfPowerStates
) {
590 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
591 fNumberOfPowerStates
= 0;
595 fPowerClients
->release();
612 void IOService::PMDebug( uint32_t event
, uintptr_t param1
, uintptr_t param2
)
614 OUR_PMLog(event
, param1
, param2
);
617 //*********************************************************************************
618 // [public] joinPMtree
620 // A policy-maker calls its nub here when initializing, to be attached into
621 // the power management hierarchy. The default function is to call the
622 // platform expert, which knows how to do it. This method is overridden
623 // by a nub subclass which may either know how to do it, or may need to
624 // take other action.
626 // This may be the only "power management" method used in a nub,
627 // meaning it may not be initialized for power management.
628 //*********************************************************************************
630 void IOService::joinPMtree( IOService
* driver
)
632 IOPlatformExpert
* platform
;
634 platform
= getPlatform();
635 assert(platform
!= 0);
636 platform
->PMRegisterDevice(this, driver
);
640 //*********************************************************************************
641 // [deprecated] youAreRoot
643 // Power Managment is informing us that we are the root power domain.
644 //*********************************************************************************
646 IOReturn
IOService::youAreRoot( void )
650 #endif /* !__LP64__ */
652 //*********************************************************************************
655 // Immediately stop driver callouts. Schedule an async stop request to detach
657 //*********************************************************************************
659 void IOService::PMstop( void )
661 IOPMRequest
* request
;
668 if (fLockedFlags
.PMStop
)
670 PM_LOG2("%s: PMstop() already stopped\n", fName
);
675 // Inhibit future driver calls.
676 fLockedFlags
.PMStop
= true;
678 // Wait for all prior driver calls to finish.
679 waitForPMDriverCall();
683 // The rest of the work is performed async.
684 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
687 PM_LOG2("%s: %p PMstop\n", getName(), OBFUSCATE(this));
688 submitPMRequest( request
);
692 //*********************************************************************************
693 // [private] handlePMstop
695 // Disconnect the node from all parents and children in the power plane.
696 //*********************************************************************************
698 void IOService::handlePMstop( IOPMRequest
* request
)
702 IOPowerConnection
* connection
;
703 IOService
* theChild
;
704 IOService
* theParent
;
707 PM_LOG2("%s: %p %s start\n", getName(), OBFUSCATE(this), __FUNCTION__
);
709 // remove driver from prevent system sleep lists
710 getPMRootDomain()->updatePreventIdleSleepList(this, false);
711 getPMRootDomain()->updatePreventSystemSleepList(this, false);
713 // remove the property
714 removeProperty(kPwrMgtKey
);
717 iter
= getParentIterator(gIOPowerPlane
);
720 while ( (next
= iter
->getNextObject()) )
722 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
724 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
727 theParent
->removePowerChild(connection
);
728 theParent
->release();
735 // detach IOConnections
736 detachAbove( gIOPowerPlane
);
738 // no more power state changes
739 fParentsKnowState
= false;
742 iter
= getChildIterator(gIOPowerPlane
);
745 while ( (next
= iter
->getNextObject()) )
747 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
749 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
752 // detach nub from child
753 connection
->detachFromChild(theChild
, gIOPowerPlane
);
756 // detach us from nub
757 detachFromChild(connection
, gIOPowerPlane
);
763 // Remove all interested drivers from the list, including the power
764 // controlling driver.
766 // Usually, the controlling driver and the policy-maker functionality
767 // are implemented by the same object, and without the deregistration,
768 // the object will be holding an extra retain on itself, and cannot
771 if ( fInterestedDrivers
)
773 IOPMinformeeList
* list
= fInterestedDrivers
;
777 while ((item
= list
->firstInList()))
779 list
->removeFromList(item
->whatObject
);
784 // Clear idle period to prevent idleTimerExpired() from servicing
785 // idle timer expirations.
787 fIdleTimerPeriod
= 0;
788 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
791 PM_LOG2("%s: %p %s done\n", getName(), OBFUSCATE(this), __FUNCTION__
);
794 //*********************************************************************************
795 // [public] addPowerChild
797 // Power Management is informing us who our children are.
798 //*********************************************************************************
800 IOReturn
IOService::addPowerChild( IOService
* child
)
802 IOPowerConnection
* connection
= 0;
803 IOPMRequest
* requests
[3] = {0, 0, 0};
808 return kIOReturnBadArgument
;
810 if (!initialized
|| !child
->initialized
)
811 return IOPMNotYetInitialized
;
813 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
816 // Is this child already one of our children?
818 iter
= child
->getParentIterator( gIOPowerPlane
);
821 IORegistryEntry
* entry
;
824 while ((next
= iter
->getNextObject()))
826 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
827 isChild(entry
, gIOPowerPlane
))
837 PM_LOG("%s: %s (%p) is already a child\n",
838 getName(), child
->getName(), OBFUSCATE(child
));
842 // Add the child to the power plane immediately, but the
843 // joining connection is marked as not ready.
844 // We want the child to appear in the power plane before
845 // returning to the caller, but don't want the caller to
846 // block on the PM work loop.
848 connection
= new IOPowerConnection
;
852 // Create a chain of PM requests to perform the bottom-half
853 // work from the PM work loop.
855 requests
[0] = acquirePMRequest(
857 /* type */ kIOPMRequestTypeAddPowerChild1
);
859 requests
[1] = acquirePMRequest(
861 /* type */ kIOPMRequestTypeAddPowerChild2
);
863 requests
[2] = acquirePMRequest(
865 /* type */ kIOPMRequestTypeAddPowerChild3
);
867 if (!requests
[0] || !requests
[1] || !requests
[2])
870 requests
[0]->attachNextRequest( requests
[1] );
871 requests
[1]->attachNextRequest( requests
[2] );
874 connection
->start(this);
875 connection
->setAwaitingAck(false);
876 connection
->setReadyFlag(false);
878 attachToChild( connection
, gIOPowerPlane
);
879 connection
->attachToChild( child
, gIOPowerPlane
);
881 // connection needs to be released
882 requests
[0]->fArg0
= connection
;
883 requests
[1]->fArg0
= connection
;
884 requests
[2]->fArg0
= connection
;
886 submitPMRequests( requests
, 3 );
887 return kIOReturnSuccess
;
891 if (connection
) connection
->release();
892 if (requests
[0]) releasePMRequest(requests
[0]);
893 if (requests
[1]) releasePMRequest(requests
[1]);
894 if (requests
[2]) releasePMRequest(requests
[2]);
896 // Silent failure, to prevent platform drivers from adding the child
897 // to the root domain.
899 return kIOReturnSuccess
;
902 //*********************************************************************************
903 // [private] addPowerChild1
905 // Step 1/3 of adding a power child. Called on the power parent.
906 //*********************************************************************************
908 void IOService::addPowerChild1( IOPMRequest
* request
)
910 IOPMPowerStateIndex tempDesire
= kPowerStateZero
;
912 // Make us temporary usable before adding the child.
915 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
917 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
919 tempDesire
= fHighestPowerState
;
922 if ((tempDesire
!= kPowerStateZero
) &&
923 (IS_PM_ROOT
|| (StateOrder(fMaxPowerState
) >= StateOrder(tempDesire
))))
925 adjustPowerState(tempDesire
);
929 //*********************************************************************************
930 // [private] addPowerChild2
932 // Step 2/3 of adding a power child. Called on the joining child.
933 // Execution blocked behind addPowerChild1.
934 //*********************************************************************************
936 void IOService::addPowerChild2( IOPMRequest
* request
)
938 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
940 IOPMPowerFlags powerFlags
;
942 unsigned long powerState
;
943 unsigned long tempDesire
;
946 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
948 if (!parent
|| !inPlane(gIOPowerPlane
))
950 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
954 // Parent will be waiting for us to complete this stage.
955 // It is safe to directly access parent's vars.
957 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
958 powerState
= parent
->fCurrentPowerState
;
961 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
965 // Set our power parent.
967 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
969 setParentInfo( powerFlags
, connection
, knowsState
);
971 connection
->setReadyFlag(true);
973 if ( fControllingDriver
&& fParentsKnowState
)
975 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
976 // initially change into the state we are already in
977 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
978 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
979 adjustPowerState(tempDesire
);
982 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
985 //*********************************************************************************
986 // [private] addPowerChild3
988 // Step 3/3 of adding a power child. Called on the parent.
989 // Execution blocked behind addPowerChild2.
990 //*********************************************************************************
992 void IOService::addPowerChild3( IOPMRequest
* request
)
994 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
996 IOPMrootDomain
* rootDomain
= getPMRootDomain();
999 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
1001 if (child
&& inPlane(gIOPowerPlane
))
1003 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder"))
1005 PM_LOG1("%s: strict PM order enforced\n", getName());
1006 fStrictTreeOrder
= true;
1010 rootDomain
->joinAggressiveness( child
);
1014 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1017 connection
->release();
1021 //*********************************************************************************
1022 // [deprecated] setPowerParent
1024 // Power Management is informing us who our parent is.
1025 // If we have a controlling driver, find out, given our newly-informed
1026 // power domain state, what state it would be in, and then tell it
1027 // to assume that state.
1028 //*********************************************************************************
1030 IOReturn
IOService::setPowerParent(
1031 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
1033 return kIOReturnUnsupported
;
1035 #endif /* !__LP64__ */
1037 //*********************************************************************************
1038 // [public] removePowerChild
1040 // Called on a parent whose child is being removed by PMstop().
1041 //*********************************************************************************
1043 IOReturn
IOService::removePowerChild( IOPowerConnection
* theNub
)
1045 IORegistryEntry
* theChild
;
1047 PM_ASSERT_IN_GATE();
1048 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1052 // detach nub from child
1053 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1056 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1057 theChild
->release();
1059 // detach from the nub
1060 detachFromChild(theNub
, gIOPowerPlane
);
1062 // Are we awaiting an ack from this child?
1063 if ( theNub
->getAwaitingAck() )
1065 // yes, pretend we got one
1066 theNub
->setAwaitingAck(false);
1067 if (fHeadNotePendingAcks
!= 0 )
1069 // that's one fewer ack to worry about
1070 fHeadNotePendingAcks
--;
1072 // is that the last?
1073 if ( fHeadNotePendingAcks
== 0 )
1077 // This parent may have a request in the work queue that is
1078 // blocked on fHeadNotePendingAcks=0. And removePowerChild()
1079 // is called while executing the child's PMstop request so they
1080 // can occur simultaneously. IOPMWorkQueue::checkForWork() must
1081 // restart and check all request queues again.
1083 gIOPMWorkQueue
->incrementProducerCount();
1090 // A child has gone away, re-scan children desires and clamp bits.
1091 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1093 if (!fAdjustPowerScheduled
)
1095 IOPMRequest
* request
;
1096 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1099 submitPMRequest( request
);
1100 fAdjustPowerScheduled
= true;
1107 //*********************************************************************************
1108 // [public] registerPowerDriver
1110 // A driver has called us volunteering to control power to our device.
1111 //*********************************************************************************
1113 IOReturn
IOService::registerPowerDriver(
1114 IOService
* powerDriver
,
1115 IOPMPowerState
* powerStates
,
1116 unsigned long numberOfStates
)
1118 IOPMRequest
* request
;
1119 IOPMPSEntry
* powerStatesCopy
= 0;
1120 IOPMPowerStateIndex stateOrder
;
1121 IOReturn error
= kIOReturnSuccess
;
1124 return IOPMNotYetInitialized
;
1126 if (!powerStates
|| (numberOfStates
< 2))
1128 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1129 return kIOReturnBadArgument
;
1132 if (!powerDriver
|| !powerDriver
->initialized
)
1134 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1135 return kIOReturnBadArgument
;
1138 if (powerStates
[0].version
> kIOPMPowerStateVersion2
)
1140 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1141 return kIOReturnBadArgument
;
1145 // Make a copy of the supplied power state array.
1146 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1147 if (!powerStatesCopy
)
1149 error
= kIOReturnNoMemory
;
1153 // Initialize to bogus values
1154 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1155 powerStatesCopy
[i
].stateOrderToIndex
= kIOPMPowerStateMax
;
1157 for (uint32_t i
= 0; i
< numberOfStates
; i
++)
1159 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1160 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1161 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1162 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1163 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1164 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1165 if (powerStates
[i
].version
>= kIOPMPowerStateVersion2
)
1166 stateOrder
= powerStates
[i
].stateOrder
;
1170 if (stateOrder
< numberOfStates
)
1172 powerStatesCopy
[i
].stateOrder
= stateOrder
;
1173 powerStatesCopy
[stateOrder
].stateOrderToIndex
= i
;
1177 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1179 if (powerStatesCopy
[i
].stateOrderToIndex
== kIOPMPowerStateMax
)
1181 // power state order missing
1182 error
= kIOReturnBadArgument
;
1186 if (kIOReturnSuccess
!= error
)
1189 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1192 error
= kIOReturnNoMemory
;
1196 powerDriver
->retain();
1197 request
->fArg0
= (void *) powerDriver
;
1198 request
->fArg1
= (void *) powerStatesCopy
;
1199 request
->fArg2
= (void *) numberOfStates
;
1201 submitPMRequest( request
);
1202 return kIOReturnSuccess
;
1206 if (powerStatesCopy
)
1207 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1212 //*********************************************************************************
1213 // [private] handleRegisterPowerDriver
1214 //*********************************************************************************
1216 void IOService::handleRegisterPowerDriver( IOPMRequest
* request
)
1218 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1219 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1220 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1221 unsigned long i
, stateIndex
;
1222 unsigned long lowestPowerState
;
1226 PM_ASSERT_IN_GATE();
1227 assert(powerStates
);
1228 assert(powerDriver
);
1229 assert(numberOfStates
> 1);
1231 if ( !fNumberOfPowerStates
)
1233 OUR_PMLog(kPMLogControllingDriver
,
1234 (unsigned long) numberOfStates
,
1235 (unsigned long) kIOPMPowerStateVersion1
);
1237 fPowerStates
= powerStates
;
1238 fNumberOfPowerStates
= numberOfStates
;
1239 fControllingDriver
= powerDriver
;
1240 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1242 lowestPowerState
= fPowerStates
[0].stateOrderToIndex
;
1243 fHighestPowerState
= fPowerStates
[numberOfStates
- 1].stateOrderToIndex
;
1245 // OR'in all the output power flags
1246 fMergedOutputPowerFlags
= 0;
1247 fDeviceUsablePowerState
= lowestPowerState
;
1248 for ( i
= 0; i
< numberOfStates
; i
++ )
1250 fMergedOutputPowerFlags
|= fPowerStates
[i
].outputPowerFlags
;
1252 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
1253 assert(stateIndex
< numberOfStates
);
1254 if ((fDeviceUsablePowerState
== lowestPowerState
) &&
1255 (fPowerStates
[stateIndex
].capabilityFlags
& IOPMDeviceUsable
))
1257 // The minimum power state that the device is usable
1258 fDeviceUsablePowerState
= stateIndex
;
1262 // Register powerDriver as interested, unless already done.
1263 // We don't want to register the default implementation since
1264 // it does nothing. One ramification of not always registering
1265 // is the one fewer retain count held.
1267 root
= getPlatform()->getProvider();
1270 ((OSMemberFunctionCast(void (*)(void),
1271 root
, &IOService::powerStateDidChangeTo
)) !=
1272 ((OSMemberFunctionCast(void (*)(void),
1273 this, &IOService::powerStateDidChangeTo
)))) ||
1274 ((OSMemberFunctionCast(void (*)(void),
1275 root
, &IOService::powerStateWillChangeTo
)) !=
1276 ((OSMemberFunctionCast(void (*)(void),
1277 this, &IOService::powerStateWillChangeTo
)))))
1279 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
)))
1292 const OSSymbol
* client
;
1293 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
1295 IOPMPowerStateIndex powerState
= getPowerStateForClient(client
);
1296 if (powerState
>= numberOfStates
)
1298 updatePowerClient(client
, fHighestPowerState
);
1304 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1306 IOPMPowerStateIndex tempDesire
;
1307 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1308 // initially change into the state we are already in
1309 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1310 adjustPowerState(tempDesire
);
1315 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1316 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1319 powerDriver
->release();
1322 //*********************************************************************************
1323 // [public] registerInterestedDriver
1325 // Add the caller to our list of interested drivers and return our current
1326 // power state. If we don't have a power-controlling driver yet, we will
1327 // call this interested driver again later when we do get a driver and find
1328 // out what the current power state of the device is.
1329 //*********************************************************************************
1331 IOPMPowerFlags
IOService::registerInterestedDriver( IOService
* driver
)
1333 IOPMRequest
* request
;
1336 if (!driver
|| !initialized
|| !fInterestedDrivers
)
1340 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1341 if (fInsertInterestSet
== NULL
)
1342 fInsertInterestSet
= OSSet::withCapacity(4);
1343 if (fInsertInterestSet
)
1345 fInsertInterestSet
->setObject(driver
);
1346 if (fRemoveInterestSet
)
1347 fRemoveInterestSet
->removeObject(driver
);
1353 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1355 submitPMRequest( request
);
1358 // This return value cannot be trusted, but return a value
1359 // for those clients that care.
1361 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1362 return kIOPMDeviceUsable
;
1365 //*********************************************************************************
1366 // [public] deRegisterInterestedDriver
1367 //*********************************************************************************
1369 IOReturn
IOService::deRegisterInterestedDriver( IOService
* driver
)
1371 IOPMinformee
* item
;
1372 IOPMRequest
* request
;
1376 return kIOReturnBadArgument
;
1377 if (!initialized
|| !fInterestedDrivers
)
1378 return IOPMNotPowerManaged
;
1381 if (fInsertInterestSet
)
1383 fInsertInterestSet
->removeObject(driver
);
1386 item
= fInterestedDrivers
->findItem(driver
);
1390 return kIOReturnNotFound
;
1393 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1394 if (fRemoveInterestSet
== NULL
)
1395 fRemoveInterestSet
= OSSet::withCapacity(4);
1396 if (fRemoveInterestSet
)
1398 fRemoveInterestSet
->setObject(driver
);
1401 item
->active
= false;
1402 waitForPMDriverCall( driver
);
1409 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1411 submitPMRequest( request
);
1417 //*********************************************************************************
1418 // [private] handleInterestChanged
1420 // Handle interest added or removed.
1421 //*********************************************************************************
1423 void IOService::handleInterestChanged( IOPMRequest
* request
)
1426 IOPMinformee
* informee
;
1427 IOPMinformeeList
* list
= fInterestedDrivers
;
1431 if (fInsertInterestSet
)
1433 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject()))
1435 if (list
->findItem(driver
) == NULL
)
1437 informee
= list
->appendNewInformee(driver
);
1439 fInsertInterestSet
->removeObject(driver
);
1441 fInsertInterestSet
->release();
1442 fInsertInterestSet
= 0;
1445 if (fRemoveInterestSet
)
1447 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject()))
1449 informee
= list
->findItem(driver
);
1452 // Clean-up async interest acknowledgement
1453 if (fHeadNotePendingAcks
&& informee
->timer
)
1455 informee
->timer
= 0;
1456 fHeadNotePendingAcks
--;
1458 list
->removeFromList(driver
);
1460 fRemoveInterestSet
->removeObject(driver
);
1462 fRemoveInterestSet
->release();
1463 fRemoveInterestSet
= 0;
1469 //*********************************************************************************
1470 // [public] acknowledgePowerChange
1472 // After we notified one of the interested drivers or a power-domain child
1473 // of an impending change in power, it has called to say it is now
1474 // prepared for the change. If this object is the last to
1475 // acknowledge this change, we take whatever action we have been waiting
1477 // That may include acknowledging to our parent. In this case, we do it
1478 // last of all to insure that this doesn't cause the parent to call us some-
1479 // where else and alter data we are relying on here (like the very existance
1480 // of a "current change note".)
1481 //*********************************************************************************
1483 IOReturn
IOService::acknowledgePowerChange( IOService
* whichObject
)
1485 IOPMRequest
* request
;
1488 return IOPMNotYetInitialized
;
1490 return kIOReturnBadArgument
;
1492 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1494 return kIOReturnNoMemory
;
1496 whichObject
->retain();
1497 request
->fArg0
= whichObject
;
1499 submitPMRequest( request
);
1503 //*********************************************************************************
1504 // [private] handleAcknowledgePowerChange
1505 //*********************************************************************************
1507 bool IOService::handleAcknowledgePowerChange( IOPMRequest
* request
)
1509 IOPMinformee
* informee
;
1510 unsigned long childPower
= kIOPMUnknown
;
1511 IOService
* theChild
;
1512 IOService
* whichObject
;
1513 bool all_acked
= false;
1515 PM_ASSERT_IN_GATE();
1516 whichObject
= (IOService
*) request
->fArg0
;
1517 assert(whichObject
);
1519 // one of our interested drivers?
1520 informee
= fInterestedDrivers
->findItem( whichObject
);
1521 if ( informee
== NULL
)
1523 if ( !isChild(whichObject
, gIOPowerPlane
) )
1525 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1528 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1531 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1534 if ( fHeadNotePendingAcks
!= 0 )
1536 assert(fPowerStates
!= NULL
);
1538 // yes, make sure we're expecting acks
1539 if ( informee
!= NULL
)
1541 // it's an interested driver
1542 // make sure we're expecting this ack
1543 if ( informee
->timer
!= 0 )
1546 if (informee
->timer
> 0)
1548 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1549 if (nsec
> LOG_SETPOWER_TIMES
) {
1550 getPMRootDomain()->pmStatsRecordApplicationResponse(
1551 gIOPMStatsDriverPSChangeSlow
, informee
->whatObject
->getName(),
1552 fDriverCallReason
, NS_TO_MS(nsec
), informee
->whatObject
->getRegistryEntryID(),
1553 NULL
, fHeadNotePowerState
);
1558 informee
->timer
= 0;
1559 // that's one fewer to worry about
1560 fHeadNotePendingAcks
--;
1562 // this driver has already acked
1563 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1567 // make sure we're expecting this ack
1568 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1570 // that's one fewer to worry about
1571 fHeadNotePendingAcks
--;
1572 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1573 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1576 childPower
= theChild
->currentPowerConsumption();
1577 theChild
->release();
1579 if ( childPower
== kIOPMUnknown
)
1581 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1583 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
1585 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1591 if ( fHeadNotePendingAcks
== 0 ) {
1592 // yes, stop the timer
1594 // and now we can continue
1598 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1603 whichObject
->release();
1608 //*********************************************************************************
1609 // [public] acknowledgeSetPowerState
1611 // After we instructed our controlling driver to change power states,
1612 // it has called to say it has finished doing so.
1613 // We continue to process the power state change.
1614 //*********************************************************************************
1616 IOReturn
IOService::acknowledgeSetPowerState( void )
1618 IOPMRequest
* request
;
1621 return IOPMNotYetInitialized
;
1623 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1625 return kIOReturnNoMemory
;
1627 submitPMRequest( request
);
1628 return kIOReturnSuccess
;
1631 //*********************************************************************************
1632 // [private] adjustPowerState
1633 //*********************************************************************************
1635 void IOService::adjustPowerState( uint32_t clamp
)
1637 PM_ASSERT_IN_GATE();
1638 computeDesiredState(clamp
, false);
1639 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
))
1641 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1643 // Indicate that children desires must be ignored, and do not ask
1644 // apps for permission to drop power. This is used by root domain
1645 // for demand sleep.
1647 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
1648 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1651 /* flags */ changeFlags
,
1652 /* power state */ fDesiredPowerState
,
1653 /* domain flags */ 0,
1655 /* parent flags */ 0);
1659 //*********************************************************************************
1660 // [public] synchronizePowerTree
1661 //*********************************************************************************
1663 IOReturn
IOService::synchronizePowerTree(
1664 IOOptionBits options
,
1665 IOService
* notifyRoot
)
1667 IOPMRequest
* request_c
= 0;
1668 IOPMRequest
* request_s
;
1670 if (this != getPMRootDomain())
1671 return kIOReturnBadArgument
;
1673 return kIOPMNotYetInitialized
;
1675 OUR_PMLog(kPMLogCSynchronizePowerTree
, options
, (notifyRoot
!= 0));
1681 // Cancels don't need to be synchronized.
1682 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1683 if (nr
) submitPMRequest(nr
);
1684 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1685 if (nr
) submitPMRequest(nr
);
1688 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1690 goto error_no_memory
;
1692 if (options
& kIOPMSyncCancelPowerDown
)
1693 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1696 request_c
->attachNextRequest( request_s
);
1697 submitPMRequest(request_c
);
1700 request_s
->fArg0
= (void *)(uintptr_t) options
;
1701 submitPMRequest(request_s
);
1703 return kIOReturnSuccess
;
1706 if (request_c
) releasePMRequest(request_c
);
1707 if (request_s
) releasePMRequest(request_s
);
1708 return kIOReturnNoMemory
;
1711 //*********************************************************************************
1712 // [private] handleSynchronizePowerTree
1713 //*********************************************************************************
1715 void IOService::handleSynchronizePowerTree( IOPMRequest
* request
)
1717 PM_ASSERT_IN_GATE();
1718 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1719 (fCurrentPowerState
== fHighestPowerState
))
1721 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1724 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1725 (options
& kIOPMSyncNoChildNotify
),
1726 /* power state */ fCurrentPowerState
,
1727 /* domain flags */ 0,
1729 /* parent flags */ 0);
1734 //*********************************************************************************
1735 // [deprecated] powerDomainWillChangeTo
1737 // Called by the power-hierarchy parent notifying of a new power state
1738 // in the power domain.
1739 // We enqueue a parent power-change to our queue of power changes.
1740 // This may or may not cause us to change power, depending on what
1741 // kind of change is occuring in the domain.
1742 //*********************************************************************************
1744 IOReturn
IOService::powerDomainWillChangeTo(
1745 IOPMPowerFlags newPowerFlags
,
1746 IOPowerConnection
* whichParent
)
1749 return kIOReturnUnsupported
;
1751 #endif /* !__LP64__ */
1753 //*********************************************************************************
1754 // [private] handlePowerDomainWillChangeTo
1755 //*********************************************************************************
1757 void IOService::handlePowerDomainWillChangeTo( IOPMRequest
* request
)
1759 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1760 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1761 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1762 IOPMPowerChangeFlags myChangeFlags
;
1765 IOPowerConnection
* connection
;
1766 IOPMPowerStateIndex maxPowerState
;
1767 IOPMPowerFlags combinedPowerFlags
;
1768 bool savedParentsKnowState
;
1769 IOReturn result
= IOPMAckImplied
;
1771 PM_ASSERT_IN_GATE();
1772 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1774 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1776 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1780 savedParentsKnowState
= fParentsKnowState
;
1782 // Combine parents' output power flags.
1784 combinedPowerFlags
= 0;
1786 iter
= getParentIterator(gIOPowerPlane
);
1789 while ( (next
= iter
->getNextObject()) )
1791 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1793 if ( connection
== whichParent
)
1794 combinedPowerFlags
|= parentPowerFlags
;
1796 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1802 // If our initial change has yet to occur, then defer the power change
1803 // until after the power domain has completed its power transition.
1805 if ( fControllingDriver
&& !fInitialPowerChange
)
1807 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1808 combinedPowerFlags
);
1810 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1812 // fMaxPowerState set a limit on self-initiated power changes.
1813 // Update it before a parent power drop.
1814 fMaxPowerState
= maxPowerState
;
1817 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1818 // to avoid propagating the root change flags if any service must
1819 // change power state due to root's will-change notification.
1820 // Root does not change power state for kIOPMSynchronize.
1822 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1823 (parentChangeFlags
& kIOPMSynchronize
);
1825 result
= startPowerChange(
1826 /* flags */ myChangeFlags
,
1827 /* power state */ maxPowerState
,
1828 /* domain flags */ combinedPowerFlags
,
1829 /* connection */ whichParent
,
1830 /* parent flags */ parentPowerFlags
);
1833 // If parent is dropping power, immediately update the parent's
1834 // capability flags. Any future merging of parent(s) combined
1835 // power flags should account for this power drop.
1837 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1839 setParentInfo(parentPowerFlags
, whichParent
, true);
1842 // Parent is expecting an ACK from us. If we did not embark on a state
1843 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1844 // still required to issue an ACK to our parent.
1846 if (IOPMAckImplied
== result
)
1849 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1853 parent
->acknowledgePowerChange( whichParent
);
1859 // Drop the retain from notifyChild().
1860 if (whichParent
) whichParent
->release();
1864 //*********************************************************************************
1865 // [deprecated] powerDomainDidChangeTo
1867 // Called by the power-hierarchy parent after the power state of the power domain
1868 // has settled at a new level.
1869 // We enqueue a parent power-change to our queue of power changes.
1870 // This may or may not cause us to change power, depending on what
1871 // kind of change is occuring in the domain.
1872 //*********************************************************************************
1874 IOReturn
IOService::powerDomainDidChangeTo(
1875 IOPMPowerFlags newPowerFlags
,
1876 IOPowerConnection
* whichParent
)
1879 return kIOReturnUnsupported
;
1881 #endif /* !__LP64__ */
1883 //*********************************************************************************
1884 // [private] handlePowerDomainDidChangeTo
1885 //*********************************************************************************
1887 void 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())
1905 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1909 savedParentsKnowState
= fParentsKnowState
;
1911 setParentInfo(parentPowerFlags
, whichParent
, true);
1913 if ( fControllingDriver
)
1915 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1916 fParentsCurrentPowerFlags
);
1918 if ((parentChangeFlags
& kIOPMDomainPowerDrop
) == 0)
1920 // fMaxPowerState set a limit on self-initiated power changes.
1921 // Update it after a parent power rise.
1922 fMaxPowerState
= maxPowerState
;
1925 if (fInitialPowerChange
)
1927 computeDesire
= true;
1928 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1929 fParentsCurrentPowerFlags
);
1931 else if (parentChangeFlags
& kIOPMRootChangeUp
)
1933 if (fAdvisoryTickleUsed
)
1935 // On system wake, re-compute the desired power state since
1936 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1937 // which is an input to computeDesiredState(). This is not
1938 // necessary for a dark wake because powerChangeDone() will
1939 // handle the dark to full wake case, but it does no harm.
1941 desireChanged
= true;
1944 if (fResetPowerStateOnWake
)
1946 // Query the driver for the desired power state on system wake.
1947 // Default implementation returns the lowest power state.
1949 IOPMPowerStateIndex wakePowerState
=
1950 fControllingDriver
->initialPowerStateForDomainState(
1951 kIOPMRootDomainState
| kIOPMPowerOn
);
1953 // fDesiredPowerState was adjusted before going to sleep
1954 // with fDeviceDesire at min.
1956 if (StateOrder(wakePowerState
) > StateOrder(fDesiredPowerState
))
1958 // Must schedule a power adjustment if we changed the
1959 // device desire. That will update the desired domain
1960 // power on the parent power connection and ping the
1961 // power parent if necessary.
1963 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1964 desireChanged
= true;
1969 if (computeDesire
|| desireChanged
)
1970 computeDesiredState(initialDesire
, false);
1972 // Absorb and propagate parent's broadcast flags
1973 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1974 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1976 result
= startPowerChange(
1977 /* flags */ myChangeFlags
,
1978 /* power state */ maxPowerState
,
1979 /* domain flags */ fParentsCurrentPowerFlags
,
1980 /* connection */ whichParent
,
1981 /* parent flags */ 0);
1984 // Parent is expecting an ACK from us. If we did not embark on a state
1985 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1986 // still required to issue an ACK to our parent.
1988 if (IOPMAckImplied
== result
)
1991 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1995 parent
->acknowledgePowerChange( whichParent
);
2000 // If the parent registers its power driver late, then this is the
2001 // first opportunity to tell our parent about our desire. Or if the
2002 // child's desire changed during a parent change notify.
2004 if (fControllingDriver
&&
2005 ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
))
2007 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
2008 getName(), fParentsKnowState
);
2009 requestDomainPower( fDesiredPowerState
);
2013 // Drop the retain from notifyChild().
2014 if (whichParent
) whichParent
->release();
2017 //*********************************************************************************
2018 // [private] setParentInfo
2020 // Set our connection data for one specific parent, and then combine all the parent
2022 //*********************************************************************************
2024 void IOService::setParentInfo(
2025 IOPMPowerFlags newPowerFlags
,
2026 IOPowerConnection
* whichParent
,
2031 IOPowerConnection
* conn
;
2033 PM_ASSERT_IN_GATE();
2035 // set our connection data
2036 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
2037 whichParent
->setParentKnowsState(knowsState
);
2039 // recompute our parent info
2040 fParentsCurrentPowerFlags
= 0;
2041 fParentsKnowState
= true;
2043 iter
= getParentIterator(gIOPowerPlane
);
2046 while ( (next
= iter
->getNextObject()) )
2048 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
2050 fParentsKnowState
&= conn
->parentKnowsState();
2051 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
2058 //******************************************************************************
2059 // [private] trackSystemSleepPreventers
2060 //******************************************************************************
2062 void IOService::trackSystemSleepPreventers(
2063 IOPMPowerStateIndex oldPowerState
,
2064 IOPMPowerStateIndex newPowerState
,
2065 IOPMPowerChangeFlags changeFlags __unused
)
2067 IOPMPowerFlags oldCapability
, newCapability
;
2069 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2070 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2071 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2072 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2074 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)
2076 if (oldCapability
== newCapability
)
2079 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
)
2081 bool enablePrevention
= ((oldCapability
& kIOPMPreventIdleSleep
) == 0);
2082 bool idleCancelAllowed
= getPMRootDomain()->updatePreventIdleSleepList(
2083 this, enablePrevention
);
2084 #if SUPPORT_IDLE_CANCEL
2085 if (idleCancelAllowed
&& enablePrevention
)
2087 IOPMRequest
* cancelRequest
;
2089 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2092 submitPMRequest( cancelRequest
);
2098 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
)
2100 getPMRootDomain()->updatePreventSystemSleepList(this,
2101 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2105 //*********************************************************************************
2106 // [public] requestPowerDomainState
2108 // Called on a power parent when a child's power requirement changes.
2109 //*********************************************************************************
2111 IOReturn
IOService::requestPowerDomainState(
2112 IOPMPowerFlags childRequestPowerFlags
,
2113 IOPowerConnection
* childConnection
,
2114 unsigned long specification
)
2116 IOPMPowerStateIndex order
, powerState
;
2117 IOPMPowerFlags outputPowerFlags
;
2119 IOPMRequest
* subRequest
;
2120 bool adjustPower
= false;
2123 return IOPMNotYetInitialized
;
2125 if (gIOPMWorkLoop
->onThread() == false)
2127 PM_LOG("%s::requestPowerDomainState\n", getName());
2128 return kIOReturnSuccess
;
2131 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2133 if (!isChild(childConnection
, gIOPowerPlane
))
2134 return kIOReturnNotAttached
;
2136 if (!fControllingDriver
|| !fNumberOfPowerStates
)
2137 return kIOReturnNotReady
;
2139 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2142 // Remove flags from child request which we can't possibly supply
2143 childRequestPowerFlags
&= fMergedOutputPowerFlags
;
2145 // Merge in the power flags contributed by this power parent
2146 // at its current or impending power state.
2148 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2149 if (fMachineState
!= kIOPM_Finished
)
2151 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
)
2153 // Use the lower power state when dropping power.
2154 // Must be careful since a power drop can be cancelled
2155 // from the following states:
2156 // - kIOPM_OurChangeTellClientsPowerDown
2157 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2159 // The child must not wait for this parent to raise power
2160 // if the power drop was cancelled. The solution is to cancel
2161 // the power drop if possible, then schedule an adjustment to
2162 // re-evaluate the parent's power state.
2164 // Root domain is excluded to avoid idle sleep issues. And allow
2165 // root domain children to pop up when system is going to sleep.
2167 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2168 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
2170 fDoNotPowerDown
= true; // cancel power drop
2171 adjustPower
= true; // schedule an adjustment
2172 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2173 getName(), fMachineState
, child
->getName());
2177 // Beyond cancellation point, report the impending state.
2179 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2182 else if (IS_POWER_RISE
)
2184 // When raising power, must report the output power flags from
2185 // child's perspective. A child power request may arrive while
2186 // parent is transitioning upwards. If a request arrives after
2187 // setParentInfo() has already recorded the output power flags
2188 // for the next power state, then using the power supplied by
2189 // fCurrentPowerState is incorrect, and might cause the child
2190 // to wait when it should not.
2192 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2195 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2197 // Map child's requested power flags to one of our power state.
2199 for (order
= 0; order
< fNumberOfPowerStates
; order
++)
2201 powerState
= fPowerStates
[order
].stateOrderToIndex
;
2202 if ((fPowerStates
[powerState
].outputPowerFlags
& childRequestPowerFlags
)
2203 == childRequestPowerFlags
)
2206 if (order
>= fNumberOfPowerStates
)
2208 powerState
= kPowerStateZero
;
2211 // Conditions that warrants a power adjustment on this parent.
2212 // Adjust power will also propagate any changes to the child's
2213 // prevent idle/sleep flags towards the root domain.
2215 if (!childConnection
->childHasRequestedPower() ||
2216 (powerState
!= childConnection
->getDesiredDomainState()))
2219 #if ENABLE_DEBUG_LOGS
2222 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2223 getName(), child
->getName(),
2224 !childConnection
->childHasRequestedPower(),
2225 (uint32_t) childConnection
->getDesiredDomainState(),
2226 (uint32_t) powerState
);
2230 // Record the child's desires on the connection.
2231 childConnection
->setChildHasRequestedPower();
2232 childConnection
->setDesiredDomainState( powerState
);
2234 // Schedule a request to re-evaluate all children desires and
2235 // adjust power state. Submit a request if one wasn't pending,
2236 // or if the current request is part of a call tree.
2238 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2239 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest()))
2241 subRequest
= acquirePMRequest(
2242 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2245 submitPMRequest( subRequest
);
2246 fAdjustPowerScheduled
= true;
2250 return kIOReturnSuccess
;
2253 //*********************************************************************************
2254 // [public] temporaryPowerClampOn
2256 // A power domain wants to clamp its power on till it has children which
2257 // will thendetermine the power domain state.
2259 // We enter the highest state until addPowerChild is called.
2260 //*********************************************************************************
2262 IOReturn
IOService::temporaryPowerClampOn( void )
2264 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2267 //*********************************************************************************
2268 // [public] makeUsable
2270 // Some client of our device is asking that we become usable. Although
2271 // this has not come from a subclassed device object, treat it exactly
2272 // as if it had. In this way, subsequent requests for lower power from
2273 // a subclassed device object will pre-empt this request.
2275 // We treat this as a subclass object request to switch to the
2276 // highest power state.
2277 //*********************************************************************************
2279 IOReturn
IOService::makeUsable( void )
2281 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2282 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2285 //*********************************************************************************
2286 // [public] currentCapability
2287 //*********************************************************************************
2289 IOPMPowerFlags
IOService::currentCapability( void )
2292 return IOPMNotPowerManaged
;
2294 return fCurrentCapabilityFlags
;
2297 //*********************************************************************************
2298 // [public] changePowerStateTo
2300 // Called by our power-controlling driver to change power state. The new desired
2301 // power state is computed and compared against the current power state. If those
2302 // power states differ, then a power state change is initiated.
2303 //*********************************************************************************
2305 IOReturn
IOService::changePowerStateTo( unsigned long ordinal
)
2307 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2308 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2311 //*********************************************************************************
2312 // [protected] changePowerStateToPriv
2314 // Called by our driver subclass to change power state. The new desired power
2315 // state is computed and compared against the current power state. If those
2316 // power states differ, then a power state change is initiated.
2317 //*********************************************************************************
2319 IOReturn
IOService::changePowerStateToPriv( unsigned long ordinal
)
2321 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2322 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2325 //*********************************************************************************
2326 // [public] changePowerStateWithOverrideTo
2328 // Called by our driver subclass to change power state. The new desired power
2329 // state is computed and compared against the current power state. If those
2330 // power states differ, then a power state change is initiated.
2331 // Override enforced - Children and Driver desires are ignored.
2332 //*********************************************************************************
2334 IOReturn
IOService::changePowerStateWithOverrideTo( IOPMPowerStateIndex ordinal
,
2335 IOPMRequestTag tag
)
2337 IOPMRequest
* request
;
2340 return kIOPMNotYetInitialized
;
2342 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2344 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2346 return kIOReturnNoMemory
;
2348 gIOPMPowerClientDevice
->retain();
2349 request
->fRequestTag
= tag
;
2350 request
->fArg0
= (void *) ordinal
;
2351 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2355 request
->installCompletionAction( action
, target
, param
);
2358 // Prevent needless downwards power transitions by clamping power
2359 // until the scheduled request is executed.
2361 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
))
2363 fTempClampPowerState
= StateMax(fTempClampPowerState
, ordinal
);
2365 fOverrideMaxPowerState
= ordinal
;
2366 request
->fArg2
= (void *) (uintptr_t) true;
2369 submitPMRequest( request
);
2373 //*********************************************************************************
2374 // [public] changePowerStateForRootDomain
2376 // Adjust the root domain's power desire on the target
2377 //*********************************************************************************
2379 IOReturn
IOService::changePowerStateForRootDomain( IOPMPowerStateIndex ordinal
)
2381 OUR_PMLog(kPMLogChangeStateForRootDomain
, ordinal
, 0);
2382 return requestPowerState( gIOPMPowerClientRootDomain
, ordinal
);
2385 //*********************************************************************************
2386 // [public for PMRD] quiescePowerTree
2388 // For root domain to issue a request to quiesce the power tree.
2389 // Supplied callback invoked upon completion.
2390 //*********************************************************************************
2392 IOReturn
IOService::quiescePowerTree(
2393 void * target
, IOPMCompletionAction action
, void * param
)
2395 IOPMRequest
* request
;
2398 return kIOPMNotYetInitialized
;
2399 if (!target
|| !action
)
2400 return kIOReturnBadArgument
;
2402 OUR_PMLog(kPMLogQuiescePowerTree
, 0, 0);
2404 // Target the root node instead of root domain. This is to avoid blocking
2405 // the quiesce request behind an existing root domain request in the work
2406 // queue. Root parent and root domain requests in the work queue must not
2407 // block the completion of the quiesce request.
2409 request
= acquirePMRequest(gIOPMRootNode
, kIOPMRequestTypeQuiescePowerTree
);
2411 return kIOReturnNoMemory
;
2413 request
->installCompletionAction(target
, action
, param
);
2415 // Submit through the normal request flow. This will make sure any request
2416 // already in the request queue will get pushed over to the work queue for
2417 // execution. Any request submitted after this request may not be serviced.
2419 submitPMRequest( request
);
2420 return kIOReturnSuccess
;
2423 //*********************************************************************************
2424 // [private] requestPowerState
2425 //*********************************************************************************
2427 IOReturn
IOService::requestPowerState(
2428 const OSSymbol
* client
,
2431 IOPMRequest
* request
;
2434 return kIOReturnBadArgument
;
2436 return kIOPMNotYetInitialized
;
2438 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2440 return kIOReturnNoMemory
;
2443 request
->fArg0
= (void *)(uintptr_t) state
;
2444 request
->fArg1
= (void *) client
;
2448 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
))
2456 fTempClampPowerState
= StateMax(fTempClampPowerState
, state
);
2458 request
->fArg2
= (void *) (uintptr_t) true;
2461 submitPMRequest( request
);
2465 //*********************************************************************************
2466 // [private] handleRequestPowerState
2467 //*********************************************************************************
2469 void 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();
2477 assert(fTempClampCount
!= 0);
2478 if (fTempClampCount
) fTempClampCount
--;
2479 if (!fTempClampCount
) fTempClampPowerState
= kPowerStateZero
;
2482 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
))
2483 state
= fHighestPowerState
;
2485 // The power suppression due to changePowerStateWithOverrideTo() expires
2486 // upon the next "device" power request - changePowerStateToPriv().
2488 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2489 (client
== gIOPMPowerClientDevice
))
2490 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2492 if ((state
== kPowerStateZero
) &&
2493 (client
!= gIOPMPowerClientDevice
) &&
2494 (client
!= gIOPMPowerClientDriver
) &&
2495 (client
!= gIOPMPowerClientChildProxy
))
2496 removePowerClient(client
);
2498 updatePowerClient(client
, state
);
2504 //*********************************************************************************
2505 // [private] Helper functions to update/remove power clients.
2506 //*********************************************************************************
2508 void IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2510 IOPMPowerStateIndex oldPowerState
= kPowerStateZero
;
2513 fPowerClients
= OSDictionary::withCapacity(4);
2514 if (fPowerClients
&& client
)
2516 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2519 oldPowerState
= num
->unsigned32BitValue();
2520 num
->setValue(powerState
);
2524 num
= OSNumber::withNumber(powerState
, 32);
2527 fPowerClients
->setObject(client
, num
);
2532 PM_ACTION_3(actionUpdatePowerClient
, client
, oldPowerState
, powerState
);
2536 void IOService::removePowerClient( const OSSymbol
* client
)
2538 if (fPowerClients
&& client
)
2539 fPowerClients
->removeObject(client
);
2542 uint32_t IOService::getPowerStateForClient( const OSSymbol
* client
)
2544 uint32_t powerState
= kPowerStateZero
;
2546 if (fPowerClients
&& client
)
2548 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2549 if (num
) powerState
= num
->unsigned32BitValue();
2554 //*********************************************************************************
2555 // [protected] powerOverrideOnPriv
2556 //*********************************************************************************
2558 IOReturn
IOService::powerOverrideOnPriv( void )
2560 IOPMRequest
* request
;
2563 return IOPMNotYetInitialized
;
2565 if (gIOPMWorkLoop
->inGate())
2567 fDeviceOverrideEnabled
= true;
2571 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2573 return kIOReturnNoMemory
;
2575 submitPMRequest( request
);
2579 //*********************************************************************************
2580 // [protected] powerOverrideOffPriv
2581 //*********************************************************************************
2583 IOReturn
IOService::powerOverrideOffPriv( void )
2585 IOPMRequest
* request
;
2588 return IOPMNotYetInitialized
;
2590 if (gIOPMWorkLoop
->inGate())
2592 fDeviceOverrideEnabled
= false;
2596 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2598 return kIOReturnNoMemory
;
2600 submitPMRequest( request
);
2604 //*********************************************************************************
2605 // [private] handlePowerOverrideChanged
2606 //*********************************************************************************
2608 void IOService::handlePowerOverrideChanged( IOPMRequest
* request
)
2610 PM_ASSERT_IN_GATE();
2611 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
)
2613 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2614 fDeviceOverrideEnabled
= true;
2618 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2619 fDeviceOverrideEnabled
= false;
2625 //*********************************************************************************
2626 // [private] computeDesiredState
2627 //*********************************************************************************
2629 void IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2633 IOPowerConnection
* connection
;
2634 uint32_t desiredState
= kPowerStateZero
;
2635 uint32_t newPowerState
= kPowerStateZero
;
2636 bool hasChildren
= false;
2638 // Desired power state is always 0 without a controlling driver.
2640 if (!fNumberOfPowerStates
)
2642 fDesiredPowerState
= kPowerStateZero
;
2646 // Examine the children's desired power state.
2648 iter
= getChildIterator(gIOPowerPlane
);
2651 while ((next
= iter
->getNextObject()))
2653 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
2655 if (connection
->getReadyFlag() == false)
2657 PM_LOG3("[%s] %s: connection not ready\n",
2658 getName(), __FUNCTION__
);
2661 if (connection
->childHasRequestedPower())
2663 desiredState
= StateMax(connection
->getDesiredDomainState(), desiredState
);
2669 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2671 removePowerClient(gIOPMPowerClientChildren
);
2673 // Iterate through all power clients to determine the min power state.
2675 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2678 const OSSymbol
* client
;
2679 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
2681 // Ignore child and driver when override is in effect.
2682 if ((fDeviceOverrideEnabled
||
2683 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2684 ((client
== gIOPMPowerClientChildren
) ||
2685 (client
== gIOPMPowerClientDriver
)))
2688 // Ignore child proxy when children are present.
2689 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
))
2692 // Advisory tickles are irrelevant unless system is in full wake
2693 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2694 !gIOPMAdvisoryTickleEnabled
)
2697 desiredState
= getPowerStateForClient(client
);
2698 assert(desiredState
< fNumberOfPowerStates
);
2700 desiredState
, client
->getCStringNoCopy());
2702 newPowerState
= StateMax(newPowerState
, desiredState
);
2704 if (client
== gIOPMPowerClientDevice
)
2705 fDeviceDesire
= desiredState
;
2710 // Factor in the temporary power desires.
2712 newPowerState
= StateMax(newPowerState
, localClamp
);
2713 newPowerState
= StateMax(newPowerState
, fTempClampPowerState
);
2715 // Limit check against max power override.
2717 newPowerState
= StateMin(newPowerState
, fOverrideMaxPowerState
);
2719 // Limit check against number of power states.
2721 if (newPowerState
>= fNumberOfPowerStates
)
2722 newPowerState
= fHighestPowerState
;
2724 fDesiredPowerState
= newPowerState
;
2726 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2727 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2728 (uint32_t) fCurrentPowerState
, newPowerState
);
2732 // Restart idle timer if possible when device desire has increased.
2733 // Or if an advisory desire exists.
2735 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
2740 // Invalidate cached tickle power state when desires change, and not
2741 // due to a tickle request. In case the driver has requested a lower
2742 // power state, but the tickle is caching a higher power state which
2743 // will drop future tickles until the cached value is lowered or in-
2744 // validated. The invalidation must occur before the power transition
2745 // to avoid dropping a necessary tickle.
2747 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2748 (fActivityTicklePowerState
!= kInvalidTicklePowerState
))
2750 IOLockLock(fActivityLock
);
2751 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2752 IOLockUnlock(fActivityLock
);
2757 //*********************************************************************************
2758 // [public] currentPowerConsumption
2760 //*********************************************************************************
2762 unsigned long IOService::currentPowerConsumption( void )
2765 return kIOPMUnknown
;
2767 return fCurrentPowerConsumption
;
2770 //*********************************************************************************
2771 // [deprecated] getPMworkloop
2772 //*********************************************************************************
2775 IOWorkLoop
* IOService::getPMworkloop( void )
2777 return gIOPMWorkLoop
;
2783 //*********************************************************************************
2784 // Power Parent/Children Applier
2785 //*********************************************************************************
2788 applyToPowerChildren(
2789 IOService
* service
,
2790 IOServiceApplierFunction applier
,
2792 IOOptionBits options
)
2794 PM_ASSERT_IN_GATE();
2796 IORegistryEntry
* entry
;
2797 IORegistryIterator
* iter
;
2798 IOPowerConnection
* connection
;
2801 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2804 while ((entry
= iter
->getNextObject()))
2806 // Get child of IOPowerConnection objects
2807 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2809 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2812 (*applier
)(child
, context
);
2823 IOService
* service
,
2824 IOServiceApplierFunction applier
,
2826 IOOptionBits options
)
2828 PM_ASSERT_IN_GATE();
2830 IORegistryEntry
* entry
;
2831 IORegistryIterator
* iter
;
2832 IOPowerConnection
* connection
;
2835 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2836 options
| kIORegistryIterateParents
);
2839 while ((entry
= iter
->getNextObject()))
2841 // Get child of IOPowerConnection objects
2842 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2844 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2847 (*applier
)(parent
, context
);
2856 #endif /* NOT_YET */
2859 // MARK: Activity Tickle & Idle Timer
2861 void IOService::setAdvisoryTickleEnable( bool enable
)
2863 gIOPMAdvisoryTickleEnabled
= enable
;
2866 //*********************************************************************************
2867 // [public] activityTickle
2869 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2870 // flag to be set, and the device state checked. If the device has been
2871 // powered down, it is powered up again.
2872 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2873 // should be intercepted by a subclass.
2874 //*********************************************************************************
2876 bool IOService::activityTickle( unsigned long type
, unsigned long stateNumber
)
2878 IOPMRequest
* request
;
2879 bool noPowerChange
= true;
2880 uint32_t tickleFlags
;
2883 return true; // no power change
2885 if ((type
== kIOPMSuperclassPolicy1
) && StateOrder(stateNumber
))
2887 IOLockLock(fActivityLock
);
2889 // Record device activity for the idle timer handler.
2891 fDeviceWasActive
= true;
2892 fActivityTickleCount
++;
2893 clock_get_uptime(&fDeviceActiveTimestamp
);
2895 PM_ACTION_0(actionActivityTickle
);
2897 // Record the last tickle power state.
2898 // This helps to filter out redundant tickles as
2899 // this function may be called from the data path.
2901 if ((fActivityTicklePowerState
== kInvalidTicklePowerState
)
2902 || StateOrder(fActivityTicklePowerState
) < StateOrder(stateNumber
))
2904 fActivityTicklePowerState
= stateNumber
;
2905 noPowerChange
= false;
2907 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2908 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2911 request
->fArg0
= (void *) stateNumber
;
2912 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2913 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2914 submitPMRequest(request
);
2918 IOLockUnlock(fActivityLock
);
2921 else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2922 ((stateNumber
= fDeviceUsablePowerState
) != kPowerStateZero
))
2924 IOLockLock(fActivityLock
);
2926 fAdvisoryTickled
= true;
2928 if (fAdvisoryTicklePowerState
!= stateNumber
)
2930 fAdvisoryTicklePowerState
= stateNumber
;
2931 noPowerChange
= false;
2933 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2934 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2937 request
->fArg0
= (void *) stateNumber
;
2938 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2939 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2940 submitPMRequest(request
);
2944 IOLockUnlock(fActivityLock
);
2947 // Returns false if the activityTickle might cause a transition to a
2948 // higher powered state, true otherwise.
2950 return noPowerChange
;
2953 //*********************************************************************************
2954 // [private] handleActivityTickle
2955 //*********************************************************************************
2957 void IOService::handleActivityTickle( IOPMRequest
* request
)
2959 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2960 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
2961 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
2962 bool adjustPower
= false;
2964 PM_ASSERT_IN_GATE();
2965 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
))
2967 // Drivers that don't want power restored on wake will drop any
2968 // tickles that pre-dates the current system wake. The model is
2969 // that each wake is a fresh start, with power state depressed
2970 // until a new tickle or an explicit power up request from the
2971 // driver. It is possible for the PM work loop to enter the
2972 // system sleep path with tickle requests queued.
2977 if (tickleFlags
& kTickleTypeActivity
)
2979 IOPMPowerStateIndex deviceDesireOrder
= StateOrder(fDeviceDesire
);
2980 uint32_t idleTimerGeneration
= ticklePowerState
; // kTickleTypePowerDrop
2982 if (tickleFlags
& kTickleTypePowerRise
)
2984 if ((StateOrder(ticklePowerState
) > deviceDesireOrder
) &&
2985 (ticklePowerState
< fNumberOfPowerStates
))
2987 fIdleTimerMinPowerState
= ticklePowerState
;
2988 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2992 else if ((deviceDesireOrder
> StateOrder(fIdleTimerMinPowerState
)) &&
2993 (idleTimerGeneration
== fIdleTimerGeneration
))
2995 // Power drop due to idle timer expiration.
2996 // Do not allow idle timer to reduce power below tickle power.
2997 // This prevents the idle timer from decreasing the device desire
2998 // to zero and cancelling the effect of a pre-sleep tickle when
2999 // system wakes up to doze state, while the device is unable to
3000 // raise its power state to satisfy the tickle.
3002 deviceDesireOrder
--;
3003 if (deviceDesireOrder
< fNumberOfPowerStates
)
3005 ticklePowerState
= fPowerStates
[deviceDesireOrder
].stateOrderToIndex
;
3006 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
3011 else // advisory tickle
3013 if (tickleFlags
& kTickleTypePowerRise
)
3015 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
3016 (ticklePowerState
< fNumberOfPowerStates
))
3018 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
3019 fHasAdvisoryDesire
= true;
3020 fAdvisoryTickleUsed
= true;
3025 IOLockLock(fActivityLock
);
3026 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3027 IOLockUnlock(fActivityLock
);
3030 else if (fHasAdvisoryDesire
)
3032 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
3033 fHasAdvisoryDesire
= false;
3044 //******************************************************************************
3045 // [public] setIdleTimerPeriod
3047 // A subclass policy-maker is using our standard idleness detection service.
3048 // Start the idle timer. Period is in seconds.
3049 //******************************************************************************
3051 IOReturn
IOService::setIdleTimerPeriod( unsigned long period
)
3054 return IOPMNotYetInitialized
;
3056 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
3058 IOPMRequest
* request
=
3059 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
3061 return kIOReturnNoMemory
;
3063 request
->fArg0
= (void *) period
;
3064 submitPMRequest( request
);
3066 return kIOReturnSuccess
;
3069 IOReturn
IOService::setIgnoreIdleTimer( bool ignore
)
3072 return IOPMNotYetInitialized
;
3074 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
3076 IOPMRequest
* request
=
3077 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
3079 return kIOReturnNoMemory
;
3081 request
->fArg0
= (void *) ignore
;
3082 submitPMRequest( request
);
3084 return kIOReturnSuccess
;
3087 //******************************************************************************
3088 // [public] nextIdleTimeout
3090 // Returns how many "seconds from now" the device should idle into its
3091 // next lowest power state.
3092 //******************************************************************************
3094 SInt32
IOService::nextIdleTimeout(
3095 AbsoluteTime currentTime
,
3096 AbsoluteTime lastActivity
,
3097 unsigned int powerState
)
3104 // Calculate time difference using funky macro from clock.h.
3105 delta
= currentTime
;
3106 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
3108 // Figure it in seconds.
3109 absolutetime_to_nanoseconds(delta
, &delta_ns
);
3110 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
3112 // Be paranoid about delta somehow exceeding timer period.
3113 if (delta_secs
< (int) fIdleTimerPeriod
)
3114 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3116 delay_secs
= (int) fIdleTimerPeriod
;
3118 return (SInt32
)delay_secs
;
3121 //*********************************************************************************
3122 // [public] start_PM_idle_timer
3123 //*********************************************************************************
3125 void IOService::start_PM_idle_timer( void )
3127 static const int maxTimeout
= 100000;
3128 static const int minTimeout
= 1;
3129 AbsoluteTime uptime
, deadline
;
3133 if (!initialized
|| !fIdleTimerPeriod
)
3136 IOLockLock(fActivityLock
);
3138 clock_get_uptime(&uptime
);
3140 // Subclasses may modify idle sleep algorithm
3141 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3143 // Check for out-of range responses
3144 if (idle_in
> maxTimeout
)
3146 // use standard implementation
3147 idle_in
= IOService::nextIdleTimeout(uptime
,
3148 fDeviceActiveTimestamp
,
3149 fCurrentPowerState
);
3150 } else if (idle_in
< minTimeout
) {
3151 idle_in
= fIdleTimerPeriod
;
3154 IOLockUnlock(fActivityLock
);
3156 fNextIdleTimerPeriod
= idle_in
;
3157 fIdleTimerStartTime
= uptime
;
3160 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3161 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3162 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3163 if (pending
) release();
3166 //*********************************************************************************
3167 // [private] restartIdleTimer
3168 //*********************************************************************************
3170 void IOService::restartIdleTimer( void )
3172 if (fDeviceDesire
!= kPowerStateZero
)
3174 fIdleTimerStopped
= false;
3175 fActivityTickleCount
= 0;
3176 start_PM_idle_timer();
3178 else if (fHasAdvisoryDesire
)
3180 fIdleTimerStopped
= false;
3181 start_PM_idle_timer();
3185 fIdleTimerStopped
= true;
3189 //*********************************************************************************
3190 // idle_timer_expired
3191 //*********************************************************************************
3195 thread_call_param_t arg0
, thread_call_param_t arg1
)
3197 IOService
* me
= (IOService
*) arg0
;
3200 gIOPMWorkLoop
->runAction(
3201 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3202 &IOService::idleTimerExpired
),
3208 //*********************************************************************************
3209 // [private] idleTimerExpired
3211 // The idle timer has expired. If there has been activity since the last
3212 // expiration, just restart the timer and return. If there has not been
3213 // activity, switch to the next lower power state and restart the timer.
3214 //*********************************************************************************
3216 void IOService::idleTimerExpired( void )
3218 IOPMRequest
* request
;
3219 bool restartTimer
= true;
3220 uint32_t tickleFlags
;
3222 if ( !initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3223 fLockedFlags
.PMStop
)
3226 fIdleTimerStartTime
= 0;
3228 IOLockLock(fActivityLock
);
3230 // Check for device activity (tickles) over last timer period.
3232 if (fDeviceWasActive
)
3234 // Device was active - do not drop power, restart timer.
3235 fDeviceWasActive
= false;
3237 else if (!fIdleTimerIgnored
)
3239 // No device activity - drop power state by one level.
3240 // Decrement the cached tickle power state when possible.
3241 // This value may be kInvalidTicklePowerState before activityTickle()
3242 // is called, but the power drop request must be issued regardless.
3244 if ((fActivityTicklePowerState
!= kInvalidTicklePowerState
) &&
3245 (fActivityTicklePowerState
!= kPowerStateZero
))
3246 fActivityTicklePowerState
--;
3248 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3249 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3252 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3253 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3254 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3255 submitPMRequest( request
);
3257 // Do not restart timer until after the tickle request has been
3260 restartTimer
= false;
3264 if (fAdvisoryTickled
)
3266 fAdvisoryTickled
= false;
3268 else if (fHasAdvisoryDesire
)
3270 // Want new tickles to turn into pm request after we drop the lock
3271 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3273 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3274 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3277 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3278 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3279 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3280 submitPMRequest( request
);
3282 // Do not restart timer until after the tickle request has been
3285 restartTimer
= false;
3289 IOLockUnlock(fActivityLock
);
3292 start_PM_idle_timer();
3296 //*********************************************************************************
3297 // [deprecated] PM_idle_timer_expiration
3298 //*********************************************************************************
3300 void IOService::PM_idle_timer_expiration( void )
3304 //*********************************************************************************
3305 // [deprecated] command_received
3306 //*********************************************************************************
3308 void IOService::command_received( void *statePtr
, void *, void * , void * )
3311 #endif /* !__LP64__ */
3313 //*********************************************************************************
3314 // [public] setAggressiveness
3316 // Pass on the input parameters to all power domain children. All those which are
3317 // power domains will pass it on to their children, etc.
3318 //*********************************************************************************
3320 IOReturn
IOService::setAggressiveness( unsigned long type
, unsigned long newLevel
)
3322 return kIOReturnSuccess
;
3325 //*********************************************************************************
3326 // [public] getAggressiveness
3328 // Called by the user client.
3329 //*********************************************************************************
3331 IOReturn
IOService::getAggressiveness( unsigned long type
, unsigned long * currentLevel
)
3333 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3336 return kIOReturnNotReady
;
3338 return rootDomain
->getAggressiveness( type
, currentLevel
);
3341 //*********************************************************************************
3342 // [public] getPowerState
3344 //*********************************************************************************
3346 UInt32
IOService::getPowerState( void )
3349 return kPowerStateZero
;
3351 return fCurrentPowerState
;
3355 //*********************************************************************************
3356 // [deprecated] systemWake
3358 // Pass this to all power domain children. All those which are
3359 // power domains will pass it on to their children, etc.
3360 //*********************************************************************************
3362 IOReturn
IOService::systemWake( void )
3366 IOPowerConnection
* connection
;
3367 IOService
* theChild
;
3369 iter
= getChildIterator(gIOPowerPlane
);
3372 while ( (next
= iter
->getNextObject()) )
3374 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
3376 if (connection
->getReadyFlag() == false)
3378 PM_LOG3("[%s] %s: connection not ready\n",
3379 getName(), __FUNCTION__
);
3383 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3386 theChild
->systemWake();
3387 theChild
->release();
3394 if ( fControllingDriver
!= NULL
)
3396 if ( fControllingDriver
->didYouWakeSystem() )
3405 //*********************************************************************************
3406 // [deprecated] temperatureCriticalForZone
3407 //*********************************************************************************
3409 IOReturn
IOService::temperatureCriticalForZone( IOService
* whichZone
)
3411 IOService
* theParent
;
3414 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3416 if ( inPlane(gIOPowerPlane
) && !IS_PM_ROOT
)
3418 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3421 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3425 theParent
->temperatureCriticalForZone(whichZone
);
3426 theParent
->release();
3432 #endif /* !__LP64__ */
3435 // MARK: Power Change (Common)
3437 //*********************************************************************************
3438 // [private] startPowerChange
3440 // All power state changes starts here.
3441 //*********************************************************************************
3443 IOReturn
IOService::startPowerChange(
3444 IOPMPowerChangeFlags changeFlags
,
3445 IOPMPowerStateIndex powerState
,
3446 IOPMPowerFlags domainFlags
,
3447 IOPowerConnection
* parentConnection
,
3448 IOPMPowerFlags parentFlags
)
3450 PM_ASSERT_IN_GATE();
3451 assert( fMachineState
== kIOPM_Finished
);
3452 assert( powerState
< fNumberOfPowerStates
);
3454 if (powerState
>= fNumberOfPowerStates
)
3455 return IOPMAckImplied
;
3457 fIsPreChange
= true;
3458 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3460 if (changeFlags
& kIOPMExpireIdleTimer
)
3462 // Root domain requested removal of tickle influence
3463 if (StateOrder(fDeviceDesire
) > StateOrder(powerState
))
3465 // Reset device desire down to the clamped power state
3466 updatePowerClient(gIOPMPowerClientDevice
, powerState
);
3467 computeDesiredState(kPowerStateZero
, true);
3469 // Invalidate tickle cache so the next tickle will issue a request
3470 IOLockLock(fActivityLock
);
3471 fDeviceWasActive
= false;
3472 fActivityTicklePowerState
= kInvalidTicklePowerState
;
3473 IOLockUnlock(fActivityLock
);
3475 fIdleTimerMinPowerState
= kPowerStateZero
;
3479 // Root domain's override handler may cancel the power change by
3480 // setting the kIOPMNotDone flag.
3482 if (changeFlags
& kIOPMNotDone
)
3483 return IOPMAckImplied
;
3485 // Forks to either Driver or Parent initiated power change paths.
3487 fHeadNoteChangeFlags
= changeFlags
;
3488 fHeadNotePowerState
= powerState
;
3489 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
3490 fHeadNoteParentConnection
= NULL
;
3492 if (changeFlags
& kIOPMSelfInitiated
)
3494 if (changeFlags
& kIOPMSynchronize
)
3502 assert(changeFlags
& kIOPMParentInitiated
);
3503 fHeadNoteDomainFlags
= domainFlags
;
3504 fHeadNoteParentFlags
= parentFlags
;
3505 fHeadNoteParentConnection
= parentConnection
;
3506 return ParentChangeStart();
3510 //*********************************************************************************
3511 // [private] notifyInterestedDrivers
3512 //*********************************************************************************
3514 bool IOService::notifyInterestedDrivers( void )
3516 IOPMinformee
* informee
;
3517 IOPMinformeeList
* list
= fInterestedDrivers
;
3518 DriverCallParam
* param
;
3520 IOItemCount skipCnt
= 0;
3522 PM_ASSERT_IN_GATE();
3523 assert( fDriverCallParamCount
== 0 );
3524 assert( fHeadNotePendingAcks
== 0 );
3526 fHeadNotePendingAcks
= 0;
3528 count
= list
->numberOfItems();
3530 goto done
; // no interested drivers
3532 // Allocate an array of interested drivers and their return values
3533 // for the callout thread. Everything else is still "owned" by the
3534 // PM work loop, which can run to process acknowledgePowerChange()
3537 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3538 if (count
> fDriverCallParamSlots
)
3540 if (fDriverCallParamSlots
)
3542 assert(fDriverCallParamPtr
);
3543 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3544 fDriverCallParamPtr
= 0;
3545 fDriverCallParamSlots
= 0;
3548 param
= IONew(DriverCallParam
, count
);
3550 goto done
; // no memory
3552 fDriverCallParamPtr
= (void *) param
;
3553 fDriverCallParamSlots
= count
;
3556 informee
= list
->firstInList();
3558 for (IOItemCount i
= 0; i
< count
; i
++)
3560 if (fInitialSetPowerState
|| (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)) {
3561 // Skip notifying self, if 'kIOPMInitialDeviceState' is set and
3562 // this is the initial power state change
3563 if ((this == informee
->whatObject
) &&
3564 (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)) {
3569 informee
->timer
= -1;
3570 param
[i
].Target
= informee
;
3572 informee
= list
->nextInList( informee
);
3579 fDriverCallParamCount
= count
;
3580 fHeadNotePendingAcks
= count
;
3582 // Block state machine and wait for callout completion.
3583 assert(!fDriverCallBusy
);
3584 fDriverCallBusy
= true;
3585 thread_call_enter( fDriverCallEntry
);
3589 // Return false if there are no interested drivers or could not schedule
3590 // callout thread due to error.
3594 //*********************************************************************************
3595 // [private] notifyInterestedDriversDone
3596 //*********************************************************************************
3598 void IOService::notifyInterestedDriversDone( void )
3600 IOPMinformee
* informee
;
3602 DriverCallParam
* param
;
3605 PM_ASSERT_IN_GATE();
3606 assert( fDriverCallBusy
== false );
3607 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3609 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3610 count
= fDriverCallParamCount
;
3614 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3616 informee
= (IOPMinformee
*) param
->Target
;
3617 result
= param
->Result
;
3619 if ((result
== IOPMAckImplied
) || (result
< 0))
3621 // Interested driver return IOPMAckImplied.
3622 // If informee timer is zero, it must have de-registered
3623 // interest during the thread callout. That also drops
3624 // the pending ack count.
3626 if (fHeadNotePendingAcks
&& informee
->timer
)
3627 fHeadNotePendingAcks
--;
3629 informee
->timer
= 0;
3631 else if (informee
->timer
)
3633 assert(informee
->timer
== -1);
3635 // Driver has not acked, and has returned a positive result.
3636 // Enforce a minimum permissible timeout value.
3637 // Make the min value large enough so timeout is less likely
3638 // to occur if a driver misinterpreted that the return value
3639 // should be in microsecond units. And make it large enough
3640 // to be noticeable if a driver neglects to ack.
3642 if (result
< kMinAckTimeoutTicks
)
3643 result
= kMinAckTimeoutTicks
;
3645 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3647 // else, child has already acked or driver has removed interest,
3648 // and head_note_pendingAcks decremented.
3649 // informee may have been removed from the interested drivers list,
3650 // thus the informee must be retained across the callout.
3652 informee
->release();
3655 fDriverCallParamCount
= 0;
3657 if ( fHeadNotePendingAcks
)
3659 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3664 MS_POP(); // pop the machine state passed to notifyAll()
3666 // If interest acks are outstanding, block the state machine until
3667 // fHeadNotePendingAcks drops to zero before notifying root domain.
3668 // Otherwise notify root domain directly.
3670 if (!fHeadNotePendingAcks
)
3676 MS_PUSH(fMachineState
);
3677 fMachineState
= kIOPM_NotifyChildrenStart
;
3681 //*********************************************************************************
3682 // [private] notifyRootDomain
3683 //*********************************************************************************
3685 void IOService::notifyRootDomain( void )
3687 assert( fDriverCallBusy
== false );
3689 // Only for root domain in the will-change phase
3690 if (!IS_ROOT_DOMAIN
|| (fMachineState
!= kIOPM_OurChangeSetPowerState
))
3696 MS_PUSH(fMachineState
); // push notifyAll() machine state
3697 fMachineState
= kIOPM_DriverThreadCallDone
;
3699 // Call IOPMrootDomain::willNotifyPowerChildren() on a thread call
3700 // to avoid a deadlock.
3701 fDriverCallReason
= kRootDomainInformPreChange
;
3702 fDriverCallBusy
= true;
3703 thread_call_enter( fDriverCallEntry
);
3706 void IOService::notifyRootDomainDone( void )
3708 assert( fDriverCallBusy
== false );
3709 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3711 MS_POP(); // pop notifyAll() machine state
3715 //*********************************************************************************
3716 // [private] notifyChildren
3717 //*********************************************************************************
3719 void IOService::notifyChildren( void )
3723 IOPowerConnection
* connection
;
3724 OSArray
* children
= 0;
3725 IOPMrootDomain
* rootDomain
;
3726 bool delayNotify
= false;
3728 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3729 (IS_POWER_DROP
== fIsPreChange
) &&
3730 ((rootDomain
= getPMRootDomain()) == this))
3732 rootDomain
->tracePoint( IS_POWER_DROP
?
3733 kIOPMTracePointSleepPowerPlaneDrivers
:
3734 kIOPMTracePointWakePowerPlaneDrivers
);
3737 if (fStrictTreeOrder
)
3738 children
= OSArray::withCapacity(8);
3740 // Sum child power consumption in notifyChild()
3741 fHeadNotePowerArrayEntry
->staticPower
= 0;
3743 iter
= getChildIterator(gIOPowerPlane
);
3746 while ((next
= iter
->getNextObject()))
3748 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3750 if (connection
->getReadyFlag() == false)
3752 PM_LOG3("[%s] %s: connection not ready\n",
3753 getName(), __FUNCTION__
);
3757 // Mechanism to postpone the did-change notification to
3758 // certain power children to order those children last.
3759 // Cannot be used together with strict tree ordering.
3761 if (!fIsPreChange
&&
3762 connection
->delayChildNotification
&&
3763 getPMRootDomain()->shouldDelayChildNotification(this))
3767 children
= OSArray::withCapacity(8);
3773 children
->setObject( connection
);
3778 if (!delayNotify
&& children
)
3779 children
->setObject( connection
);
3781 notifyChild( connection
);
3787 if (children
&& (children
->getCount() == 0))
3789 children
->release();
3794 assert(fNotifyChildArray
== 0);
3795 fNotifyChildArray
= children
;
3796 MS_PUSH(fMachineState
);
3800 // Block until all non-delayed children have acked their
3801 // notification. Then notify the remaining delayed child
3802 // in the array. This is used to hold off graphics child
3803 // notification while the rest of the system powers up.
3804 // If a hid tickle arrives during this time, the delayed
3805 // children are immediately notified and root domain will
3806 // not clamp power for dark wake.
3808 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3809 PM_LOG2("%s: %d children in delayed array\n",
3810 getName(), children
->getCount());
3814 // Child array created to support strict notification order.
3815 // Notify children in the array one at a time.
3817 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3822 //*********************************************************************************
3823 // [private] notifyChildrenOrdered
3824 //*********************************************************************************
3826 void IOService::notifyChildrenOrdered( void )
3828 PM_ASSERT_IN_GATE();
3829 assert(fNotifyChildArray
);
3830 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3832 // Notify one child, wait for it to ack, then repeat for next child.
3833 // This is a workaround for some drivers with multiple instances at
3834 // the same branch in the power tree, but the driver is slow to power
3835 // up unless the tree ordering is observed. Problem observed only on
3836 // system wake, not on system sleep.
3838 // We have the ability to power off in reverse child index order.
3839 // That works nicely on some machines, but not on all HW configs.
3841 if (fNotifyChildArray
->getCount())
3843 IOPowerConnection
* connection
;
3844 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3845 notifyChild( connection
);
3846 fNotifyChildArray
->removeObject(0);
3850 fNotifyChildArray
->release();
3851 fNotifyChildArray
= 0;
3853 MS_POP(); // pushed by notifyChildren()
3857 //*********************************************************************************
3858 // [private] notifyChildrenDelayed
3859 //*********************************************************************************
3861 void IOService::notifyChildrenDelayed( void )
3863 IOPowerConnection
* connection
;
3865 PM_ASSERT_IN_GATE();
3866 assert(fNotifyChildArray
);
3867 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3869 // Wait after all non-delayed children and interested drivers have ack'ed,
3870 // then notify all delayed children. If notify delay is canceled, child
3871 // acks may be outstanding with PM blocked on fHeadNotePendingAcks != 0.
3872 // But the handling for either case is identical.
3874 for (int i
= 0; ; i
++)
3876 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3880 notifyChild( connection
);
3883 PM_LOG2("%s: notified delayed children\n", getName());
3884 fNotifyChildArray
->release();
3885 fNotifyChildArray
= 0;
3887 MS_POP(); // pushed by notifyChildren()
3890 //*********************************************************************************
3891 // [private] notifyAll
3892 //*********************************************************************************
3894 IOReturn
IOService::notifyAll( uint32_t nextMS
)
3896 // Save the machine state to be restored by notifyInterestedDriversDone()
3898 PM_ASSERT_IN_GATE();
3900 fMachineState
= kIOPM_DriverThreadCallDone
;
3901 fDriverCallReason
= fIsPreChange
?
3902 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3904 if (!notifyInterestedDrivers())
3905 notifyInterestedDriversDone();
3907 return IOPMWillAckLater
;
3910 //*********************************************************************************
3911 // [private, static] pmDriverCallout
3913 // Thread call context
3914 //*********************************************************************************
3916 IOReturn
IOService::actionDriverCalloutDone(
3918 void * arg0
, void * arg1
,
3919 void * arg2
, void * arg3
)
3921 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3923 assert( fDriverCallBusy
);
3924 fDriverCallBusy
= false;
3926 assert(gIOPMWorkQueue
);
3927 gIOPMWorkQueue
->signalWorkAvailable();
3929 return kIOReturnSuccess
;
3932 void IOService::pmDriverCallout( IOService
* from
)
3935 switch (from
->fDriverCallReason
)
3937 case kDriverCallSetPowerState
:
3938 from
->driverSetPowerState();
3941 case kDriverCallInformPreChange
:
3942 case kDriverCallInformPostChange
:
3943 from
->driverInformPowerChange();
3946 case kRootDomainInformPreChange
:
3947 getPMRootDomain()->willNotifyPowerChildren(from
->fHeadNotePowerState
);
3951 panic("IOService::pmDriverCallout bad machine state %x",
3952 from
->fDriverCallReason
);
3955 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3957 /* arg0 */ (void *) from
->pwrMgt
);
3960 //*********************************************************************************
3961 // [private] driverSetPowerState
3963 // Thread call context
3964 //*********************************************************************************
3966 void IOService::driverSetPowerState( void )
3968 IOPMPowerStateIndex powerState
;
3969 DriverCallParam
* param
;
3970 IOPMDriverCallEntry callEntry
;
3973 uint32_t oldPowerState
= getPowerState();
3975 assert( fDriverCallBusy
);
3976 assert( fDriverCallParamPtr
);
3977 assert( fDriverCallParamCount
== 1 );
3979 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3980 powerState
= fHeadNotePowerState
;
3982 if (assertPMDriverCall(&callEntry
))
3984 OUR_PMLogFuncStart(kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3985 start_spindump_timer("SetState");
3986 clock_get_uptime(&fDriverCallStartTime
);
3987 result
= fControllingDriver
->setPowerState( powerState
, this );
3988 clock_get_uptime(&end
);
3989 stop_spindump_timer();
3990 OUR_PMLogFuncEnd(kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3992 deassertPMDriverCall(&callEntry
);
3994 // Record the most recent max power state residency timings.
3995 // Use with DeviceActiveTimestamp to diagnose tickle issues.
3996 if (powerState
== fHighestPowerState
)
3997 fMaxPowerStateEntryTime
= end
;
3998 else if (oldPowerState
== fHighestPowerState
)
3999 fMaxPowerStateExitTime
= end
;
4003 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
4004 fName
, OBFUSCATE(this), fCurrentPowerState
, powerState
, result
);
4008 if ((result
== IOPMAckImplied
) || (result
< 0))
4012 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
4013 absolutetime_to_nanoseconds(end
, &nsec
);
4014 if (nsec
> LOG_SETPOWER_TIMES
) {
4015 getPMRootDomain()->pmStatsRecordApplicationResponse(
4016 gIOPMStatsDriverPSChangeSlow
,
4017 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
4024 result
= kIOPMAckImplied
;
4026 param
->Result
= result
;
4029 //*********************************************************************************
4030 // [private] driverInformPowerChange
4032 // Thread call context
4033 //*********************************************************************************
4035 void IOService::driverInformPowerChange( void )
4037 IOPMinformee
* informee
;
4039 DriverCallParam
* param
;
4040 IOPMDriverCallEntry callEntry
;
4041 IOPMPowerFlags powerFlags
;
4042 IOPMPowerStateIndex powerState
;
4047 assert( fDriverCallBusy
);
4048 assert( fDriverCallParamPtr
);
4049 assert( fDriverCallParamCount
);
4051 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4052 count
= fDriverCallParamCount
;
4054 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4055 powerState
= fHeadNotePowerState
;
4057 for (IOItemCount i
= 0; i
< count
; i
++)
4059 informee
= (IOPMinformee
*) param
->Target
;
4060 driver
= informee
->whatObject
;
4062 if (assertPMDriverCall(&callEntry
, 0, informee
))
4064 if (fDriverCallReason
== kDriverCallInformPreChange
)
4066 OUR_PMLogFuncStart(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
4067 start_spindump_timer("WillChange");
4068 clock_get_uptime(&informee
->startTime
);
4069 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
4070 clock_get_uptime(&end
);
4071 stop_spindump_timer();
4072 OUR_PMLogFuncEnd(kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
4076 OUR_PMLogFuncStart(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
4077 start_spindump_timer("DidChange");
4078 clock_get_uptime(&informee
->startTime
);
4079 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
4080 clock_get_uptime(&end
);
4081 stop_spindump_timer();
4082 OUR_PMLogFuncEnd(kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
4085 deassertPMDriverCall(&callEntry
);
4088 if ((result
== IOPMAckImplied
) || (result
< 0))
4092 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
4093 absolutetime_to_nanoseconds(end
, &nsec
);
4094 if (nsec
> LOG_SETPOWER_TIMES
) {
4095 getPMRootDomain()->pmStatsRecordApplicationResponse(
4096 gIOPMStatsDriverPSChangeSlow
, driver
->getName(),
4097 fDriverCallReason
, NS_TO_MS(nsec
), driver
->getRegistryEntryID(),
4104 result
= kIOPMAckImplied
;
4106 param
->Result
= result
;
4111 //*********************************************************************************
4112 // [private] notifyChild
4114 // Notify a power domain child of an upcoming power change.
4115 // If the object acknowledges the current change, we return TRUE.
4116 //*********************************************************************************
4118 bool IOService::notifyChild( IOPowerConnection
* theNub
)
4120 IOReturn ret
= IOPMAckImplied
;
4121 unsigned long childPower
;
4122 IOService
* theChild
;
4123 IOPMRequest
* childRequest
;
4124 IOPMPowerChangeFlags requestArg2
;
4127 PM_ASSERT_IN_GATE();
4128 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
4134 // Unless the child handles the notification immediately and returns
4135 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
4136 fHeadNotePendingAcks
++;
4137 theNub
->setAwaitingAck(true);
4139 requestArg2
= fHeadNoteChangeFlags
;
4140 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
))
4141 requestArg2
|= kIOPMDomainPowerDrop
;
4143 requestType
= fIsPreChange
?
4144 kIOPMRequestTypePowerDomainWillChange
:
4145 kIOPMRequestTypePowerDomainDidChange
;
4147 childRequest
= acquirePMRequest( theChild
, requestType
);
4151 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4152 childRequest
->fArg1
= (void *) theNub
;
4153 childRequest
->fArg2
= (void *)(uintptr_t) requestArg2
;
4154 theChild
->submitPMRequest( childRequest
);
4155 ret
= IOPMWillAckLater
;
4159 ret
= IOPMAckImplied
;
4160 fHeadNotePendingAcks
--;
4161 theNub
->setAwaitingAck(false);
4162 childPower
= theChild
->currentPowerConsumption();
4163 if ( childPower
== kIOPMUnknown
)
4165 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4167 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
4168 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4172 theChild
->release();
4173 return (IOPMAckImplied
== ret
);
4176 //*********************************************************************************
4177 // [private] notifyControllingDriver
4178 //*********************************************************************************
4180 bool IOService::notifyControllingDriver( void )
4182 DriverCallParam
* param
;
4184 PM_ASSERT_IN_GATE();
4185 assert( fDriverCallParamCount
== 0 );
4186 assert( fControllingDriver
);
4188 if (fInitialSetPowerState
)
4190 fInitialSetPowerState
= false;
4191 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4193 // Driver specified flag to skip the inital setPowerState()
4194 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)
4200 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4203 param
= IONew(DriverCallParam
, 1);
4205 return false; // no memory
4207 fDriverCallParamPtr
= (void *) param
;
4208 fDriverCallParamSlots
= 1;
4211 param
->Target
= fControllingDriver
;
4212 fDriverCallParamCount
= 1;
4215 // Block state machine and wait for callout completion.
4216 assert(!fDriverCallBusy
);
4217 fDriverCallBusy
= true;
4218 thread_call_enter( fDriverCallEntry
);
4223 //*********************************************************************************
4224 // [private] notifyControllingDriverDone
4225 //*********************************************************************************
4227 void IOService::notifyControllingDriverDone( void )
4229 DriverCallParam
* param
;
4232 PM_ASSERT_IN_GATE();
4233 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4235 assert( fDriverCallBusy
== false );
4236 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4238 if (param
&& fDriverCallParamCount
)
4240 assert(fDriverCallParamCount
== 1);
4242 // the return value from setPowerState()
4243 result
= param
->Result
;
4245 if ((result
== IOPMAckImplied
) || (result
< 0))
4249 else if (fDriverTimer
)
4251 assert(fDriverTimer
== -1);
4253 // Driver has not acked, and has returned a positive result.
4254 // Enforce a minimum permissible timeout value.
4255 // Make the min value large enough so timeout is less likely
4256 // to occur if a driver misinterpreted that the return value
4257 // should be in microsecond units. And make it large enough
4258 // to be noticeable if a driver neglects to ack.
4260 if (result
< kMinAckTimeoutTicks
)
4261 result
= kMinAckTimeoutTicks
;
4263 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4265 // else, child has already acked and driver_timer reset to 0.
4267 fDriverCallParamCount
= 0;
4271 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4276 MS_POP(); // pushed by OurChangeSetPowerState()
4277 fIsPreChange
= false;
4280 //*********************************************************************************
4281 // [private] all_done
4283 // A power change is done.
4284 //*********************************************************************************
4286 void IOService::all_done( void )
4288 IOPMPowerStateIndex prevPowerState
;
4289 const IOPMPSEntry
* powerStatePtr
;
4290 IOPMDriverCallEntry callEntry
;
4291 uint32_t prevMachineState
= fMachineState
;
4292 bool actionCalled
= false;
4295 fMachineState
= kIOPM_Finished
;
4297 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4298 ((prevMachineState
== kIOPM_Finished
) ||
4299 (prevMachineState
== kIOPM_SyncFinish
)))
4301 // Sync operation and no power change occurred.
4302 // Do not inform driver and clients about this request completion,
4303 // except for the originator (root domain).
4305 PM_ACTION_2(actionPowerChangeDone
,
4306 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4308 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
4310 powerChangeDone(fCurrentPowerState
);
4312 else if (fAdvisoryTickleUsed
)
4314 // Not root domain and advisory tickle target.
4315 // Re-adjust power after power tree sync at the 'did' pass
4316 // to recompute desire and adjust power state between dark
4317 // and full wake transitions. Root domain is responsible
4318 // for calling setAdvisoryTickleEnable() before starting
4319 // the kIOPMSynchronize power change.
4321 if (!fAdjustPowerScheduled
&&
4322 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
))
4324 IOPMRequest
* request
;
4325 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4328 submitPMRequest( request
);
4329 fAdjustPowerScheduled
= true;
4338 if (fHeadNoteChangeFlags
& kIOPMSelfInitiated
)
4340 // power state changed
4341 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0)
4343 trackSystemSleepPreventers(
4344 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4346 // we changed, tell our parent
4347 requestDomainPower(fHeadNotePowerState
);
4349 // yes, did power raise?
4350 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4352 // yes, inform clients and apps
4353 tellChangeUp (fHeadNotePowerState
);
4355 prevPowerState
= fCurrentPowerState
;
4357 fCurrentPowerState
= fHeadNotePowerState
;
4360 ts
= mach_absolute_time();
4361 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4365 fPMVars
->myCurrentState
= fCurrentPowerState
;
4367 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4368 PM_ACTION_2(actionPowerChangeDone
,
4369 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4370 actionCalled
= true;
4372 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4373 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4374 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4375 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4377 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4379 // Bump tickle generation count once the entire tree is down
4380 gIOPMTickleGeneration
++;
4383 // inform subclass policy-maker
4384 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4385 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4387 powerChangeDone(prevPowerState
);
4388 deassertPMDriverCall(&callEntry
);
4391 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
4393 // changePowerStateWithOverrideTo() was cancelled
4394 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4398 // parent-initiated power change
4399 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
4401 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4402 ParentChangeRootChangeDown();
4404 // power state changed
4405 if ((fHeadNoteChangeFlags
& kIOPMNotDone
) == 0)
4407 trackSystemSleepPreventers(
4408 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4411 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4413 // yes, inform clients and apps
4414 tellChangeUp (fHeadNotePowerState
);
4417 prevPowerState
= fCurrentPowerState
;
4418 fCurrentPowerState
= fHeadNotePowerState
;
4421 ts
= mach_absolute_time();
4422 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4426 fPMVars
->myCurrentState
= fCurrentPowerState
;
4429 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4430 PM_ACTION_2(actionPowerChangeDone
,
4431 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4432 actionCalled
= true;
4434 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4435 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4436 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4437 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4439 // inform subclass policy-maker
4440 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4441 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4443 powerChangeDone(prevPowerState
);
4444 deassertPMDriverCall(&callEntry
);
4449 // When power rises enough to satisfy the tickle's desire for more power,
4450 // the condition preventing idle-timer from dropping power is removed.
4452 if (StateOrder(fCurrentPowerState
) >= StateOrder(fIdleTimerMinPowerState
))
4454 fIdleTimerMinPowerState
= kPowerStateZero
;
4459 PM_ACTION_2(actionPowerChangeDone
,
4460 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4465 // MARK: Power Change Initiated by Driver
4467 //*********************************************************************************
4468 // [private] OurChangeStart
4470 // Begin the processing of a power change initiated by us.
4471 //*********************************************************************************
4473 void IOService::OurChangeStart( void )
4475 PM_ASSERT_IN_GATE();
4476 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4478 // fMaxPowerState is our maximum possible power state based on the current
4479 // power state of our parents. If we are trying to raise power beyond the
4480 // maximum, send an async request for more power to all parents.
4482 if (!IS_PM_ROOT
&& (StateOrder(fMaxPowerState
) < StateOrder(fHeadNotePowerState
)))
4484 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4485 requestDomainPower(fHeadNotePowerState
);
4490 // Redundant power changes skips to the end of the state machine.
4492 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
4497 fInitialPowerChange
= false;
4499 // Change started, but may not complete...
4500 // Can be canceled (power drop) or deferred (power rise).
4502 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4504 // Two separate paths, depending if power is being raised or lowered.
4505 // Lowering power is subject to approval by clients of this service.
4509 fDoNotPowerDown
= false;
4511 // Ask for persmission to drop power state
4512 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4513 fOutOfBandParameter
= kNotifyApps
;
4514 askChangeDown(fHeadNotePowerState
);
4518 // This service is raising power and parents are able to support the
4519 // new power state. However a parent may have already committed to
4520 // drop power, which might force this object to temporarily drop power.
4521 // This results in "oscillations" before the state machines converge
4522 // to a steady state.
4524 // To prevent this, a child must make a power reservation against all
4525 // parents before raising power. If the reservation fails, indicating
4526 // that the child will be unable to sustain the higher power state,
4527 // then the child will signal the parent to adjust power, and the child
4528 // will defer its power change.
4532 // Reserve parent power necessary to achieve fHeadNotePowerState.
4533 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4534 if (ret
!= kIOReturnSuccess
)
4536 // Reservation failed, defer power rise.
4537 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4542 OurChangeTellCapabilityWillChange();
4546 //*********************************************************************************
4547 // [private] requestDomainPowerApplier
4549 // Call requestPowerDomainState() on all power parents.
4550 //*********************************************************************************
4552 struct IOPMRequestDomainPowerContext
{
4553 IOService
* child
; // the requesting child
4554 IOPMPowerFlags requestPowerFlags
; // power flags requested by child
4558 requestDomainPowerApplier(
4559 IORegistryEntry
* entry
,
4562 IOPowerConnection
* connection
;
4564 IOPMRequestDomainPowerContext
* context
;
4566 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0)
4568 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4573 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4575 if (connection
->parentKnowsState() && connection
->getReadyFlag())
4577 parent
->requestPowerDomainState(
4578 context
->requestPowerFlags
,
4586 //*********************************************************************************
4587 // [private] requestDomainPower
4589 // Called by a power child to broadcast its desired power state to all parents.
4590 // If the child self-initiates a power change, it must call this function to
4591 // allow its parents to adjust power state.
4592 //*********************************************************************************
4594 IOReturn
IOService::requestDomainPower(
4595 IOPMPowerStateIndex ourPowerState
,
4596 IOOptionBits options
)
4598 IOPMPowerFlags requestPowerFlags
;
4599 IOPMPowerStateIndex maxPowerState
;
4600 IOPMRequestDomainPowerContext context
;
4602 PM_ASSERT_IN_GATE();
4603 assert(ourPowerState
< fNumberOfPowerStates
);
4604 if (ourPowerState
>= fNumberOfPowerStates
)
4605 return kIOReturnBadArgument
;
4607 return kIOReturnSuccess
;
4609 // Fetch our input power flags for the requested power state.
4610 // Parent request is stated in terms of required power flags.
4612 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4614 // Disregard the "previous request" for power reservation.
4616 if (((options
& kReserveDomainPower
) == 0) &&
4617 (fPreviousRequestPowerFlags
== requestPowerFlags
))
4619 // skip if domain already knows our requirements
4622 fPreviousRequestPowerFlags
= requestPowerFlags
;
4624 // The results will be collected by fHeadNoteDomainTargetFlags
4625 context
.child
= this;
4626 context
.requestPowerFlags
= requestPowerFlags
;
4627 fHeadNoteDomainTargetFlags
= 0;
4628 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4630 if (options
& kReserveDomainPower
)
4632 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4633 fHeadNoteDomainTargetFlags
);
4635 if (StateOrder(maxPowerState
) < StateOrder(ourPowerState
))
4637 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4639 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4640 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4641 return kIOReturnNoPower
;
4646 return kIOReturnSuccess
;
4649 //*********************************************************************************
4650 // [private] OurSyncStart
4651 //*********************************************************************************
4653 void IOService::OurSyncStart( void )
4655 PM_ASSERT_IN_GATE();
4657 if (fInitialPowerChange
)
4660 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4662 if (fHeadNoteChangeFlags
& kIOPMNotDone
)
4668 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
)
4670 fDoNotPowerDown
= false;
4672 // Ask for permission to drop power state
4673 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4674 fOutOfBandParameter
= kNotifyApps
;
4675 askChangeDown(fHeadNotePowerState
);
4679 // Only inform capability app and clients.
4680 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4684 //*********************************************************************************
4685 // [private] OurChangeTellClientsPowerDown
4687 // All applications and kernel clients have acknowledged our permission to drop
4688 // power. Here we notify them that we will lower the power and wait for acks.
4689 //*********************************************************************************
4691 void IOService::OurChangeTellClientsPowerDown( void )
4694 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4697 fMachineState
= kIOPM_OurChangeTellUserPMPolicyPowerDown
;
4699 tellChangeDown1(fHeadNotePowerState
);
4702 //*********************************************************************************
4703 // [private] OurChangeTellUserPMPolicyPowerDown
4705 // All applications and kernel clients have acknowledged our permission to drop
4706 // power. Here we notify power management policy in user-space and wait for acks
4707 // one last time before we lower power
4708 //*********************************************************************************
4709 void IOService::OurChangeTellUserPMPolicyPowerDown ( void )
4711 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4712 fOutOfBandParameter
= kNotifyApps
;
4714 tellClientsWithResponse(kIOPMMessageLastCallBeforeSleep
);
4717 //*********************************************************************************
4718 // [private] OurChangeTellPriorityClientsPowerDown
4720 // All applications and kernel clients have acknowledged our intention to drop
4721 // power. Here we notify "priority" clients that we are lowering power.
4722 //*********************************************************************************
4724 void IOService::OurChangeTellPriorityClientsPowerDown( void )
4726 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4727 tellChangeDown2(fHeadNotePowerState
);
4730 //*********************************************************************************
4731 // [private] OurChangeTellCapabilityWillChange
4733 // Extra stage for root domain to notify apps and drivers about the
4734 // system capability change when raising power state.
4735 //*********************************************************************************
4737 void IOService::OurChangeTellCapabilityWillChange( void )
4739 if (!IS_ROOT_DOMAIN
)
4740 return OurChangeNotifyInterestedDriversWillChange();
4742 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4745 //*********************************************************************************
4746 // [private] OurChangeNotifyInterestedDriversWillChange
4748 // All applications and kernel clients have acknowledged our power state change.
4749 // Here we notify interested drivers pre-change.
4750 //*********************************************************************************
4752 void IOService::OurChangeNotifyInterestedDriversWillChange( void )
4754 IOPMrootDomain
* rootDomain
;
4755 if ((rootDomain
= getPMRootDomain()) == this)
4759 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4762 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4765 notifyAll( kIOPM_OurChangeSetPowerState
);
4768 //*********************************************************************************
4769 // [private] OurChangeSetPowerState
4771 // Instruct our controlling driver to program the hardware for the power state
4772 // change. Wait for async completions.
4773 //*********************************************************************************
4775 void IOService::OurChangeSetPowerState( void )
4777 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4778 fMachineState
= kIOPM_DriverThreadCallDone
;
4779 fDriverCallReason
= kDriverCallSetPowerState
;
4781 if (notifyControllingDriver() == false)
4782 notifyControllingDriverDone();
4785 //*********************************************************************************
4786 // [private] OurChangeWaitForPowerSettle
4788 // Our controlling driver has completed the power state change we initiated.
4789 // Wait for the driver specified settle time to expire.
4790 //*********************************************************************************
4792 void IOService::OurChangeWaitForPowerSettle( void )
4794 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4798 //*********************************************************************************
4799 // [private] OurChangeNotifyInterestedDriversDidChange
4801 // Power has settled on a power change we initiated. Here we notify
4802 // all our interested drivers post-change.
4803 //*********************************************************************************
4805 void IOService::OurChangeNotifyInterestedDriversDidChange( void )
4807 IOPMrootDomain
* rootDomain
;
4808 if ((rootDomain
= getPMRootDomain()) == this)
4810 rootDomain
->tracePoint( IS_POWER_DROP
?
4811 kIOPMTracePointSleepDidChangeInterests
:
4812 kIOPMTracePointWakeDidChangeInterests
);
4815 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4818 //*********************************************************************************
4819 // [private] OurChangeTellCapabilityDidChange
4821 // For root domain to notify capability power-change.
4822 //*********************************************************************************
4824 void IOService::OurChangeTellCapabilityDidChange( void )
4826 if (!IS_ROOT_DOMAIN
)
4827 return OurChangeFinish();
4829 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4830 kIOPMTracePointSleepCapabilityClients
:
4831 kIOPMTracePointWakeCapabilityClients
);
4833 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4836 //*********************************************************************************
4837 // [private] OurChangeFinish
4839 // Done with this self-induced power state change.
4840 //*********************************************************************************
4842 void IOService::OurChangeFinish( void )
4848 // MARK: Power Change Initiated by Parent
4850 //*********************************************************************************
4851 // [private] ParentChangeStart
4853 // Here we begin the processing of a power change initiated by our parent.
4854 //*********************************************************************************
4856 IOReturn
IOService::ParentChangeStart( void )
4858 PM_ASSERT_IN_GATE();
4859 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4861 // Root power domain has transitioned to its max power state
4862 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4863 (kIOPMDomainDidChange
| kIOPMRootChangeUp
))
4865 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4866 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
4872 // Power domain is forcing us to lower power
4873 if ( StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
) )
4875 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4877 // Tell apps and kernel clients
4878 fInitialPowerChange
= false;
4879 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4880 tellChangeDown1(fHeadNotePowerState
);
4881 return IOPMWillAckLater
;
4884 // Power domain is allowing us to raise power up to fHeadNotePowerState
4885 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4887 if ( StateOrder(fDesiredPowerState
) > StateOrder(fCurrentPowerState
) )
4889 if ( StateOrder(fDesiredPowerState
) < StateOrder(fHeadNotePowerState
) )
4891 // We power up, but not all the way
4892 fHeadNotePowerState
= fDesiredPowerState
;
4893 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4894 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4897 // We don't need to change
4898 fHeadNotePowerState
= fCurrentPowerState
;
4899 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4900 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4904 if ( fHeadNoteChangeFlags
& kIOPMDomainDidChange
)
4906 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4908 PM_ACTION_2(actionPowerChangeStart
,
4909 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4911 // Parent did change up - start our change up
4912 fInitialPowerChange
= false;
4913 ParentChangeTellCapabilityWillChange();
4914 return IOPMWillAckLater
;
4916 else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
)
4918 // No need to change power state, but broadcast change
4920 fMachineState
= kIOPM_SyncNotifyDidChange
;
4921 fDriverCallReason
= kDriverCallInformPreChange
;
4922 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4924 return IOPMWillAckLater
;
4928 // No power state change necessary
4929 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4932 return IOPMAckImplied
;
4935 //******************************************************************************
4936 // [private] ParentChangeRootChangeDown
4938 // Root domain has finished the transition to the system sleep state. And all
4939 // drivers in the power plane should have powered down. Cancel the idle timer,
4940 // and also reset the device desire for those drivers that don't want power
4941 // automatically restored on wake.
4942 //******************************************************************************
4944 void IOService::ParentChangeRootChangeDown( void )
4946 // Always stop the idle timer before root power down
4947 if (fIdleTimerPeriod
&& !fIdleTimerStopped
)
4949 fIdleTimerStopped
= true;
4950 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
4954 if (fResetPowerStateOnWake
)
4956 // Reset device desire down to the lowest power state.
4957 // Advisory tickle desire is intentionally untouched since
4958 // it has no effect until system is promoted to full wake.
4960 if (fDeviceDesire
!= kPowerStateZero
)
4962 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4963 computeDesiredState(kPowerStateZero
, true);
4964 requestDomainPower( fDesiredPowerState
);
4965 PM_LOG1("%s: tickle desire removed\n", fName
);
4968 // Invalidate tickle cache so the next tickle will issue a request
4969 IOLockLock(fActivityLock
);
4970 fDeviceWasActive
= false;
4971 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4972 IOLockUnlock(fActivityLock
);
4974 fIdleTimerMinPowerState
= kPowerStateZero
;
4976 else if (fAdvisoryTickleUsed
)
4978 // Less aggressive mechanism to accelerate idle timer expiration
4979 // before system sleep. May not always allow the driver to wake
4980 // up from system sleep in the min power state.
4984 bool dropTickleDesire
= false;
4986 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
4987 (fIdleTimerMinPowerState
== kPowerStateZero
) &&
4988 (fDeviceDesire
!= kPowerStateZero
))
4990 IOLockLock(fActivityLock
);
4992 if (!fDeviceWasActive
)
4994 // No tickles since the last idle timer expiration.
4995 // Safe to drop the device desire to zero.
4996 dropTickleDesire
= true;
5000 // Was tickled since the last idle timer expiration,
5001 // but not in the last minute.
5002 clock_get_uptime(&now
);
5003 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
5004 absolutetime_to_nanoseconds(now
, &nsec
);
5005 if (nsec
>= kNoTickleCancelWindow
)
5007 dropTickleDesire
= true;
5011 if (dropTickleDesire
)
5013 // Force the next tickle to raise power state
5014 fDeviceWasActive
= false;
5015 fActivityTicklePowerState
= kInvalidTicklePowerState
;
5018 IOLockUnlock(fActivityLock
);
5021 if (dropTickleDesire
)
5023 // Advisory tickle desire is intentionally untouched since
5024 // it has no effect until system is promoted to full wake.
5026 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
5027 computeDesiredState(kPowerStateZero
, true);
5028 PM_LOG1("%s: tickle desire dropped\n", fName
);
5033 //*********************************************************************************
5034 // [private] ParentChangeTellPriorityClientsPowerDown
5036 // All applications and kernel clients have acknowledged our intention to drop
5037 // power. Here we notify "priority" clients that we are lowering power.
5038 //*********************************************************************************
5040 void IOService::ParentChangeTellPriorityClientsPowerDown( void )
5042 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
5043 tellChangeDown2(fHeadNotePowerState
);
5046 //*********************************************************************************
5047 // [private] ParentChangeTellCapabilityWillChange
5049 // All (legacy) applications and kernel clients have acknowledged, extra stage for
5050 // root domain to notify apps and drivers about the system capability change.
5051 //*********************************************************************************
5053 void IOService::ParentChangeTellCapabilityWillChange( void )
5055 if (!IS_ROOT_DOMAIN
)
5056 return ParentChangeNotifyInterestedDriversWillChange();
5058 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
5061 //*********************************************************************************
5062 // [private] ParentChangeNotifyInterestedDriversWillChange
5064 // All applications and kernel clients have acknowledged our power state change.
5065 // Here we notify interested drivers pre-change.
5066 //*********************************************************************************
5068 void IOService::ParentChangeNotifyInterestedDriversWillChange( void )
5070 notifyAll( kIOPM_ParentChangeSetPowerState
);
5073 //*********************************************************************************
5074 // [private] ParentChangeSetPowerState
5076 // Instruct our controlling driver to program the hardware for the power state
5077 // change. Wait for async completions.
5078 //*********************************************************************************
5080 void IOService::ParentChangeSetPowerState( void )
5082 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
5083 fMachineState
= kIOPM_DriverThreadCallDone
;
5084 fDriverCallReason
= kDriverCallSetPowerState
;
5086 if (notifyControllingDriver() == false)
5087 notifyControllingDriverDone();
5090 //*********************************************************************************
5091 // [private] ParentChangeWaitForPowerSettle
5093 // Our controlling driver has completed the power state change initiated by our
5094 // parent. Wait for the driver specified settle time to expire.
5095 //*********************************************************************************
5097 void IOService::ParentChangeWaitForPowerSettle( void )
5099 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
5103 //*********************************************************************************
5104 // [private] ParentChangeNotifyInterestedDriversDidChange
5106 // Power has settled on a power change initiated by our parent. Here we notify
5107 // all our interested drivers post-change.
5108 //*********************************************************************************
5110 void IOService::ParentChangeNotifyInterestedDriversDidChange( void )
5112 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
5115 //*********************************************************************************
5116 // [private] ParentChangeTellCapabilityDidChange
5118 // For root domain to notify capability power-change.
5119 //*********************************************************************************
5121 void IOService::ParentChangeTellCapabilityDidChange( void )
5123 if (!IS_ROOT_DOMAIN
)
5124 return ParentChangeAcknowledgePowerChange();
5126 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
5129 //*********************************************************************************
5130 // [private] ParentAcknowledgePowerChange
5132 // Acknowledge our power parent that our power change is done.
5133 //*********************************************************************************
5135 void IOService::ParentChangeAcknowledgePowerChange( void )
5137 IORegistryEntry
* nub
;
5140 nub
= fHeadNoteParentConnection
;
5143 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
5146 parent
->acknowledgePowerChange((IOService
*)nub
);
5153 // MARK: Ack and Settle timers
5155 //*********************************************************************************
5156 // [private] settleTimerExpired
5158 // Power has settled after our last change. Notify interested parties that
5159 // there is a new power state.
5160 //*********************************************************************************
5162 void IOService::settleTimerExpired( void )
5165 gIOPMWorkQueue
->signalWorkAvailable();
5168 //*********************************************************************************
5169 // settle_timer_expired
5171 // Holds a retain while the settle timer callout is in flight.
5172 //*********************************************************************************
5175 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5177 IOService
* me
= (IOService
*) arg0
;
5179 if (gIOPMWorkLoop
&& gIOPMWorkQueue
)
5181 gIOPMWorkLoop
->runAction(
5182 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5188 //*********************************************************************************
5189 // [private] startSettleTimer
5191 // Calculate a power-settling delay in microseconds and start a timer.
5192 //*********************************************************************************
5194 void IOService::startSettleTimer( void )
5197 // This function is broken and serves no useful purpose since it never
5198 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5199 // yet it starts a delay timer. It appears no driver relies on a delay
5200 // from settleUpTime and settleDownTime in the power state table.
5202 AbsoluteTime deadline
;
5203 IOPMPowerStateIndex stateIndex
;
5204 IOPMPowerStateIndex currentOrder
, newOrder
, i
;
5205 uint32_t settleTime
= 0;
5208 PM_ASSERT_IN_GATE();
5210 currentOrder
= StateOrder(fCurrentPowerState
);
5211 newOrder
= StateOrder(fHeadNotePowerState
);
5216 if ( newOrder
< currentOrder
)
5218 while ( i
> newOrder
)
5220 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
5221 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleDownTime
;
5227 if ( newOrder
> currentOrder
)
5229 while ( i
< newOrder
)
5231 stateIndex
= fPowerStates
[i
+1].stateOrderToIndex
;
5232 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleUpTime
;
5240 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5241 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5242 if (pending
) release();
5247 //*********************************************************************************
5248 // [private] ackTimerTick
5250 // The acknowledgement timeout periodic timer has ticked.
5251 // If we are awaiting acks for a power change notification,
5252 // we decrement the timer word of each interested driver which hasn't acked.
5253 // If a timer word becomes zero, we pretend the driver aknowledged.
5254 // If we are waiting for the controlling driver to change the power
5255 // state of the hardware, we decrement its timer word, and if it becomes
5256 // zero, we pretend the driver acknowledged.
5258 // Returns true if the timer tick made it possible to advance to the next
5259 // machine state, false otherwise.
5260 //*********************************************************************************
5263 void IOService::ack_timer_ticked ( void )
5267 #endif /* !__LP64__ */
5269 bool IOService::ackTimerTick( void )
5271 IOPMinformee
* nextObject
;
5274 PM_ASSERT_IN_GATE();
5275 switch (fMachineState
) {
5276 case kIOPM_OurChangeWaitForPowerSettle
:
5277 case kIOPM_ParentChangeWaitForPowerSettle
:
5278 // are we waiting for controlling driver to acknowledge?
5279 if ( fDriverTimer
> 0 )
5281 // yes, decrement timer tick
5283 if ( fDriverTimer
== 0 )
5285 // controlling driver is tardy
5286 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5287 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
5288 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
5289 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5290 fName
, OBFUSCATE(this), fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5292 if (gIOKitDebug
& kIOLogDebugPower
)
5294 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5295 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5299 // Unblock state machine and pretend driver has acked.
5303 // still waiting, set timer again
5309 case kIOPM_NotifyChildrenStart
:
5310 // are we waiting for interested parties to acknowledge?
5311 if ( fHeadNotePendingAcks
!= 0 )
5313 // yes, go through the list of interested drivers
5314 nextObject
= fInterestedDrivers
->firstInList();
5315 // and check each one
5316 while ( nextObject
!= NULL
)
5318 if ( nextObject
->timer
> 0 )
5320 nextObject
->timer
--;
5321 // this one should have acked by now
5322 if ( nextObject
->timer
== 0 )
5324 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5325 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5326 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5327 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5328 nextObject
->whatObject
->getName(),
5329 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5330 OBFUSCATE(nextObject
->whatObject
), fName
, fCurrentPowerState
, fHeadNotePowerState
,
5333 // Pretend driver has acked.
5334 fHeadNotePendingAcks
--;
5337 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5340 // is that the last?
5341 if ( fHeadNotePendingAcks
== 0 )
5343 // yes, we can continue
5346 // no, set timer again
5352 // TODO: aggreggate this
5353 case kIOPM_OurChangeTellClientsPowerDown
:
5354 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
5355 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5356 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5357 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5358 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5359 case kIOPM_SyncTellClientsPowerDown
:
5360 case kIOPM_SyncTellPriorityClientsPowerDown
:
5361 case kIOPM_SyncNotifyWillChange
:
5362 case kIOPM_TellCapabilityChangeDone
:
5363 // apps didn't respond in time
5364 cleanClientResponses(true);
5365 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5366 // tardy equates to approval
5371 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5372 getName(), fMachineState
);
5378 //*********************************************************************************
5379 // [private] start_watchdog_timer
5380 //*********************************************************************************
5381 void IOService::start_watchdog_timer( void )
5383 AbsoluteTime deadline
;
5385 static int timeout
= -1;
5387 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5390 if (thread_call_isactive(fWatchdogTimer
)) return;
5391 if (timeout
== -1) {
5392 PE_parse_boot_argn("swd_timeout", &timeout
, sizeof(timeout
));
5395 timeout
= WATCHDOG_TIMER_PERIOD
;
5398 clock_interval_to_deadline(timeout
, kSecondScale
, &deadline
);
5401 pending
= thread_call_enter_delayed(fWatchdogTimer
, deadline
);
5402 if (pending
) release();
5406 //*********************************************************************************
5407 // [private] stop_watchdog_timer
5408 // Returns true if watchdog was enabled and stopped now
5409 //*********************************************************************************
5411 bool IOService::stop_watchdog_timer( void )
5415 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5418 pending
= thread_call_cancel(fWatchdogTimer
);
5419 if (pending
) release();
5424 //*********************************************************************************
5425 // reset_watchdog_timer
5426 //*********************************************************************************
5428 void IOService::reset_watchdog_timer( void )
5430 if (stop_watchdog_timer())
5431 start_watchdog_timer();
5435 //*********************************************************************************
5436 // [static] watchdog_timer_expired
5438 // Inside PM work loop's gate.
5439 //*********************************************************************************
5442 IOService::watchdog_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5444 IOService
* me
= (IOService
*) arg0
;
5447 gIOPMWatchDogThread
= current_thread();
5448 getPMRootDomain()->sleepWakeDebugTrig(true);
5449 gIOPMWatchDogThread
= 0;
5450 thread_call_free(me
->fWatchdogTimer
);
5451 me
->fWatchdogTimer
= 0;
5457 IOWorkLoop
* IOService::getIOPMWorkloop( void )
5459 return gIOPMWorkLoop
;
5464 //*********************************************************************************
5465 // [private] start_ack_timer
5466 //*********************************************************************************
5468 void IOService::start_ack_timer( void )
5470 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5473 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
5475 AbsoluteTime deadline
;
5478 clock_interval_to_deadline(interval
, scale
, &deadline
);
5481 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5482 if (pending
) release();
5484 // Stop watchdog if ack is delayed by more than a sec
5485 if (interval
* scale
> kSecondScale
) {
5486 stop_watchdog_timer();
5490 //*********************************************************************************
5491 // [private] stop_ack_timer
5492 //*********************************************************************************
5494 void IOService::stop_ack_timer( void )
5498 pending
= thread_call_cancel(fAckTimer
);
5499 if (pending
) release();
5501 start_watchdog_timer();
5504 //*********************************************************************************
5505 // [static] actionAckTimerExpired
5507 // Inside PM work loop's gate.
5508 //*********************************************************************************
5511 IOService::actionAckTimerExpired(
5513 void * arg0
, void * arg1
,
5514 void * arg2
, void * arg3
)
5516 IOService
* me
= (IOService
*) target
;
5519 // done will be true if the timer tick unblocks the machine state,
5520 // otherwise no need to signal the work loop.
5522 done
= me
->ackTimerTick();
5523 if (done
&& gIOPMWorkQueue
)
5525 gIOPMWorkQueue
->signalWorkAvailable();
5526 me
->start_watchdog_timer();
5529 return kIOReturnSuccess
;
5532 //*********************************************************************************
5533 // ack_timer_expired
5535 // Thread call function. Holds a retain while the callout is in flight.
5536 //*********************************************************************************
5539 IOService::ack_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5541 IOService
* me
= (IOService
*) arg0
;
5545 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5550 //*********************************************************************************
5551 // [private] start_spindump_timer
5552 //*********************************************************************************
5554 void IOService::start_spindump_timer( const char * delay_type
)
5556 AbsoluteTime deadline
;
5559 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
))
5562 if (gIOSpinDumpKextName
[0] == '\0' &&
5563 !(PE_parse_boot_argn("swd_kext_name", &gIOSpinDumpKextName
,
5564 sizeof(gIOSpinDumpKextName
))))
5569 if (strncmp(gIOSpinDumpKextName
, fName
, sizeof(gIOSpinDumpKextName
)) != 0)
5572 if (gIOSpinDumpDelayType
[0] == '\0' &&
5573 !(PE_parse_boot_argn("swd_delay_type", &gIOSpinDumpDelayType
,
5574 sizeof(gIOSpinDumpDelayType
))))
5576 strncpy(gIOSpinDumpDelayType
, "SetState", sizeof(gIOSpinDumpDelayType
));
5579 if (strncmp(delay_type
, gIOSpinDumpDelayType
, sizeof(gIOSpinDumpDelayType
)) != 0)
5582 if (gIOSpinDumpDelayDuration
== 0 &&
5583 !(PE_parse_boot_argn("swd_delay_duration", &gIOSpinDumpDelayDuration
,
5584 sizeof(gIOSpinDumpDelayDuration
))))
5586 gIOSpinDumpDelayDuration
= 300;
5589 clock_interval_to_deadline(gIOSpinDumpDelayDuration
, kMillisecondScale
, &deadline
);
5592 pending
= thread_call_enter_delayed(fSpinDumpTimer
, deadline
);
5593 if (pending
) release();
5596 //*********************************************************************************
5597 // [private] stop_spindump_timer
5598 //*********************************************************************************
5600 void IOService::stop_spindump_timer( void )
5604 if (!fSpinDumpTimer
|| !(kIOKextSpinDump
& gIOKitDebug
))
5607 pending
= thread_call_cancel(fSpinDumpTimer
);
5608 if (pending
) release();
5612 //*********************************************************************************
5613 // [static] actionSpinDumpTimerExpired
5615 // Inside PM work loop's gate.
5616 //*********************************************************************************
5619 IOService::actionSpinDumpTimerExpired(
5621 void * arg0
, void * arg1
,
5622 void * arg2
, void * arg3
)
5624 getPMRootDomain()->takeStackshot(false, false, true);
5626 return kIOReturnSuccess
;
5629 //*********************************************************************************
5630 // spindump_timer_expired
5632 // Thread call function. Holds a retain while the callout is in flight.
5633 //*********************************************************************************
5636 IOService::spindump_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5638 IOService
* me
= (IOService
*) arg0
;
5642 gIOPMWorkLoop
->runAction(&actionSpinDumpTimerExpired
, me
);
5648 // MARK: Client Messaging
5650 //*********************************************************************************
5651 // [private] tellSystemCapabilityChange
5652 //*********************************************************************************
5654 void IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5657 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5658 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5662 // Notify app first on pre-change.
5663 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5667 // Notify kernel clients first on post-change.
5668 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5671 tellClientsWithResponse( fOutOfBandMessage
);
5674 //*********************************************************************************
5675 // [public] askChangeDown
5677 // Ask registered applications and kernel clients if we can change to a lower
5680 // Subclass can override this to send a different message type. Parameter is
5681 // the destination state number.
5683 // Return true if we don't have to wait for acknowledgements
5684 //*********************************************************************************
5686 bool IOService::askChangeDown( unsigned long stateNum
)
5688 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5691 //*********************************************************************************
5692 // [private] tellChangeDown1
5694 // Notify registered applications and kernel clients that we are definitely
5697 // Return true if we don't have to wait for acknowledgements
5698 //*********************************************************************************
5700 bool IOService::tellChangeDown1( unsigned long stateNum
)
5702 fOutOfBandParameter
= kNotifyApps
;
5703 return tellChangeDown(stateNum
);
5706 //*********************************************************************************
5707 // [private] tellChangeDown2
5709 // Notify priority clients that we are definitely dropping power.
5711 // Return true if we don't have to wait for acknowledgements
5712 //*********************************************************************************
5714 bool IOService::tellChangeDown2( unsigned long stateNum
)
5716 fOutOfBandParameter
= kNotifyPriority
;
5717 return tellChangeDown(stateNum
);
5720 //*********************************************************************************
5721 // [public] tellChangeDown
5723 // Notify registered applications and kernel clients that we are definitely
5726 // Subclass can override this to send a different message type. Parameter is
5727 // the destination state number.
5729 // Return true if we don't have to wait for acknowledgements
5730 //*********************************************************************************
5732 bool IOService::tellChangeDown( unsigned long stateNum
)
5734 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5737 //*********************************************************************************
5738 // cleanClientResponses
5740 //*********************************************************************************
5742 static void logAppTimeouts( OSObject
* object
, void * arg
)
5744 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5746 unsigned int clientIndex
;
5750 if (OSDynamicCast(_IOServiceInterestNotifier
, object
))
5752 // Discover the 'counter' value or index assigned to this client
5753 // when it was notified, by searching for the array index of the
5754 // client in an array holding the cached interested clients.
5756 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5758 if ((clientIndex
!= (unsigned int) -1) &&
5759 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5760 (flag
!= kOSBooleanTrue
))
5762 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5766 pid
= clientID
->unsigned32BitValue();
5767 proc_name(pid
, name
, sizeof(name
));
5768 clientID
->release();
5771 PM_ERROR(context
->errorLog
, pid
, name
);
5773 // TODO: record message type if possible
5774 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5775 gIOPMStatsApplicationResponseTimedOut
,
5776 name
, 0, (30*1000), pid
, object
);
5782 void IOService::cleanClientResponses( bool logErrors
)
5784 if (logErrors
&& fResponseArray
)
5786 switch ( fOutOfBandParameter
) {
5788 case kNotifyCapabilityChangeApps
:
5789 if (fNotifyClientArray
)
5791 IOPMInterestContext context
;
5793 context
.responseArray
= fResponseArray
;
5794 context
.notifyClients
= fNotifyClientArray
;
5795 context
.serialNumber
= fSerialNumber
;
5796 context
.messageType
= kIOMessageCopyClientID
;
5797 context
.notifyType
= kNotifyApps
;
5798 context
.isPreChange
= fIsPreChange
;
5799 context
.enableTracing
= false;
5801 context
.maxTimeRequested
= 0;
5802 context
.stateNumber
= fHeadNotePowerState
;
5803 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5804 context
.changeFlags
= fHeadNoteChangeFlags
;
5805 context
.errorLog
= "PM notification timeout (pid %d, %s)\n";
5807 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5812 // kNotifyPriority, kNotifyCapabilityChangePriority
5813 // TODO: identify the priority client that has not acked
5814 PM_ERROR("PM priority notification timeout\n");
5815 if (gIOKitDebug
& kIOLogDebugPower
)
5817 panic("PM priority notification timeout");
5825 fResponseArray
->release();
5826 fResponseArray
= NULL
;
5828 if (fNotifyClientArray
)
5830 fNotifyClientArray
->release();
5831 fNotifyClientArray
= NULL
;
5835 //*********************************************************************************
5836 // [protected] tellClientsWithResponse
5838 // Notify registered applications and kernel clients that we are definitely
5841 // Return true if we don't have to wait for acknowledgements
5842 //*********************************************************************************
5844 bool IOService::tellClientsWithResponse( int messageType
)
5846 IOPMInterestContext context
;
5847 bool isRootDomain
= IS_ROOT_DOMAIN
;
5848 uint32_t maxTimeOut
= kMaxTimeRequested
;
5850 PM_ASSERT_IN_GATE();
5851 assert( fResponseArray
== NULL
);
5852 assert( fNotifyClientArray
== NULL
);
5854 if(messageType
== (int)kIOPMMessageLastCallBeforeSleep
)
5855 RD_LOG("tellClientsWithResponse( kIOPMMessageLastCallBeforeSleep, %d )\n",
5856 fOutOfBandParameter
);
5858 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5859 getIOMessageString(messageType
), fOutOfBandParameter
);
5861 fResponseArray
= OSArray::withCapacity( 1 );
5862 if (!fResponseArray
)
5865 fResponseArray
->setCapacityIncrement(8);
5866 if (++fSerialNumber
== 0)
5869 context
.responseArray
= fResponseArray
;
5870 context
.notifyClients
= 0;
5871 context
.serialNumber
= fSerialNumber
;
5872 context
.messageType
= messageType
;
5873 context
.notifyType
= fOutOfBandParameter
;
5874 context
.isPreChange
= fIsPreChange
;
5875 context
.enableTracing
= false;
5877 context
.maxTimeRequested
= 0;
5878 context
.stateNumber
= fHeadNotePowerState
;
5879 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5880 context
.changeFlags
= fHeadNoteChangeFlags
;
5881 context
.messageFilter
= (isRootDomain
) ?
5882 OSMemberFunctionCast(
5885 &IOPMrootDomain::systemMessageFilter
) : 0;
5887 switch ( fOutOfBandParameter
) {
5889 applyToInterested( gIOAppPowerStateInterest
,
5890 pmTellAppWithResponse
, (void *) &context
);
5893 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5894 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
) &&
5895 (context
.messageType
!= kIOPMMessageLastCallBeforeSleep
))
5897 // Notify capability app for tellChangeDown1()
5898 // but not for askChangeDown().
5899 context
.notifyType
= kNotifyCapabilityChangeApps
;
5900 context
.messageType
= kIOMessageSystemCapabilityChange
;
5901 applyToInterested( gIOAppPowerStateInterest
,
5902 pmTellCapabilityAppWithResponse
, (void *) &context
);
5903 context
.notifyType
= fOutOfBandParameter
;
5904 context
.messageType
= messageType
;
5906 if(context
.messageType
== kIOMessageCanSystemSleep
)
5908 maxTimeOut
= kCanSleepMaxTimeReq
;
5909 if(gCanSleepTimeout
)
5911 maxTimeOut
= (gCanSleepTimeout
*us_per_s
);
5914 context
.maxTimeRequested
= maxTimeOut
;
5915 applyToInterested( gIOGeneralInterest
,
5916 pmTellClientWithResponse
, (void *) &context
);
5918 fNotifyClientArray
= context
.notifyClients
;
5921 case kNotifyPriority
:
5922 context
.enableTracing
= isRootDomain
;
5923 applyToInterested( gIOPriorityPowerStateInterest
,
5924 pmTellClientWithResponse
, (void *) &context
);
5928 // Notify capability clients for tellChangeDown2().
5929 context
.notifyType
= kNotifyCapabilityChangePriority
;
5930 context
.messageType
= kIOMessageSystemCapabilityChange
;
5931 applyToInterested( gIOPriorityPowerStateInterest
,
5932 pmTellCapabilityClientWithResponse
, (void *) &context
);
5936 case kNotifyCapabilityChangeApps
:
5937 applyToInterested( gIOAppPowerStateInterest
,
5938 pmTellCapabilityAppWithResponse
, (void *) &context
);
5939 fNotifyClientArray
= context
.notifyClients
;
5940 if(context
.messageType
== kIOMessageCanSystemSleep
)
5942 maxTimeOut
= kCanSleepMaxTimeReq
;
5943 if(gCanSleepTimeout
)
5945 maxTimeOut
= (gCanSleepTimeout
*us_per_s
);
5948 context
.maxTimeRequested
= maxTimeOut
;
5951 case kNotifyCapabilityChangePriority
:
5952 context
.enableTracing
= isRootDomain
;
5953 applyToInterested( gIOPriorityPowerStateInterest
,
5954 pmTellCapabilityClientWithResponse
, (void *) &context
);
5958 // do we have to wait for somebody?
5959 if ( !checkForDone() )
5961 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5962 if (context
.enableTracing
) {
5963 getPMRootDomain()->traceDetail(context
.messageType
, 0, context
.maxTimeRequested
/ 1000);
5965 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5970 // everybody responded
5973 fResponseArray
->release();
5974 fResponseArray
= NULL
;
5976 if (fNotifyClientArray
)
5978 fNotifyClientArray
->release();
5979 fNotifyClientArray
= NULL
;
5985 //*********************************************************************************
5986 // [static private] pmTellAppWithResponse
5988 // We send a message to an application, and we expect a response, so we compute a
5989 // cookie we can identify the response with.
5990 //*********************************************************************************
5992 void IOService::pmTellAppWithResponse( OSObject
* object
, void * arg
)
5994 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5995 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5996 uint32_t msgIndex
, msgRef
, msgType
;
5997 OSNumber
*clientID
= NULL
;
5999 boolean_t proc_suspended
= FALSE
;
6000 OSObject
* waitForReply
= kOSBooleanTrue
;
6001 #if LOG_APP_RESPONSE_TIMES
6005 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
6008 if (context
->us
== getPMRootDomain())
6010 if ((clientID
= copyClientIDForNotification(object
, context
)))
6012 uint32_t clientPID
= clientID
->unsigned32BitValue();
6013 clientID
->release();
6014 proc
= proc_find(clientPID
);
6018 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6023 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
6030 if (context
->messageFilter
&&
6031 !context
->messageFilter(context
->us
, object
, context
, 0, &waitForReply
))
6033 if (kIOLogDebugPower
& gIOKitDebug
)
6035 logClientIDForNotification(object
, context
, "DROP App");
6040 // Create client array (for tracking purposes) only if the service
6041 // has app clients. Usually only root domain does.
6042 if (0 == context
->notifyClients
)
6043 context
->notifyClients
= OSArray::withCapacity( 32 );
6045 msgType
= context
->messageType
;
6046 msgIndex
= context
->responseArray
->getCount();
6047 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6049 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6050 if (kIOLogDebugPower
& gIOKitDebug
)
6052 logClientIDForNotification(object
, context
, "MESG App");
6055 if (waitForReply
== kOSBooleanTrue
)
6059 clock_get_uptime(&now
);
6060 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6063 context
->responseArray
->setObject(msgIndex
, num
);
6067 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6072 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6073 if (kIOLogDebugPower
& gIOKitDebug
)
6075 logClientIDForNotification(object
, context
, "App response ignored");
6079 if (context
->notifyClients
)
6080 context
->notifyClients
->setObject(msgIndex
, object
);
6082 context
->us
->messageClient(msgType
, object
, (void *)(uintptr_t) msgRef
);
6085 //*********************************************************************************
6086 // [static private] pmTellClientWithResponse
6088 // We send a message to an in-kernel client, and we expect a response,
6089 // so we compute a cookie we can identify the response with.
6090 //*********************************************************************************
6092 void IOService::pmTellClientWithResponse( OSObject
* object
, void * arg
)
6094 IOPowerStateChangeNotification notify
;
6095 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6096 OSObject
* replied
= kOSBooleanTrue
;
6097 _IOServiceInterestNotifier
* notifier
;
6098 uint32_t msgIndex
, msgRef
, msgType
;
6101 if (context
->messageFilter
&&
6102 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6104 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6105 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6107 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6108 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6109 context
->us
->getName(),
6110 getIOMessageString(context
->messageType
),
6111 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6116 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6117 msgType
= context
->messageType
;
6118 msgIndex
= context
->responseArray
->getCount();
6119 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6121 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6122 if (gIOKitDebug
& kIOLogPower
) {
6123 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6124 if (OSDynamicCast(IOService
, object
)) {
6125 const char *who
= ((IOService
*) object
)->getName();
6126 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6128 else if (notifier
) {
6129 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6132 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6134 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6135 context
->us
->getName(),
6136 getIOMessageString(msgType
),
6137 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6140 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
6141 notify
.returnValue
= 0;
6142 notify
.stateNumber
= context
->stateNumber
;
6143 notify
.stateFlags
= context
->stateFlags
;
6145 if (context
->enableTracing
&& (notifier
!= 0))
6147 getPMRootDomain()->traceDetail(msgType
, msgIndex
, (uintptr_t) notifier
->handler
);
6150 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
6152 if (kIOReturnSuccess
== retCode
)
6154 if (0 == notify
.returnValue
) {
6155 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6157 replied
= kOSBooleanFalse
;
6158 if ( notify
.returnValue
> context
->maxTimeRequested
)
6160 if (notify
.returnValue
> kPriorityClientMaxWait
)
6162 context
->maxTimeRequested
= kPriorityClientMaxWait
;
6163 PM_ERROR("%s: client %p returned %llu for %s\n",
6164 context
->us
->getName(),
6165 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6166 (uint64_t) notify
.returnValue
,
6167 getIOMessageString(msgType
));
6170 context
->maxTimeRequested
= notify
.returnValue
;
6174 // not a client of ours
6175 // so we won't be waiting for response
6176 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6179 context
->responseArray
->setObject(msgIndex
, replied
);
6182 //*********************************************************************************
6183 // [static private] pmTellCapabilityAppWithResponse
6184 //*********************************************************************************
6186 void IOService::pmTellCapabilityAppWithResponse( OSObject
* object
, void * arg
)
6188 IOPMSystemCapabilityChangeParameters msgArg
;
6189 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6190 OSObject
* replied
= kOSBooleanTrue
;
6191 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6192 uint32_t msgIndex
, msgRef
, msgType
;
6193 #if LOG_APP_RESPONSE_TIMES
6197 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
6200 memset(&msgArg
, 0, sizeof(msgArg
));
6201 if (context
->messageFilter
&&
6202 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
))
6207 // Create client array (for tracking purposes) only if the service
6208 // has app clients. Usually only root domain does.
6209 if (0 == context
->notifyClients
)
6210 context
->notifyClients
= OSArray::withCapacity( 32 );
6212 msgType
= context
->messageType
;
6213 msgIndex
= context
->responseArray
->getCount();
6214 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6216 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
6217 if (kIOLogDebugPower
& gIOKitDebug
)
6219 // Log client pid/name and client array index.
6220 OSNumber
* clientID
= NULL
;
6221 OSString
* clientIDString
= NULL
;;
6222 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6224 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6227 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
6228 context
->us
->getName(),
6229 msgIndex
, getIOMessageString(msgType
),
6230 (replied
!= kOSBooleanTrue
),
6231 clientIDString
? clientIDString
->getCStringNoCopy() : "");
6232 if (clientID
) clientID
->release();
6233 if (clientIDString
) clientIDString
->release();
6236 msgArg
.notifyRef
= msgRef
;
6237 msgArg
.maxWaitForReply
= 0;
6239 if (replied
== kOSBooleanTrue
)
6241 msgArg
.notifyRef
= 0;
6242 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
6243 if (context
->notifyClients
)
6244 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
6250 clock_get_uptime(&now
);
6251 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
6254 context
->responseArray
->setObject(msgIndex
, num
);
6258 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
6261 if (context
->notifyClients
)
6262 context
->notifyClients
->setObject(msgIndex
, object
);
6265 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6268 //*********************************************************************************
6269 // [static private] pmTellCapabilityClientWithResponse
6270 //*********************************************************************************
6272 void IOService::pmTellCapabilityClientWithResponse(
6273 OSObject
* object
, void * arg
)
6275 IOPMSystemCapabilityChangeParameters msgArg
;
6276 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6277 OSObject
* replied
= kOSBooleanTrue
;
6278 _IOServiceInterestNotifier
* notifier
;
6279 uint32_t msgIndex
, msgRef
, msgType
;
6282 memset(&msgArg
, 0, sizeof(msgArg
));
6283 if (context
->messageFilter
&&
6284 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, 0))
6286 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6287 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6289 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6290 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6291 context
->us
->getName(),
6292 getIOMessageString(context
->messageType
),
6293 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6298 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6299 msgType
= context
->messageType
;
6300 msgIndex
= context
->responseArray
->getCount();
6301 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6303 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6304 if (gIOKitDebug
& kIOLogPower
) {
6305 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6306 if (OSDynamicCast(IOService
, object
)) {
6307 const char *who
= ((IOService
*) object
)->getName();
6308 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6310 else if (notifier
) {
6311 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6314 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6316 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6317 context
->us
->getName(),
6318 getIOMessageString(msgType
),
6319 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6322 msgArg
.notifyRef
= msgRef
;
6323 msgArg
.maxWaitForReply
= 0;
6325 if (context
->enableTracing
&& (notifier
!= 0))
6327 getPMRootDomain()->traceDetail(msgType
, msgIndex
, (uintptr_t) notifier
->handler
);
6330 retCode
= context
->us
->messageClient(
6331 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6333 if ( kIOReturnSuccess
== retCode
)
6335 if ( 0 == msgArg
.maxWaitForReply
)
6337 // client doesn't want time to respond
6338 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6342 replied
= kOSBooleanFalse
;
6343 if ( msgArg
.maxWaitForReply
> context
->maxTimeRequested
)
6345 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
)
6347 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
6348 PM_ERROR("%s: client %p returned %u for %s\n",
6349 context
->us
->getName(),
6350 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6351 msgArg
.maxWaitForReply
,
6352 getIOMessageString(msgType
));
6355 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6361 // not a client of ours
6362 // so we won't be waiting for response
6363 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6366 context
->responseArray
->setObject(msgIndex
, replied
);
6369 //*********************************************************************************
6370 // [public] tellNoChangeDown
6372 // Notify registered applications and kernel clients that we are not
6375 // Subclass can override this to send a different message type. Parameter is
6376 // the aborted destination state number.
6377 //*********************************************************************************
6379 void IOService::tellNoChangeDown( unsigned long )
6381 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6384 //*********************************************************************************
6385 // [public] tellChangeUp
6387 // Notify registered applications and kernel clients that we are raising power.
6389 // Subclass can override this to send a different message type. Parameter is
6390 // the aborted destination state number.
6391 //*********************************************************************************
6393 void IOService::tellChangeUp( unsigned long )
6395 return tellClients( kIOMessageDeviceHasPoweredOn
);
6398 //*********************************************************************************
6399 // [protected] tellClients
6401 // Notify registered applications and kernel clients of something.
6402 //*********************************************************************************
6404 void IOService::tellClients( int messageType
)
6406 IOPMInterestContext context
;
6408 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6410 memset(&context
, 0, sizeof(context
));
6411 context
.messageType
= messageType
;
6412 context
.isPreChange
= fIsPreChange
;
6414 context
.stateNumber
= fHeadNotePowerState
;
6415 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6416 context
.changeFlags
= fHeadNoteChangeFlags
;
6417 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6418 OSMemberFunctionCast(
6421 &IOPMrootDomain::systemMessageFilter
) : 0;
6423 context
.notifyType
= kNotifyPriority
;
6424 applyToInterested( gIOPriorityPowerStateInterest
,
6425 tellKernelClientApplier
, (void *) &context
);
6427 context
.notifyType
= kNotifyApps
;
6428 applyToInterested( gIOAppPowerStateInterest
,
6429 tellAppClientApplier
, (void *) &context
);
6431 applyToInterested( gIOGeneralInterest
,
6432 tellKernelClientApplier
, (void *) &context
);
6435 //*********************************************************************************
6436 // [private] tellKernelClientApplier
6438 // Message a kernel client.
6439 //*********************************************************************************
6441 static void tellKernelClientApplier( OSObject
* object
, void * arg
)
6443 IOPowerStateChangeNotification notify
;
6444 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6446 if (context
->messageFilter
&&
6447 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6449 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6450 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6452 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6453 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6454 context
->us
->getName(),
6455 IOService::getIOMessageString(context
->messageType
),
6456 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6461 notify
.powerRef
= (void *) 0;
6462 notify
.returnValue
= 0;
6463 notify
.stateNumber
= context
->stateNumber
;
6464 notify
.stateFlags
= context
->stateFlags
;
6466 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6468 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6469 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6471 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6472 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6473 context
->us
->getName(),
6474 IOService::getIOMessageString(context
->messageType
),
6475 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6479 static OSNumber
* copyClientIDForNotification(
6481 IOPMInterestContext
*context
)
6483 OSNumber
*clientID
= NULL
;
6484 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6488 static void logClientIDForNotification(
6490 IOPMInterestContext
*context
,
6491 const char *logString
)
6493 OSString
*logClientID
= NULL
;
6494 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6499 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6501 PM_LOG("%s %s %s, %s\n",
6502 context
->us
->getName(), logString
,
6503 IOService::getIOMessageString(context
->messageType
),
6504 logClientID
? logClientID
->getCStringNoCopy() : "");
6507 logClientID
->release();
6511 clientID
->release();
6516 static void tellAppClientApplier( OSObject
* object
, void * arg
)
6518 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6519 OSNumber
* clientID
= NULL
;
6521 boolean_t proc_suspended
= FALSE
;
6523 if (context
->us
== IOService::getPMRootDomain())
6525 if ((clientID
= copyClientIDForNotification(object
, context
)))
6527 uint32_t clientPID
= clientID
->unsigned32BitValue();
6528 clientID
->release();
6529 proc
= proc_find(clientPID
);
6533 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6538 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6545 if (context
->messageFilter
&&
6546 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6548 if (kIOLogDebugPower
& gIOKitDebug
)
6550 logClientIDForNotification(object
, context
, "DROP App");
6555 if (kIOLogDebugPower
& gIOKitDebug
)
6557 logClientIDForNotification(object
, context
, "MESG App");
6560 context
->us
->messageClient(context
->messageType
, object
, 0);
6563 //*********************************************************************************
6564 // [private] checkForDone
6565 //*********************************************************************************
6567 bool IOService::checkForDone( void )
6572 if (fResponseArray
== NULL
) {
6576 for (i
= 0; ; i
++) {
6577 theFlag
= fResponseArray
->getObject(i
);
6579 if (NULL
== theFlag
) {
6583 if (kOSBooleanTrue
!= theFlag
) {
6590 //*********************************************************************************
6591 // [public] responseValid
6592 //*********************************************************************************
6594 bool IOService::responseValid( uint32_t refcon
, int pid
)
6596 UInt16 serialComponent
;
6597 UInt16 ordinalComponent
;
6599 OSObject
*object
= 0;
6601 serialComponent
= (refcon
>> 16) & 0xFFFF;
6602 ordinalComponent
= (refcon
& 0xFFFF);
6604 if ( serialComponent
!= fSerialNumber
)
6609 if ( fResponseArray
== NULL
)
6614 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6621 if (fNotifyClientArray
)
6622 object
= fNotifyClientArray
->getObject(ordinalComponent
);
6625 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
6634 proc_name(pid
, name
, sizeof(name
));
6635 clock_get_uptime(&now
);
6636 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6637 SUB_ABSOLUTETIME(&now
, &start
);
6638 absolutetime_to_nanoseconds(now
, &nsec
);
6640 if (kIOLogDebugPower
& gIOKitDebug
)
6642 PM_LOG("Ack(%u) %u ms\n",
6643 (uint32_t) ordinalComponent
,
6648 if (nsec
> LOG_APP_RESPONSE_TIMES
)
6650 IOLog("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec
),
6654 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
6656 // TODO: populate the messageType argument
6657 getPMRootDomain()->pmStatsRecordApplicationResponse(
6658 gIOPMStatsApplicationResponseSlow
,
6659 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6663 getPMRootDomain()->pmStatsRecordApplicationResponse(
6664 gIOPMStatsApplicationResponsePrompt
,
6665 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6669 theFlag
= kOSBooleanFalse
;
6672 getPMRootDomain()->pmStatsRecordApplicationResponse(
6673 gIOPMStatsApplicationResponsePrompt
,
6674 0, 0, 0, pid
, object
);
6678 if ( kOSBooleanFalse
== theFlag
)
6680 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6686 //*********************************************************************************
6687 // [public] allowPowerChange
6689 // Our power state is about to lower, and we have notified applications
6690 // and kernel clients, and one of them has acknowledged. If this is the last to do
6691 // so, and all acknowledgements are positive, we continue with the power change.
6692 //*********************************************************************************
6694 IOReturn
IOService::allowPowerChange( unsigned long refcon
)
6696 IOPMRequest
* request
;
6701 return kIOReturnSuccess
;
6704 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6706 return kIOReturnNoMemory
;
6708 request
->fArg0
= (void *) refcon
;
6709 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6710 request
->fArg2
= (void *) 0;
6711 submitPMRequest( request
);
6713 return kIOReturnSuccess
;
6717 IOReturn
IOService::serializedAllowPowerChange2( unsigned long refcon
)
6719 // [deprecated] public
6720 return kIOReturnUnsupported
;
6722 #endif /* !__LP64__ */
6724 //*********************************************************************************
6725 // [public] cancelPowerChange
6727 // Our power state is about to lower, and we have notified applications
6728 // and kernel clients, and one of them has vetoed the change. If this is the last
6729 // client to respond, we abandon the power change.
6730 //*********************************************************************************
6732 IOReturn
IOService::cancelPowerChange( unsigned long refcon
)
6734 IOPMRequest
* request
;
6736 pid_t pid
= proc_selfpid();
6741 return kIOReturnSuccess
;
6745 proc_name(pid
, name
, sizeof(name
));
6746 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid
, name
);
6748 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6751 return kIOReturnNoMemory
;
6754 request
->fArg0
= (void *) refcon
;
6755 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6756 request
->fArg2
= (void *) OSString::withCString(name
);
6757 submitPMRequest( request
);
6759 return kIOReturnSuccess
;
6763 IOReturn
IOService::serializedCancelPowerChange2( unsigned long refcon
)
6765 // [deprecated] public
6766 return kIOReturnUnsupported
;
6769 //*********************************************************************************
6770 // PM_Clamp_Timer_Expired
6772 // called when clamp timer expires...set power state to 0.
6773 //*********************************************************************************
6775 void IOService::PM_Clamp_Timer_Expired( void )
6779 //*********************************************************************************
6782 // Set to highest available power state for a minimum of duration milliseconds
6783 //*********************************************************************************
6785 void IOService::clampPowerOn( unsigned long duration
)
6788 #endif /* !__LP64__ */
6790 //*********************************************************************************
6791 // configurePowerStateReport
6793 // Configures the IOStateReport for kPMPowerStateChannel
6794 //*********************************************************************************
6795 IOReturn
IOService::configurePowerStatesReport( IOReportConfigureAction action
, void *result
)
6798 IOReturn rc
= kIOReturnSuccess
;
6804 return kIOReturnUnsupported
;
6806 if (!fNumberOfPowerStates
)
6807 return kIOReturnSuccess
; // For drivers which are in power plane, but haven't called registerPowerDriver()
6812 case kIOReportEnable
:
6818 reportSize
= STATEREPORT_BUFSIZE(fNumberOfPowerStates
);
6819 fReportBuf
= IOMalloc(reportSize
);
6821 rc
= kIOReturnNoMemory
;
6824 memset(fReportBuf
, 0, reportSize
);
6826 STATEREPORT_INIT(fNumberOfPowerStates
, fReportBuf
, reportSize
,
6827 getRegistryEntryID(), kPMPowerStatesChID
, kIOReportCategoryPower
);
6829 for (i
= 0; i
< fNumberOfPowerStates
; i
++) {
6832 if (fPowerStates
[i
].capabilityFlags
& kIOPMPowerOn
)
6833 bits
|= kPMReportPowerOn
;
6834 if (fPowerStates
[i
].capabilityFlags
& kIOPMDeviceUsable
)
6835 bits
|= kPMReportDeviceUsable
;
6836 if (fPowerStates
[i
].capabilityFlags
& kIOPMLowPower
)
6837 bits
|= kPMReportLowPower
;
6839 STATEREPORT_SETSTATEID(fReportBuf
, i
, ((bits
& 0xff) << 8) |
6840 ((StateOrder(fMaxPowerState
) & 0xf) << 4) | (StateOrder(i
) & 0xf));
6842 ts
= mach_absolute_time();
6843 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
6846 case kIOReportDisable
:
6847 if (fReportClientCnt
== 0) {
6848 rc
= kIOReturnBadArgument
;
6851 if (fReportClientCnt
== 1)
6853 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
6859 case kIOReportGetDimensions
:
6861 STATEREPORT_UPDATERES(fReportBuf
, kIOReportGetDimensions
, result
);
6870 //*********************************************************************************
6871 // updatePowerStateReport
6873 // Updates the IOStateReport for kPMPowerStateChannel
6874 //*********************************************************************************
6875 IOReturn
IOService::updatePowerStatesReport( IOReportConfigureAction action
, void *result
, void *destination
)
6880 IOReturn rc
= kIOReturnSuccess
;
6881 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6885 return kIOReturnUnsupported
;
6886 if (!fNumberOfPowerStates
)
6887 return kIOReturnSuccess
;
6889 if ( !result
|| !dest
) return kIOReturnBadArgument
;
6893 case kIOReportCopyChannelData
:
6894 if ( !fReportBuf
) {
6895 rc
= kIOReturnNotOpen
;
6899 ts
= mach_absolute_time();
6900 STATEREPORT_UPDATEPREP(fReportBuf
, ts
, data2cpy
, size2cpy
);
6901 if (size2cpy
> (dest
->getCapacity() - dest
->getLength()) ) {
6902 rc
= kIOReturnOverrun
;
6906 STATEREPORT_UPDATERES(fReportBuf
, kIOReportCopyChannelData
, result
);
6907 dest
->appendBytes(data2cpy
, size2cpy
);
6921 //*********************************************************************************
6922 // configureSimplePowerReport
6924 // Configures the IOSimpleReport for given channel id
6925 //*********************************************************************************
6926 IOReturn
IOService::configureSimplePowerReport(IOReportConfigureAction action
, void *result
)
6929 IOReturn rc
= kIOReturnSuccess
;
6932 return kIOReturnUnsupported
;
6934 if ( !fNumberOfPowerStates
)
6939 case kIOReportEnable
:
6940 case kIOReportDisable
:
6943 case kIOReportGetDimensions
:
6944 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
6952 //*********************************************************************************
6953 // updateSimplePowerReport
6955 // Updates the IOSimpleReport for the given chanel id
6956 //*********************************************************************************
6957 IOReturn
IOService::updateSimplePowerReport( IOReportConfigureAction action
, void *result
, void *destination
)
6961 uint64_t buf
[SIMPLEREPORT_BUFSIZE
/sizeof(uint64_t)+1]; // Force a 8-byte alignment
6962 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6963 IOReturn rc
= kIOReturnSuccess
;
6968 return kIOReturnUnsupported
;
6969 if ( !result
|| !dest
) return kIOReturnBadArgument
;
6971 if ( !fNumberOfPowerStates
)
6976 case kIOReportCopyChannelData
:
6978 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), kPMCurrStateChID
, kIOReportCategoryPower
);
6980 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMPowerOn
)
6981 bits
|= kPMReportPowerOn
;
6982 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMDeviceUsable
)
6983 bits
|= kPMReportDeviceUsable
;
6984 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMLowPower
)
6985 bits
|= kPMReportLowPower
;
6988 SIMPLEREPORT_SETVALUE(buf
, ((bits
& 0xff) << 8) | ((StateOrder(fMaxPowerState
) & 0xf) << 4) |
6989 (StateOrder(fCurrentPowerState
) & 0xf));
6991 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
6992 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
6993 rc
= kIOReturnOverrun
;
6997 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
6998 dest
->appendBytes(data2cpy
, size2cpy
);
7008 return kIOReturnSuccess
;
7015 // MARK: Driver Overrides
7017 //*********************************************************************************
7018 // [public] setPowerState
7020 // Does nothing here. This should be implemented in a subclass driver.
7021 //*********************************************************************************
7023 IOReturn
IOService::setPowerState(
7024 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
7029 //*********************************************************************************
7030 // [public] maxCapabilityForDomainState
7032 // Finds the highest power state in the array whose input power requirement
7033 // is equal to the input parameter. Where a more intelligent decision is
7034 // possible, override this in the subclassed driver.
7035 //*********************************************************************************
7037 IOPMPowerStateIndex
IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags
)
7039 IOPMPowerStateIndex stateIndex
;
7041 if (!fNumberOfPowerStates
)
7042 return kPowerStateZero
;
7044 for ( int order
= fNumberOfPowerStates
- 1; order
>= 0; order
-- )
7046 stateIndex
= fPowerStates
[order
].stateOrderToIndex
;
7048 if ( (flags
& fPowerStates
[stateIndex
].inputPowerFlags
) ==
7049 fPowerStates
[stateIndex
].inputPowerFlags
)
7054 return kPowerStateZero
;
7057 unsigned long IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState
)
7059 return getPowerStateForDomainFlags(domainState
);
7062 //*********************************************************************************
7063 // [public] initialPowerStateForDomainState
7065 // Called to query the power state for the initial power transition.
7066 //*********************************************************************************
7068 unsigned long IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState
)
7070 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
))
7072 // Return lowest power state for any root power domain changes
7073 return kPowerStateZero
;
7076 return getPowerStateForDomainFlags(domainState
);
7079 //*********************************************************************************
7080 // [public] powerStateForDomainState
7082 // This method is not called from PM.
7083 //*********************************************************************************
7085 unsigned long IOService::powerStateForDomainState( IOPMPowerFlags domainState
)
7087 return getPowerStateForDomainFlags(domainState
);
7091 //*********************************************************************************
7092 // [deprecated] didYouWakeSystem
7094 // Does nothing here. This should be implemented in a subclass driver.
7095 //*********************************************************************************
7097 bool IOService::didYouWakeSystem( void )
7101 #endif /* !__LP64__ */
7103 //*********************************************************************************
7104 // [public] powerStateWillChangeTo
7106 // Does nothing here. This should be implemented in a subclass driver.
7107 //*********************************************************************************
7109 IOReturn
IOService::powerStateWillChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7111 return kIOPMAckImplied
;
7114 //*********************************************************************************
7115 // [public] powerStateDidChangeTo
7117 // Does nothing here. This should be implemented in a subclass driver.
7118 //*********************************************************************************
7120 IOReturn
IOService::powerStateDidChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
7122 return kIOPMAckImplied
;
7125 //*********************************************************************************
7126 // [protected] powerChangeDone
7128 // Called from PM work loop thread.
7129 // Does nothing here. This should be implemented in a subclass policy-maker.
7130 //*********************************************************************************
7132 void IOService::powerChangeDone( unsigned long )
7137 //*********************************************************************************
7138 // [deprecated] newTemperature
7140 // Does nothing here. This should be implemented in a subclass driver.
7141 //*********************************************************************************
7143 IOReturn
IOService::newTemperature( long currentTemp
, IOService
* whichZone
)
7147 #endif /* !__LP64__ */
7149 //*********************************************************************************
7150 // [public] systemWillShutdown
7152 // System shutdown and restart notification.
7153 //*********************************************************************************
7155 void IOService::systemWillShutdown( IOOptionBits specifier
)
7157 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
7159 rootDomain
->acknowledgeSystemWillShutdown( this );
7163 // MARK: PM State Machine
7165 //*********************************************************************************
7166 // [private static] acquirePMRequest
7167 //*********************************************************************************
7170 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
7171 IOPMRequest
* active
)
7173 IOPMRequest
* request
;
7177 request
= IOPMRequest::create();
7180 request
->init( target
, requestType
);
7183 IOPMRequest
* root
= active
->getRootRequest();
7184 if (root
) request
->attachRootRequest(root
);
7189 PM_ERROR("%s: No memory for PM request type 0x%x\n",
7190 target
->getName(), (uint32_t) requestType
);
7195 //*********************************************************************************
7196 // [private static] releasePMRequest
7197 //*********************************************************************************
7199 void IOService::releasePMRequest( IOPMRequest
* request
)
7208 //*********************************************************************************
7209 // [private static] submitPMRequest
7210 //*********************************************************************************
7212 void IOService::submitPMRequest( IOPMRequest
* request
)
7215 assert( gIOPMReplyQueue
);
7216 assert( gIOPMRequestQueue
);
7218 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7219 (long)request
->getType(), OBFUSCATE(request
),
7220 OBFUSCATE(request
->getTarget()), request
->getTarget()->getName(),
7221 OBFUSCATE(request
->fArg0
),
7222 OBFUSCATE(request
->fArg1
), OBFUSCATE(request
->fArg2
));
7224 if (request
->isReplyType())
7225 gIOPMReplyQueue
->queuePMRequest( request
);
7227 gIOPMRequestQueue
->queuePMRequest( request
);
7230 void IOService::submitPMRequests( IOPMRequest
** requests
, IOItemCount count
)
7233 assert( count
> 0 );
7234 assert( gIOPMRequestQueue
);
7236 for (IOItemCount i
= 0; i
< count
; i
++)
7238 IOPMRequest
* req
= requests
[i
];
7239 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
7240 (long)req
->getType(), OBFUSCATE(req
),
7241 OBFUSCATE(req
->getTarget()), req
->getTarget()->getName(),
7242 OBFUSCATE(req
->fArg0
),
7243 OBFUSCATE(req
->fArg1
), OBFUSCATE(req
->fArg2
));
7246 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
7249 //*********************************************************************************
7250 // [private] actionPMRequestQueue
7252 // IOPMRequestQueue::checkForWork() passing a new request to the request target.
7253 //*********************************************************************************
7255 bool IOService::actionPMRequestQueue(
7256 IOPMRequest
* request
,
7257 IOPMRequestQueue
* queue
)
7263 // Work queue will immediately execute the request if the per-service
7264 // request queue is empty. Note pwrMgt is the target's IOServicePM.
7266 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
7270 // Calling PM without PMinit() is not allowed, fail the request.
7271 // Need to signal more when completing attached requests.
7273 PM_LOG("%s: PM not initialized\n", getName());
7274 PM_LOG1("[- %02x] %p [%p %s] !initialized\n",
7275 request
->getType(), OBFUSCATE(request
),
7276 OBFUSCATE(this), getName());
7278 more
= gIOPMCompletionQueue
->queuePMRequest(request
);
7279 if (more
) gIOPMWorkQueue
->incrementProducerCount();
7285 //*********************************************************************************
7286 // [private] actionPMCompletionQueue
7288 // IOPMCompletionQueue::checkForWork() passing a completed request to the
7290 //*********************************************************************************
7292 bool IOService::actionPMCompletionQueue(
7293 IOPMRequest
* request
,
7294 IOPMCompletionQueue
* queue
)
7296 bool more
= (request
->getNextRequest() != 0);
7297 IOPMRequest
* root
= request
->getRootRequest();
7299 if (root
&& (root
!= request
))
7302 gIOPMWorkQueue
->incrementProducerCount();
7304 releasePMRequest( request
);
7308 //*********************************************************************************
7309 // [private] actionPMWorkQueueRetire
7311 // IOPMWorkQueue::checkForWork() passing a retired request to the request target.
7312 //*********************************************************************************
7314 bool IOService::actionPMWorkQueueRetire( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7316 assert(request
&& queue
);
7318 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7319 request
->getType(), OBFUSCATE(request
),
7320 OBFUSCATE(this), getName(),
7321 fMachineState
, gIOPMBusyRequestCount
);
7323 // Catch requests created by idleTimerExpired()
7324 if (request
->getType() == kIOPMRequestTypeActivityTickle
)
7326 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
7328 if ((tickleFlags
& kTickleTypePowerDrop
) && fIdleTimerPeriod
)
7332 else if (tickleFlags
== (kTickleTypeActivity
| kTickleTypePowerRise
))
7334 // Invalidate any idle power drop that got queued while
7335 // processing this request.
7336 fIdleTimerGeneration
++;
7340 // When the completed request is linked, tell work queue there is
7341 // more work pending.
7343 return (gIOPMCompletionQueue
->queuePMRequest( request
));
7346 //*********************************************************************************
7347 // [private] isPMBlocked
7349 // Check if machine state transition is blocked.
7350 //*********************************************************************************
7352 bool IOService::isPMBlocked( IOPMRequest
* request
, int count
)
7357 if (kIOPM_Finished
== fMachineState
)
7360 if (kIOPM_DriverThreadCallDone
== fMachineState
)
7362 // 5 = kDriverCallInformPreChange
7363 // 6 = kDriverCallInformPostChange
7364 // 7 = kDriverCallSetPowerState
7365 // 8 = kRootDomainInformPreChange
7366 if (fDriverCallBusy
)
7367 reason
= 5 + fDriverCallReason
;
7371 // Waiting on driver's setPowerState() timeout.
7377 // Child or interested driver acks pending.
7378 if (fHeadNotePendingAcks
)
7383 // Waiting on apps or priority power interest clients.
7389 // Waiting on settle timer expiration.
7396 fWaitReason
= reason
;
7402 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7403 request
->getType(), OBFUSCATE(request
),
7404 OBFUSCATE(this), getName(),
7405 fMachineState
, reason
);
7414 //*********************************************************************************
7415 // [private] actionPMWorkQueueInvoke
7417 // IOPMWorkQueue::checkForWork() passing a request to the
7418 // request target for execution.
7419 //*********************************************************************************
7421 bool IOService::actionPMWorkQueueInvoke( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7426 assert(request
&& queue
);
7428 while (isPMBlocked(request
, loop
++) == false)
7430 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7431 request
->getType(), OBFUSCATE(request
),
7432 OBFUSCATE(this), getName(), fMachineState
);
7434 gIOPMRequest
= request
;
7435 gIOPMWorkInvokeCount
++;
7437 // Every PM machine states must be handled in one of the cases below.
7439 switch ( fMachineState
)
7441 case kIOPM_Finished
:
7442 start_watchdog_timer();
7444 executePMRequest( request
);
7447 case kIOPM_OurChangeTellClientsPowerDown
:
7448 // Root domain might self cancel due to assertions.
7451 bool cancel
= (bool) fDoNotPowerDown
;
7452 getPMRootDomain()->askChangeDownDone(
7453 &fHeadNoteChangeFlags
, &cancel
);
7454 fDoNotPowerDown
= cancel
;
7457 // askChangeDown() done, was it vetoed?
7458 if (!fDoNotPowerDown
)
7460 // no, we can continue
7461 OurChangeTellClientsPowerDown();
7465 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7466 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7467 if (IS_ROOT_DOMAIN
) {
7468 // RootDomain already sent "WillSleep" to its clients
7469 tellChangeUp(fCurrentPowerState
);
7472 tellNoChangeDown(fHeadNotePowerState
);
7474 // mark the change note un-actioned
7475 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7481 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
7482 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7483 if (fDoNotPowerDown
)
7485 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7486 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7487 if (IS_ROOT_DOMAIN
) {
7488 // RootDomain already sent "WillSleep" to its clients
7489 tellChangeUp(fCurrentPowerState
);
7492 tellNoChangeDown(fHeadNotePowerState
);
7494 // mark the change note un-actioned
7495 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7500 OurChangeTellUserPMPolicyPowerDown();
7503 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
7504 // PMRD: LastCallBeforeSleep notify done
7505 // Non-PMRD: tellChangeDown/kNotifyApps done
7506 if (fDoNotPowerDown
)
7508 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7509 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7510 // no, tell clients we're back in the old state
7511 tellChangeUp(fCurrentPowerState
);
7512 // mark the change note un-actioned
7513 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7519 // yes, we can continue
7520 OurChangeTellPriorityClientsPowerDown();
7524 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
7525 OurChangeNotifyInterestedDriversWillChange();
7528 case kIOPM_OurChangeSetPowerState
:
7529 OurChangeSetPowerState();
7532 case kIOPM_OurChangeWaitForPowerSettle
:
7533 OurChangeWaitForPowerSettle();
7536 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
7537 OurChangeNotifyInterestedDriversDidChange();
7540 case kIOPM_OurChangeTellCapabilityDidChange
:
7541 OurChangeTellCapabilityDidChange();
7544 case kIOPM_OurChangeFinish
:
7548 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
7549 ParentChangeTellPriorityClientsPowerDown();
7552 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
7553 ParentChangeNotifyInterestedDriversWillChange();
7556 case kIOPM_ParentChangeSetPowerState
:
7557 ParentChangeSetPowerState();
7560 case kIOPM_ParentChangeWaitForPowerSettle
:
7561 ParentChangeWaitForPowerSettle();
7564 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7565 ParentChangeNotifyInterestedDriversDidChange();
7568 case kIOPM_ParentChangeTellCapabilityDidChange
:
7569 ParentChangeTellCapabilityDidChange();
7572 case kIOPM_ParentChangeAcknowledgePowerChange
:
7573 ParentChangeAcknowledgePowerChange();
7576 case kIOPM_DriverThreadCallDone
:
7577 switch (fDriverCallReason
)
7579 case kDriverCallInformPreChange
:
7580 case kDriverCallInformPostChange
:
7581 notifyInterestedDriversDone();
7583 case kDriverCallSetPowerState
:
7584 notifyControllingDriverDone();
7586 case kRootDomainInformPreChange
:
7587 notifyRootDomainDone();
7590 panic("%s: bad call reason %x",
7591 getName(), fDriverCallReason
);
7595 case kIOPM_NotifyChildrenOrdered
:
7596 notifyChildrenOrdered();
7599 case kIOPM_NotifyChildrenDelayed
:
7600 notifyChildrenDelayed();
7603 case kIOPM_NotifyChildrenStart
:
7604 // pop notifyAll() state saved by notifyInterestedDriversDone()
7609 case kIOPM_SyncTellClientsPowerDown
:
7610 // Root domain might self cancel due to assertions.
7613 bool cancel
= (bool) fDoNotPowerDown
;
7614 getPMRootDomain()->askChangeDownDone(
7615 &fHeadNoteChangeFlags
, &cancel
);
7616 fDoNotPowerDown
= cancel
;
7618 if (!fDoNotPowerDown
)
7620 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7621 fOutOfBandParameter
= kNotifyApps
;
7622 tellChangeDown(fHeadNotePowerState
);
7626 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7627 // askChangeDown/kNotifyApps
7628 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7629 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7630 tellNoChangeDown(fHeadNotePowerState
);
7631 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7636 case kIOPM_SyncTellPriorityClientsPowerDown
:
7637 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7638 if (!fDoNotPowerDown
)
7640 fMachineState
= kIOPM_SyncNotifyWillChange
;
7641 fOutOfBandParameter
= kNotifyPriority
;
7642 tellChangeDown(fHeadNotePowerState
);
7646 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7647 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7648 tellChangeUp(fCurrentPowerState
);
7649 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7654 case kIOPM_SyncNotifyWillChange
:
7655 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
)
7657 fMachineState
= kIOPM_SyncFinish
;
7660 fMachineState
= kIOPM_SyncNotifyDidChange
;
7661 fDriverCallReason
= kDriverCallInformPreChange
;
7665 case kIOPM_SyncNotifyDidChange
:
7666 fIsPreChange
= false;
7668 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7670 fMachineState
= kIOPM_SyncFinish
;
7674 assert(IS_ROOT_DOMAIN
);
7675 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7678 fDriverCallReason
= kDriverCallInformPostChange
;
7682 case kIOPM_SyncTellCapabilityDidChange
:
7683 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7686 case kIOPM_SyncFinish
:
7687 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7688 ParentChangeAcknowledgePowerChange();
7693 case kIOPM_TellCapabilityChangeDone
:
7696 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
)
7698 MS_POP(); // tellSystemCapabilityChange()
7701 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7705 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
)
7707 MS_POP(); // tellSystemCapabilityChange()
7710 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7712 tellClientsWithResponse( fOutOfBandMessage
);
7716 panic("PMWorkQueueInvoke: unknown machine state %x",
7722 if (fMachineState
== kIOPM_Finished
)
7724 stop_watchdog_timer();
7733 //*********************************************************************************
7734 // [private] executePMRequest
7735 //*********************************************************************************
7737 void IOService::executePMRequest( IOPMRequest
* request
)
7739 assert( kIOPM_Finished
== fMachineState
);
7741 switch (request
->getType())
7743 case kIOPMRequestTypePMStop
:
7744 handlePMstop( request
);
7747 case kIOPMRequestTypeAddPowerChild1
:
7748 addPowerChild1( request
);
7751 case kIOPMRequestTypeAddPowerChild2
:
7752 addPowerChild2( request
);
7755 case kIOPMRequestTypeAddPowerChild3
:
7756 addPowerChild3( request
);
7759 case kIOPMRequestTypeRegisterPowerDriver
:
7760 handleRegisterPowerDriver( request
);
7763 case kIOPMRequestTypeAdjustPowerState
:
7764 fAdjustPowerScheduled
= false;
7768 case kIOPMRequestTypePowerDomainWillChange
:
7769 handlePowerDomainWillChangeTo( request
);
7772 case kIOPMRequestTypePowerDomainDidChange
:
7773 handlePowerDomainDidChangeTo( request
);
7776 case kIOPMRequestTypeRequestPowerState
:
7777 case kIOPMRequestTypeRequestPowerStateOverride
:
7778 handleRequestPowerState( request
);
7781 case kIOPMRequestTypePowerOverrideOnPriv
:
7782 case kIOPMRequestTypePowerOverrideOffPriv
:
7783 handlePowerOverrideChanged( request
);
7786 case kIOPMRequestTypeActivityTickle
:
7787 handleActivityTickle( request
);
7790 case kIOPMRequestTypeSynchronizePowerTree
:
7791 handleSynchronizePowerTree( request
);
7794 case kIOPMRequestTypeSetIdleTimerPeriod
:
7796 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7797 fNextIdleTimerPeriod
= fIdleTimerPeriod
;
7798 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
7803 case kIOPMRequestTypeIgnoreIdleTimer
:
7804 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7807 case kIOPMRequestTypeQuiescePowerTree
:
7808 gIOPMWorkQueue
->finishQuiesceRequest(request
);
7812 panic("executePMRequest: unknown request type %x", request
->getType());
7816 //*********************************************************************************
7817 // [private] actionPMReplyQueue
7819 // IOPMRequestQueue::checkForWork() passing a reply-type request to the
7821 //*********************************************************************************
7823 bool IOService::actionPMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7827 assert( request
&& queue
);
7828 assert( request
->isReplyType() );
7830 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7831 request
->getType(), OBFUSCATE(request
),
7832 OBFUSCATE(this), getName(), fMachineState
);
7834 switch ( request
->getType() )
7836 case kIOPMRequestTypeAllowPowerChange
:
7837 case kIOPMRequestTypeCancelPowerChange
:
7838 // Check if we are expecting this response.
7839 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7840 (int)(uintptr_t) request
->fArg1
))
7842 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
7844 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7845 // flag is set. Only root domain will set this flag.
7846 // However, there is one exception to this rule. User-space PM
7847 // policy may choose to cancel sleep even after all clients have
7848 // been notified that we will lower power.
7850 if ((fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7851 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7852 || ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0))
7854 fDoNotPowerDown
= true;
7856 OSString
* name
= (OSString
*) request
->fArg2
;
7857 getPMRootDomain()->pmStatsRecordApplicationResponse(
7858 gIOPMStatsApplicationResponseCancel
,
7859 name
? name
->getCStringNoCopy() : "", 0,
7860 0, (int)(uintptr_t) request
->fArg1
, 0);
7867 cleanClientResponses(false);
7871 // OSString containing app name in Arg2 must be released.
7872 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
7874 OSObject
* obj
= (OSObject
*) request
->fArg2
;
7875 if (obj
) obj
->release();
7879 case kIOPMRequestTypeAckPowerChange
:
7880 more
= handleAcknowledgePowerChange( request
);
7883 case kIOPMRequestTypeAckSetPowerState
:
7884 if (fDriverTimer
== -1)
7886 // driver acked while setPowerState() call is in-flight.
7887 // take this ack, return value from setPowerState() is irrelevant.
7888 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
7889 (uintptr_t) this, fDriverTimer
);
7892 else if (fDriverTimer
> 0)
7894 // expected ack, stop the timer
7898 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
7899 if (nsec
> LOG_SETPOWER_TIMES
) {
7900 getPMRootDomain()->pmStatsRecordApplicationResponse(
7901 gIOPMStatsDriverPSChangeSlow
,
7902 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), getRegistryEntryID(),
7903 NULL
, fHeadNotePowerState
);
7906 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
7913 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
7917 case kIOPMRequestTypeInterestChanged
:
7918 handleInterestChanged( request
);
7922 case kIOPMRequestTypeIdleCancel
:
7923 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
7924 || (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7925 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7926 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
7927 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
7929 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7930 PM_LOG2("%s: cancel from machine state %d\n",
7931 getName(), fMachineState
);
7932 fDoNotPowerDown
= true;
7933 // Stop waiting for app replys.
7934 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
7935 (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
) ||
7936 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
) ||
7937 (fMachineState
== kIOPM_SyncTellClientsPowerDown
) )
7938 cleanClientResponses(false);
7943 case kIOPMRequestTypeChildNotifyDelayCancel
:
7944 if (fMachineState
== kIOPM_NotifyChildrenDelayed
)
7946 PM_LOG2("%s: delay notify cancelled\n", getName());
7947 notifyChildrenDelayed();
7952 panic("PMReplyQueue: unknown reply type %x", request
->getType());
7955 more
|= gIOPMCompletionQueue
->queuePMRequest(request
);
7957 gIOPMWorkQueue
->incrementProducerCount();
7962 //*********************************************************************************
7963 // [private] assertPMDriverCall / deassertPMDriverCall
7964 //*********************************************************************************
7966 bool IOService::assertPMDriverCall(
7967 IOPMDriverCallEntry
* entry
,
7968 IOOptionBits options
,
7969 IOPMinformee
* inform
)
7971 IOService
* target
= 0;
7979 if (fLockedFlags
.PMStop
)
7984 if (((options
& kIOPMADC_NoInactiveCheck
) == 0) && isInactive())
7991 if (!inform
->active
)
7995 target
= inform
->whatObject
;
7996 if (target
->isInactive())
8002 entry
->thread
= current_thread();
8003 entry
->target
= target
;
8004 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8013 void IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
8015 bool wakeup
= false;
8019 assert( !queue_empty(&fPMDriverCallQueue
) );
8020 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
8021 if (fLockedFlags
.PMDriverCallWait
)
8029 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
8032 void IOService::waitForPMDriverCall( IOService
* target
)
8034 const IOPMDriverCallEntry
* entry
;
8035 thread_t thread
= current_thread();
8036 AbsoluteTime deadline
;
8043 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
8045 // Target of interested driver call
8046 if (target
&& (target
!= entry
->target
))
8049 if (entry
->thread
== thread
)
8053 PM_LOG("%s: %s(%s) on PM thread\n",
8054 fName
, __FUNCTION__
, target
? target
->getName() : "");
8055 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
8056 fName
, __FUNCTION__
, target
? target
->getName() : "");
8068 fLockedFlags
.PMDriverCallWait
= true;
8069 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
8070 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
8071 fLockedFlags
.PMDriverCallWait
= false;
8072 if (THREAD_TIMED_OUT
== waitResult
)
8074 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
8081 //*********************************************************************************
8082 // [private] Debug helpers
8083 //*********************************************************************************
8085 const char * IOService::getIOMessageString( uint32_t msg
)
8087 #define MSG_ENTRY(x) {(int) x, #x}
8089 static const IONamedValue msgNames
[] = {
8090 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
8091 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
8092 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
8093 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
8094 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
8095 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
8096 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
8097 MSG_ENTRY( kIOMessageCanSystemSleep
),
8098 MSG_ENTRY( kIOMessageSystemWillSleep
),
8099 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
8100 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
8101 MSG_ENTRY( kIOMessageSystemWillRestart
),
8102 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
8103 MSG_ENTRY( kIOMessageSystemCapabilityChange
),
8104 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep
)
8107 return IOFindNameForValue(msg
, msgNames
);
8112 // MARK: IOPMRequest
8114 //*********************************************************************************
8115 // IOPMRequest Class
8117 // Requests from PM clients, and also used for inter-object messaging within PM.
8118 //*********************************************************************************
8120 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
8122 IOPMRequest
* IOPMRequest::create( void )
8124 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
8125 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
8133 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
8135 if (!IOCommand::init())
8138 fRequestType
= type
;
8144 // Root node and root domain requests does not prevent the power tree from
8145 // becoming quiescent.
8147 fIsQuiesceBlocker
= ((fTarget
!= gIOPMRootNode
) &&
8148 (fTarget
!= IOService::getPMRootDomain()));
8153 void IOPMRequest::reset( void )
8155 assert( fWorkWaitCount
== 0 );
8156 assert( fFreeWaitCount
== 0 );
8158 detachNextRequest();
8159 detachRootRequest();
8161 if (fCompletionAction
&& (fRequestType
== kIOPMRequestTypeQuiescePowerTree
))
8163 // Call the completion on PM work loop context
8164 fCompletionAction(fCompletionTarget
, fCompletionParam
);
8165 fCompletionAction
= 0;
8168 fRequestType
= kIOPMRequestTypeInvalid
;
8177 bool IOPMRequest::attachNextRequest( IOPMRequest
* next
)
8183 // Postpone the execution of the next request after
8185 fRequestNext
= next
;
8186 fRequestNext
->fWorkWaitCount
++;
8187 #if LOG_REQUEST_ATTACH
8188 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8189 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8190 fRequestNext
->fRequestType
,
8191 (uint32_t) fRequestNext
->fWorkWaitCount
,
8192 fTarget
->getName());
8199 bool IOPMRequest::detachNextRequest( void )
8205 assert(fRequestNext
->fWorkWaitCount
);
8206 if (fRequestNext
->fWorkWaitCount
)
8207 fRequestNext
->fWorkWaitCount
--;
8208 #if LOG_REQUEST_ATTACH
8209 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
8210 OBFUSCATE(this), fRequestType
, OBFUSCATE(fRequestNext
),
8211 fRequestNext
->fRequestType
,
8212 (uint32_t) fRequestNext
->fWorkWaitCount
,
8213 fTarget
->getName());
8221 bool IOPMRequest::attachRootRequest( IOPMRequest
* root
)
8227 // Delay the completion of the root request after
8229 fRequestRoot
= root
;
8230 fRequestRoot
->fFreeWaitCount
++;
8231 #if LOG_REQUEST_ATTACH
8232 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8233 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8234 (uint32_t) fRequestRoot
->fType
,
8235 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8236 fTarget
->getName());
8243 bool IOPMRequest::detachRootRequest( void )
8249 assert(fRequestRoot
->fFreeWaitCount
);
8250 if (fRequestRoot
->fFreeWaitCount
)
8251 fRequestRoot
->fFreeWaitCount
--;
8252 #if LOG_REQUEST_ATTACH
8253 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
8254 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
8255 (uint32_t) fRequestRoot
->fType
,
8256 (uint32_t) fRequestRoot
->fFreeWaitCount
,
8257 fTarget
->getName());
8266 // MARK: IOPMRequestQueue
8268 //*********************************************************************************
8269 // IOPMRequestQueue Class
8271 // Global queues. Queues are created once and never released.
8272 //*********************************************************************************
8274 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
8276 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
8278 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
8279 if (me
&& !me
->init(inOwner
, inAction
))
8287 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
8289 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8292 queue_init(&fQueue
);
8293 fLock
= IOLockAlloc();
8294 return (fLock
!= 0);
8297 void IOPMRequestQueue::free( void )
8304 return IOEventSource::free();
8307 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
8311 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8312 IOLockUnlock(fLock
);
8313 if (workLoop
) signalWorkAvailable();
8317 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
8321 assert(requests
&& count
);
8327 queue_enter(&fQueue
, next
, typeof(next
), fCommandChain
);
8329 IOLockUnlock(fLock
);
8330 if (workLoop
) signalWorkAvailable();
8333 bool IOPMRequestQueue::checkForWork( void )
8335 Action dqAction
= (Action
) action
;
8336 IOPMRequest
* request
;
8338 int dequeueCount
= 0;
8341 IOLockLock( fLock
);
8343 while (!queue_empty(&fQueue
))
8345 if (dequeueCount
++ >= kMaxDequeueCount
)
8347 // Allow other queues a chance to work
8352 queue_remove_first(&fQueue
, request
, typeof(request
), fCommandChain
);
8353 IOLockUnlock(fLock
);
8354 target
= request
->getTarget();
8356 more
|= (*dqAction
)( target
, request
, this );
8357 IOLockLock( fLock
);
8360 IOLockUnlock( fLock
);
8365 // MARK: IOPMWorkQueue
8367 //*********************************************************************************
8368 // IOPMWorkQueue Class
8370 // Queue of IOServicePM objects, each with a queue of IOPMRequest sharing the
8372 //*********************************************************************************
8374 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
8377 IOPMWorkQueue::create( IOService
* inOwner
, Action invoke
, Action retire
)
8379 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
8380 if (me
&& !me
->init(inOwner
, invoke
, retire
))
8388 bool IOPMWorkQueue::init( IOService
* inOwner
, Action invoke
, Action retire
)
8390 if (!invoke
|| !retire
||
8391 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
8394 queue_init(&fWorkQueue
);
8396 fInvokeAction
= invoke
;
8397 fRetireAction
= retire
;
8398 fConsumerCount
= fProducerCount
= 0;
8403 bool IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
8405 queue_head_t
* requestQueue
;
8411 assert( onThread() );
8412 assert( queue_next(&request
->fCommandChain
) ==
8413 queue_prev(&request
->fCommandChain
) );
8415 gIOPMBusyRequestCount
++;
8417 if (request
->isQuiesceType())
8419 if ((request
->getTarget() == gIOPMRootNode
) && !fQuiesceStartTime
)
8421 // Attach new quiesce request to all quiesce blockers in the queue
8422 fQuiesceStartTime
= mach_absolute_time();
8423 attachQuiesceRequest(request
);
8424 fQuiesceRequest
= request
;
8427 else if (fQuiesceRequest
&& request
->isQuiesceBlocker())
8429 // Attach the new quiesce blocker to the blocked quiesce request
8430 request
->attachNextRequest(fQuiesceRequest
);
8433 // Add new request to the tail of the per-service request queue.
8434 // Then immediately check the request queue to minimize latency
8435 // if the queue was empty.
8437 requestQueue
= &pwrMgt
->RequestHead
;
8438 empty
= queue_empty(requestQueue
);
8439 queue_enter(requestQueue
, request
, typeof(request
), fCommandChain
);
8442 more
= checkRequestQueue(requestQueue
, &empty
);
8445 // Request just added is blocked, add its target IOServicePM
8446 // to the work queue.
8447 assert( queue_next(&pwrMgt
->WorkChain
) ==
8448 queue_prev(&pwrMgt
->WorkChain
) );
8450 queue_enter(&fWorkQueue
, pwrMgt
, typeof(pwrMgt
), WorkChain
);
8452 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8453 fQueueLength
, pwrMgt
->Name
, OBFUSCATE(pwrMgt
));
8460 bool IOPMWorkQueue::checkRequestQueue( queue_head_t
* requestQueue
, bool * empty
)
8462 IOPMRequest
* request
;
8467 assert(!queue_empty(requestQueue
));
8469 request
= (typeof(request
)) queue_first(requestQueue
);
8470 if (request
->isWorkBlocked())
8471 break; // request dispatch blocked on attached request
8473 target
= request
->getTarget();
8476 done
= (*fInvokeAction
)( target
, request
, this );
8480 PM_LOG("PM request 0x%x dropped\n", request
->getType());
8484 break; // PM state machine blocked
8486 assert(gIOPMBusyRequestCount
> 0);
8487 if (gIOPMBusyRequestCount
)
8488 gIOPMBusyRequestCount
--;
8490 if (request
== fQuiesceRequest
)
8492 fQuiesceRequest
= 0;
8495 queue_remove_first(requestQueue
, request
, typeof(request
), fCommandChain
);
8496 more
|= (*fRetireAction
)( target
, request
, this );
8497 done
= queue_empty(requestQueue
);
8504 // Retired a request that may unblock a previously visited request
8505 // that is still waiting on the work queue. Must trigger another
8513 bool IOPMWorkQueue::checkForWork( void )
8515 IOServicePM
* entry
;
8520 #if WORK_QUEUE_STATS
8521 fStatCheckForWork
++;
8524 // Iterate over all IOServicePM entries in the work queue,
8525 // and check each entry's request queue.
8527 while (fConsumerCount
!= fProducerCount
)
8529 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8530 fProducerCount
, fConsumerCount
);
8532 fConsumerCount
= fProducerCount
;
8534 #if WORK_QUEUE_STATS
8535 if (queue_empty(&fWorkQueue
))
8541 uint32_t cachedWorkCount
= gIOPMWorkInvokeCount
;
8544 __IGNORE_WCASTALIGN(entry
= (typeof(entry
)) queue_first(&fWorkQueue
));
8545 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
))
8547 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
8549 // Get next entry, points to head if current entry is last.
8550 __IGNORE_WCASTALIGN(next
= (typeof(next
)) queue_next(&entry
->WorkChain
));
8552 // if request queue is empty, remove IOServicePM from work queue.
8555 assert(fQueueLength
);
8556 if (fQueueLength
) fQueueLength
--;
8557 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8558 fQueueLength
, entry
->Name
, OBFUSCATE(entry
));
8559 queue_remove(&fWorkQueue
, entry
, typeof(entry
), WorkChain
);
8564 #if WORK_QUEUE_STATS
8565 if (cachedWorkCount
== gIOPMWorkInvokeCount
)
8573 void IOPMWorkQueue::signalWorkAvailable( void )
8576 IOEventSource::signalWorkAvailable();
8579 void IOPMWorkQueue::incrementProducerCount( void )
8584 void IOPMWorkQueue::attachQuiesceRequest( IOPMRequest
* quiesceRequest
)
8586 IOServicePM
* entry
;
8587 IOPMRequest
* request
;
8589 if (queue_empty(&fWorkQueue
))
8594 queue_iterate(&fWorkQueue
, entry
, typeof(entry
), WorkChain
)
8596 queue_iterate(&entry
->RequestHead
, request
, typeof(request
), fCommandChain
)
8598 // Attach the quiesce request to any request in the queue that
8599 // is not linked to a next request. These requests will block
8600 // the quiesce request.
8602 if (request
->isQuiesceBlocker())
8604 request
->attachNextRequest(quiesceRequest
);
8610 void IOPMWorkQueue::finishQuiesceRequest( IOPMRequest
* quiesceRequest
)
8612 if (fQuiesceRequest
&& (quiesceRequest
== fQuiesceRequest
) &&
8613 (fQuiesceStartTime
!= 0))
8616 fQuiesceFinishTime
= mach_absolute_time();
8621 // MARK: IOPMCompletionQueue
8623 //*********************************************************************************
8624 // IOPMCompletionQueue Class
8625 //*********************************************************************************
8627 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
8629 IOPMCompletionQueue
*
8630 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
8632 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
8633 if (me
&& !me
->init(inOwner
, inAction
))
8641 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
8643 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8646 queue_init(&fQueue
);
8650 bool IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
8655 // unblock dependent request
8656 more
= request
->detachNextRequest();
8657 queue_enter(&fQueue
, request
, typeof(request
), fCommandChain
);
8661 bool IOPMCompletionQueue::checkForWork( void )
8663 Action dqAction
= (Action
) action
;
8664 IOPMRequest
* request
;
8669 request
= (typeof(request
)) queue_first(&fQueue
);
8670 while (!queue_end(&fQueue
, (queue_entry_t
) request
))
8672 next
= (typeof(next
)) queue_next(&request
->fCommandChain
);
8673 if (!request
->isFreeBlocked())
8675 queue_remove(&fQueue
, request
, typeof(request
), fCommandChain
);
8676 target
= request
->getTarget();
8678 more
|= (*dqAction
)( target
, request
, this );
8687 // MARK: IOServicePM
8689 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8691 //*********************************************************************************
8694 // Serialize IOServicePM for debugging.
8695 //*********************************************************************************
8698 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8700 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8703 dict
->setObject(key
, num
);
8708 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
) const
8710 OSDictionary
* dict
;
8712 int powerClamp
= -1;
8715 if (IdleTimerPeriod
)
8718 if (PMActions
.parameter
& kPMActionsFlagLimitPower
)
8722 if (PMActions
.parameter
&
8723 (kPMActionsFlagIsDisplayWrangler
| kPMActionsFlagIsGraphicsDevice
))
8727 #if WORK_QUEUE_STATS
8728 if (gIOPMRootNode
== ControllingDriver
)
8733 dict
= OSDictionary::withDictionary(
8734 PowerClients
, PowerClients
->getCount() + dictSize
);
8736 dict
= OSDictionary::withCapacity(dictSize
);
8740 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8741 setPMProperty(dict
, "CapabilityFlags", CurrentCapabilityFlags
);
8742 if (NumberOfPowerStates
)
8743 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
-1);
8744 if (DesiredPowerState
!= CurrentPowerState
)
8745 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8746 if (kIOPM_Finished
!= MachineState
)
8747 setPMProperty(dict
, "MachineState", MachineState
);
8748 if (DeviceOverrideEnabled
)
8749 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8750 if (powerClamp
>= 0)
8751 setPMProperty(dict
, "PowerClamp", powerClamp
);
8753 if (IdleTimerPeriod
)
8759 clock_get_uptime(&now
);
8761 // The idle timer period in milliseconds
8762 setPMProperty(dict
, "IdleTimerPeriod", NextIdleTimerPeriod
* 1000ULL);
8764 // Number of tickles since the last idle timer expiration
8765 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8767 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
8769 // Milliseconds since the last activity tickle
8771 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8772 absolutetime_to_nanoseconds(delta
, &nsecs
);
8773 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
8776 if (!IdleTimerStopped
&& AbsoluteTime_to_scalar(&IdleTimerStartTime
))
8778 // Idle timer elapsed time in milliseconds
8780 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
8781 absolutetime_to_nanoseconds(delta
, &nsecs
);
8782 setPMProperty(dict
, "IdleTimerElapsedTime", NS_TO_MS(nsecs
));
8786 #if WORK_QUEUE_STATS
8787 if (gIOPMRootNode
== Owner
)
8789 setPMProperty(dict
, "WQ-CheckForWork",
8790 gIOPMWorkQueue
->fStatCheckForWork
);
8791 setPMProperty(dict
, "WQ-ScanEntries",
8792 gIOPMWorkQueue
->fStatScanEntries
);
8793 setPMProperty(dict
, "WQ-QueueEmpty",
8794 gIOPMWorkQueue
->fStatQueueEmpty
);
8795 setPMProperty(dict
, "WQ-NoWorkDone",
8796 gIOPMWorkQueue
->fStatNoWorkDone
);
8800 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
)
8802 // Don't report advisory tickle when it has no influence
8803 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
8806 ok
= dict
->serialize(s
);
8810 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
8813 bool IOServicePM::serialize( OSSerialize
* s
) const
8815 IOReturn ret
= kIOReturnNotReady
;
8817 if (gIOPMWatchDogThread
== current_thread())
8819 // Calling without lock as this data is collected for debug purpose, before reboot.
8820 // The workloop is probably already hung in state machine.
8821 ret
= gatedSerialize(s
);
8823 else if (gIOPMWorkLoop
)
8825 ret
= gIOPMWorkLoop
->runAction(
8826 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
8827 (OSObject
*) this, (void *) s
);
8830 return (kIOReturnSuccess
== ret
);
8833 void IOServicePM::pmPrint(
8836 uintptr_t param2
) const
8838 gPlatform
->PMLog(Name
, event
, param1
, param2
);
8841 void IOServicePM::pmTrace(
8845 uintptr_t param2
) const
8847 uintptr_t nameAsArg
= 0;
8849 assert(event
< KDBG_CODE_MAX
);
8850 assert((eventFunc
& ~KDBG_FUNC_MASK
) == 0);
8852 // Copy the first characters of the name into an uintptr_t.
8853 // NULL termination is not required.
8854 strncpy((char*)&nameAsArg
, Name
, sizeof(nameAsArg
));
8856 IOTimeStampConstant(IODBG_POWER(event
) | eventFunc
, nameAsArg
, (uintptr_t)Owner
->getRegistryEntryID(), (uintptr_t)(OBFUSCATE(param1
)), (uintptr_t)(OBFUSCATE(param2
)));