2 * Copyright (c) 1998-2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
29 #include <IOKit/assert.h>
30 #include <IOKit/IOKitDebug.h>
31 #include <IOKit/IOLib.h>
32 #include <IOKit/IOMessage.h>
33 #include <IOKit/IOPlatformExpert.h>
34 #include <IOKit/IOService.h>
35 #include <IOKit/IOEventSource.h>
36 #include <IOKit/IOWorkLoop.h>
37 #include <IOKit/IOCommand.h>
38 #include <IOKit/IOTimeStamp.h>
39 #include <IOKit/IOReportMacros.h>
41 #include <IOKit/pwr_mgt/IOPMlog.h>
42 #include <IOKit/pwr_mgt/IOPMinformee.h>
43 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
44 #include <IOKit/pwr_mgt/IOPowerConnection.h>
45 #include <IOKit/pwr_mgt/RootDomain.h>
46 #include <IOKit/pwr_mgt/IOPMPrivate.h>
49 #include <sys/proc_internal.h>
50 #include <libkern/OSDebug.h>
51 #include <kern/thread.h>
53 // Required for notification instrumentation
54 #include "IOServicePrivate.h"
55 #include "IOServicePMPrivate.h"
56 #include "IOKitKernelInternal.h"
59 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
60 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
61 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
62 static void tellAppClientApplier(OSObject
* object
, void * arg
);
64 static uint64_t computeTimeDeltaNS( const AbsoluteTime
* start
)
69 clock_get_uptime(&now
);
70 SUB_ABSOLUTETIME(&now
, start
);
71 absolutetime_to_nanoseconds(now
, &nsec
);
76 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
79 //******************************************************************************
81 //******************************************************************************
83 static bool gIOPMInitialized
= false;
84 static uint32_t gIOPMBusyCount
= 0;
85 static uint32_t gIOPMWorkCount
= 0;
86 static uint32_t gIOPMTickleGeneration
= 0;
87 static IOWorkLoop
* gIOPMWorkLoop
= 0;
88 static IOPMRequestQueue
* gIOPMRequestQueue
= 0;
89 static IOPMRequestQueue
* gIOPMReplyQueue
= 0;
90 static IOPMWorkQueue
* gIOPMWorkQueue
= 0;
91 static IOPMCompletionQueue
* gIOPMFreeQueue
= 0;
92 static IOPMRequest
* gIOPMRequest
= 0;
93 static IOService
* gIOPMRootNode
= 0;
94 static IOPlatformExpert
* gPlatform
= 0;
96 const OSSymbol
* gIOPMPowerClientDevice
= 0;
97 const OSSymbol
* gIOPMPowerClientDriver
= 0;
98 const OSSymbol
* gIOPMPowerClientChildProxy
= 0;
99 const OSSymbol
* gIOPMPowerClientChildren
= 0;
100 const OSSymbol
* gIOPMPowerClientRootDomain
= 0;
102 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= 0;
103 static bool gIOPMAdvisoryTickleEnabled
= true;
104 static thread_t gIOPMWatchDogThread
= NULL
;
106 static uint32_t getPMRequestType( void )
108 uint32_t type
= kIOPMRequestTypeInvalid
;
110 type
= gIOPMRequest
->getType();
114 static IOPMRequestTag
getPMRequestTag( void )
116 IOPMRequestTag tag
= 0;
118 (gIOPMRequest
->getType() == kIOPMRequestTypeRequestPowerStateOverride
))
120 tag
= gIOPMRequest
->fRequestTag
;
125 //******************************************************************************
127 //******************************************************************************
129 #define PM_ERROR(x...) do { kprintf(x);IOLog(x); \
131 #define PM_LOG(x...) do { kprintf(x); } while (false)
133 #define PM_LOG1(x...) do { \
134 if (kIOLogDebugPower & gIOKitDebug) \
135 kprintf(x); } while (false)
137 #define PM_LOG2(x...) do { \
138 if (kIOLogDebugPower & gIOKitDebug) \
139 kprintf(x); } while (false)
142 #define PM_LOG3(x...) do { kprintf(x); } while (false)
144 #define PM_LOG3(x...)
147 #define RD_LOG(x...) do { \
148 if ((kIOLogPMRootDomain & gIOKitDebug) && \
149 (getPMRootDomain() == this)) { \
150 kprintf("PMRD: " x); \
152 #define PM_ASSERT_IN_GATE(x) \
154 assert(gIOPMWorkLoop->inGate()); \
157 #define PM_LOCK() IOLockLock(fPMLock)
158 #define PM_UNLOCK() IOLockUnlock(fPMLock)
159 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
160 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
162 #define ns_per_us 1000
163 #define k30Seconds (30*1000000)
164 #define kMinAckTimeoutTicks (10*1000000)
165 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
166 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
167 #define kPwrMgtKey "IOPowerManagement"
169 #define OUR_PMLog(t, a, b) do { \
170 if (gIOKitDebug & kIOLogPower) \
171 pwrMgt->pmPrint(t, a, b); \
172 if (gIOKitTrace & kIOTracePowerMgmt) \
173 pwrMgt->pmTrace(t, a, b); \
176 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
177 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
179 #define SUPPORT_IDLE_CANCEL 1
181 #define kIOPMPowerStateMax 0xFFFFFFFF
182 #define kInvalidTicklePowerState kIOPMPowerStateMax
184 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
186 #define IS_PM_ROOT (this == gIOPMRootNode)
187 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
188 #define IS_POWER_DROP (StateOrder(fHeadNotePowerState) < StateOrder(fCurrentPowerState))
189 #define IS_POWER_RISE (StateOrder(fHeadNotePowerState) > StateOrder(fCurrentPowerState))
191 // log setPowerStates longer than (ns):
192 #if defined(__i386__) || defined(__x86_64__)
193 #define LOG_SETPOWER_TIMES (300ULL * 1000ULL * 1000ULL)
195 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
197 // log app responses longer than (ns):
198 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
199 // use message tracer to log messages longer than (ns):
200 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
203 kReserveDomainPower
= 1
207 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
208 assert(kIOPM_BadMachineState != n); \
209 fSavedMachineState = n; } while (false)
212 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
213 fMachineState = fSavedMachineState; \
214 fSavedMachineState = kIOPM_BadMachineState; } while (false)
216 #define PM_ACTION_0(a) \
217 do { if (fPMActions.a) { \
218 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
221 #define PM_ACTION_2(a, x, y) \
222 do { if (fPMActions.a) { \
223 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, \
224 getPMRequestTag()); } \
227 #define PM_ACTION_3(a, x, y, z) \
228 do { if (fPMActions.a) { \
229 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y, z); } \
232 static OSNumber
* copyClientIDForNotification(
234 IOPMInterestContext
*context
);
236 static void logClientIDForNotification(
238 IOPMInterestContext
*context
,
239 const char *logString
);
241 //*********************************************************************************
244 // Check kgmacros after modifying machine states.
245 //*********************************************************************************
250 kIOPM_OurChangeTellClientsPowerDown
= 1,
251 kIOPM_OurChangeTellUserPMPolicyPowerDown
= 2,
252 kIOPM_OurChangeTellPriorityClientsPowerDown
= 3,
253 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 4,
254 kIOPM_OurChangeSetPowerState
= 5,
255 kIOPM_OurChangeWaitForPowerSettle
= 6,
256 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 7,
257 kIOPM_OurChangeTellCapabilityDidChange
= 8,
258 kIOPM_OurChangeFinish
= 9,
260 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
261 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
262 kIOPM_ParentChangeSetPowerState
= 12,
263 kIOPM_ParentChangeWaitForPowerSettle
= 13,
264 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
265 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
266 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
268 kIOPM_NotifyChildrenStart
= 17,
269 kIOPM_NotifyChildrenOrdered
= 18,
270 kIOPM_NotifyChildrenDelayed
= 19,
271 kIOPM_SyncTellClientsPowerDown
= 20,
272 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
273 kIOPM_SyncNotifyWillChange
= 22,
274 kIOPM_SyncNotifyDidChange
= 23,
275 kIOPM_SyncTellCapabilityDidChange
= 24,
276 kIOPM_SyncFinish
= 25,
277 kIOPM_TellCapabilityChangeDone
= 26,
278 kIOPM_DriverThreadCallDone
= 27,
280 kIOPM_BadMachineState
= 0xFFFFFFFF
283 //*********************************************************************************
286 // Initialize power management.
287 //*********************************************************************************
289 void IOService::PMinit( void )
293 if ( !gIOPMInitialized
)
295 gPlatform
= getPlatform();
296 gIOPMWorkLoop
= IOWorkLoop::workLoop();
299 gIOPMRequestQueue
= IOPMRequestQueue::create(
300 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
301 this, &IOService::servicePMRequestQueue
));
303 gIOPMReplyQueue
= IOPMRequestQueue::create(
304 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
305 this, &IOService::servicePMReplyQueue
));
307 gIOPMWorkQueue
= IOPMWorkQueue::create(
309 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
310 &IOService::servicePMRequest
),
311 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
312 &IOService::retirePMRequest
));
314 gIOPMFreeQueue
= IOPMCompletionQueue::create(
315 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
316 this, &IOService::servicePMFreeQueue
));
318 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
321 gIOPMRequestQueue
->release();
322 gIOPMRequestQueue
= 0;
325 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
328 gIOPMReplyQueue
->release();
332 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
335 gIOPMWorkQueue
->release();
339 if (gIOPMWorkLoop
->addEventSource(gIOPMFreeQueue
) !=
342 gIOPMFreeQueue
->release();
346 gIOPMPowerClientDevice
=
347 OSSymbol::withCStringNoCopy( "DevicePowerState" );
349 gIOPMPowerClientDriver
=
350 OSSymbol::withCStringNoCopy( "DriverPowerState" );
352 gIOPMPowerClientChildProxy
=
353 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
355 gIOPMPowerClientChildren
=
356 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
358 gIOPMPowerClientAdvisoryTickle
=
359 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
361 gIOPMPowerClientRootDomain
=
362 OSSymbol::withCStringNoCopy( "RootDomainPower" );
365 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMFreeQueue
)
366 gIOPMInitialized
= true;
368 if (!gIOPMInitialized
)
371 pwrMgt
= new IOServicePM
;
373 setProperty(kPwrMgtKey
, pwrMgt
);
375 queue_init(&pwrMgt
->WorkChain
);
376 queue_init(&pwrMgt
->RequestHead
);
377 queue_init(&pwrMgt
->PMDriverCallQueue
);
380 fPMLock
= IOLockAlloc();
381 fInterestedDrivers
= new IOPMinformeeList
;
382 fInterestedDrivers
->initialize();
383 fDesiredPowerState
= kPowerStateZero
;
384 fDeviceDesire
= kPowerStateZero
;
385 fInitialPowerChange
= true;
386 fInitialSetPowerState
= true;
387 fPreviousRequestPowerFlags
= 0;
388 fDeviceOverrideEnabled
= false;
389 fMachineState
= kIOPM_Finished
;
390 fSavedMachineState
= kIOPM_BadMachineState
;
391 fIdleTimerMinPowerState
= kPowerStateZero
;
392 fActivityLock
= IOLockAlloc();
393 fStrictTreeOrder
= false;
394 fActivityTicklePowerState
= kInvalidTicklePowerState
;
395 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
396 fControllingDriver
= NULL
;
398 fNumberOfPowerStates
= 0;
399 fCurrentPowerState
= kPowerStateZero
;
400 fParentsCurrentPowerFlags
= 0;
401 fMaxPowerState
= kPowerStateZero
;
403 fParentsKnowState
= false;
405 fResponseArray
= NULL
;
406 fNotifyClientArray
= NULL
;
407 fCurrentPowerConsumption
= kIOPMUnknown
;
408 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
410 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot()))
412 gIOPMRootNode
= this;
413 fParentsKnowState
= true;
415 else if (getProperty(kIOPMResetPowerStateOnWakeKey
) == kOSBooleanTrue
)
417 fResetPowerStateOnWake
= true;
422 fWatchdogTimer
= thread_call_allocate(
423 &IOService::watchdog_timer_expired
, (thread_call_param_t
)this);
426 fAckTimer
= thread_call_allocate(
427 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
428 fSettleTimer
= thread_call_allocate(
429 &settle_timer_expired
, (thread_call_param_t
)this);
430 fIdleTimer
= thread_call_allocate(
431 &idle_timer_expired
, (thread_call_param_t
)this);
432 fDriverCallEntry
= thread_call_allocate(
433 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
434 assert(fDriverCallEntry
);
436 // Check for powerChangeDone override.
437 if (OSMemberFunctionCast(void (*)(void),
438 getResourceService(), &IOService::powerChangeDone
) !=
439 OSMemberFunctionCast(void (*)(void),
440 this, &IOService::powerChangeDone
))
442 fPCDFunctionOverride
= true;
446 IOPMprot
* prot
= new IOPMprot
;
450 prot
->ourName
= fName
;
451 prot
->thePlatform
= gPlatform
;
456 pm_vars
= (void *) (uintptr_t) true;
463 //*********************************************************************************
466 // Free the data created by PMinit. Only called from IOService::free().
467 //*********************************************************************************
469 void IOService::PMfree( void )
476 assert(fMachineState
== kIOPM_Finished
);
477 assert(fInsertInterestSet
== NULL
);
478 assert(fRemoveInterestSet
== NULL
);
479 assert(fNotifyChildArray
== NULL
);
480 assert(queue_empty(&pwrMgt
->RequestHead
));
481 assert(queue_empty(&fPMDriverCallQueue
));
483 if (fWatchdogTimer
) {
484 thread_call_cancel(fWatchdogTimer
);
485 thread_call_free(fWatchdogTimer
);
486 fWatchdogTimer
= NULL
;
489 if ( fSettleTimer
) {
490 thread_call_cancel(fSettleTimer
);
491 thread_call_free(fSettleTimer
);
495 thread_call_cancel(fAckTimer
);
496 thread_call_free(fAckTimer
);
500 thread_call_cancel(fIdleTimer
);
501 thread_call_free(fIdleTimer
);
504 if ( fDriverCallEntry
) {
505 thread_call_free(fDriverCallEntry
);
506 fDriverCallEntry
= NULL
;
512 if ( fActivityLock
) {
513 IOLockFree(fActivityLock
);
514 fActivityLock
= NULL
;
516 if ( fInterestedDrivers
) {
517 fInterestedDrivers
->release();
518 fInterestedDrivers
= NULL
;
520 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
521 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
522 fDriverCallParamPtr
= 0;
523 fDriverCallParamSlots
= 0;
525 if ( fResponseArray
) {
526 fResponseArray
->release();
527 fResponseArray
= NULL
;
529 if ( fNotifyClientArray
) {
530 fNotifyClientArray
->release();
531 fNotifyClientArray
= NULL
;
533 if (fPowerStates
&& fNumberOfPowerStates
) {
534 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
535 fNumberOfPowerStates
= 0;
539 fPowerClients
->release();
556 void IOService::PMDebug( uint32_t event
, uintptr_t param1
, uintptr_t param2
)
558 OUR_PMLog(event
, param1
, param2
);
561 //*********************************************************************************
562 // [public] joinPMtree
564 // A policy-maker calls its nub here when initializing, to be attached into
565 // the power management hierarchy. The default function is to call the
566 // platform expert, which knows how to do it. This method is overridden
567 // by a nub subclass which may either know how to do it, or may need to
568 // take other action.
570 // This may be the only "power management" method used in a nub,
571 // meaning it may not be initialized for power management.
572 //*********************************************************************************
574 void IOService::joinPMtree( IOService
* driver
)
576 IOPlatformExpert
* platform
;
578 platform
= getPlatform();
579 assert(platform
!= 0);
580 platform
->PMRegisterDevice(this, driver
);
584 //*********************************************************************************
585 // [deprecated] youAreRoot
587 // Power Managment is informing us that we are the root power domain.
588 //*********************************************************************************
590 IOReturn
IOService::youAreRoot( void )
594 #endif /* !__LP64__ */
596 //*********************************************************************************
599 // Immediately stop driver callouts. Schedule an async stop request to detach
601 //*********************************************************************************
603 void IOService::PMstop( void )
605 IOPMRequest
* request
;
612 if (fLockedFlags
.PMStop
)
614 PM_LOG2("%s: PMstop() already stopped\n", fName
);
619 // Inhibit future driver calls.
620 fLockedFlags
.PMStop
= true;
622 // Wait for all prior driver calls to finish.
623 waitForPMDriverCall();
627 // The rest of the work is performed async.
628 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
631 PM_LOG2("%s: %p PMstop\n", getName(), OBFUSCATE(this));
632 submitPMRequest( request
);
636 //*********************************************************************************
637 // [private] handlePMstop
639 // Disconnect the node from all parents and children in the power plane.
640 //*********************************************************************************
642 void IOService::handlePMstop( IOPMRequest
* request
)
646 IOPowerConnection
* connection
;
647 IOService
* theChild
;
648 IOService
* theParent
;
651 PM_LOG2("%s: %p %s start\n", getName(), OBFUSCATE(this), __FUNCTION__
);
653 // remove driver from prevent system sleep lists
654 getPMRootDomain()->updatePreventIdleSleepList(this, false);
655 getPMRootDomain()->updatePreventSystemSleepList(this, false);
657 // remove the property
658 removeProperty(kPwrMgtKey
);
661 iter
= getParentIterator(gIOPowerPlane
);
664 while ( (next
= iter
->getNextObject()) )
666 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
668 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
671 theParent
->removePowerChild(connection
);
672 theParent
->release();
679 // detach IOConnections
680 detachAbove( gIOPowerPlane
);
682 // no more power state changes
683 fParentsKnowState
= false;
686 iter
= getChildIterator(gIOPowerPlane
);
689 while ( (next
= iter
->getNextObject()) )
691 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
693 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
696 // detach nub from child
697 connection
->detachFromChild(theChild
, gIOPowerPlane
);
700 // detach us from nub
701 detachFromChild(connection
, gIOPowerPlane
);
707 // Remove all interested drivers from the list, including the power
708 // controlling driver.
710 // Usually, the controlling driver and the policy-maker functionality
711 // are implemented by the same object, and without the deregistration,
712 // the object will be holding an extra retain on itself, and cannot
715 if ( fInterestedDrivers
)
717 IOPMinformeeList
* list
= fInterestedDrivers
;
721 while ((item
= list
->firstInList()))
723 list
->removeFromList(item
->whatObject
);
728 // Clear idle period to prevent idleTimerExpired() from servicing
729 // idle timer expirations.
731 fIdleTimerPeriod
= 0;
732 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
735 PM_LOG2("%s: %p %s done\n", getName(), OBFUSCATE(this), __FUNCTION__
);
738 //*********************************************************************************
739 // [public] addPowerChild
741 // Power Management is informing us who our children are.
742 //*********************************************************************************
744 IOReturn
IOService::addPowerChild( IOService
* child
)
746 IOPowerConnection
* connection
= 0;
747 IOPMRequest
* requests
[3] = {0, 0, 0};
752 return kIOReturnBadArgument
;
754 if (!initialized
|| !child
->initialized
)
755 return IOPMNotYetInitialized
;
757 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
760 // Is this child already one of our children?
762 iter
= child
->getParentIterator( gIOPowerPlane
);
765 IORegistryEntry
* entry
;
768 while ((next
= iter
->getNextObject()))
770 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
771 isChild(entry
, gIOPowerPlane
))
781 PM_LOG("%s: %s (%p) is already a child\n",
782 getName(), child
->getName(), OBFUSCATE(child
));
786 // Add the child to the power plane immediately, but the
787 // joining connection is marked as not ready.
788 // We want the child to appear in the power plane before
789 // returning to the caller, but don't want the caller to
790 // block on the PM work loop.
792 connection
= new IOPowerConnection
;
796 // Create a chain of PM requests to perform the bottom-half
797 // work from the PM work loop.
799 requests
[0] = acquirePMRequest(
801 /* type */ kIOPMRequestTypeAddPowerChild1
);
803 requests
[1] = acquirePMRequest(
805 /* type */ kIOPMRequestTypeAddPowerChild2
);
807 requests
[2] = acquirePMRequest(
809 /* type */ kIOPMRequestTypeAddPowerChild3
);
811 if (!requests
[0] || !requests
[1] || !requests
[2])
814 requests
[0]->attachNextRequest( requests
[1] );
815 requests
[1]->attachNextRequest( requests
[2] );
818 connection
->start(this);
819 connection
->setAwaitingAck(false);
820 connection
->setReadyFlag(false);
822 attachToChild( connection
, gIOPowerPlane
);
823 connection
->attachToChild( child
, gIOPowerPlane
);
825 // connection needs to be released
826 requests
[0]->fArg0
= connection
;
827 requests
[1]->fArg0
= connection
;
828 requests
[2]->fArg0
= connection
;
830 submitPMRequest( requests
, 3 );
831 return kIOReturnSuccess
;
835 if (connection
) connection
->release();
836 if (requests
[0]) releasePMRequest(requests
[0]);
837 if (requests
[1]) releasePMRequest(requests
[1]);
838 if (requests
[2]) releasePMRequest(requests
[2]);
840 // Silent failure, to prevent platform drivers from adding the child
841 // to the root domain.
843 return kIOReturnSuccess
;
846 //*********************************************************************************
847 // [private] addPowerChild1
849 // Step 1/3 of adding a power child. Called on the power parent.
850 //*********************************************************************************
852 void IOService::addPowerChild1( IOPMRequest
* request
)
854 IOPMPowerStateIndex tempDesire
= kPowerStateZero
;
856 // Make us temporary usable before adding the child.
859 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
861 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
863 tempDesire
= fHighestPowerState
;
866 if ((tempDesire
!= kPowerStateZero
) &&
867 (IS_PM_ROOT
|| (StateOrder(fMaxPowerState
) >= StateOrder(tempDesire
))))
869 adjustPowerState(tempDesire
);
873 //*********************************************************************************
874 // [private] addPowerChild2
876 // Step 2/3 of adding a power child. Called on the joining child.
877 // Execution blocked behind addPowerChild1.
878 //*********************************************************************************
880 void IOService::addPowerChild2( IOPMRequest
* request
)
882 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
884 IOPMPowerFlags powerFlags
;
886 unsigned long powerState
;
887 unsigned long tempDesire
;
890 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
892 if (!parent
|| !inPlane(gIOPowerPlane
))
894 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
898 // Parent will be waiting for us to complete this stage.
899 // It is safe to directly access parent's vars.
901 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
902 powerState
= parent
->fCurrentPowerState
;
905 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
909 // Set our power parent.
911 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
913 setParentInfo( powerFlags
, connection
, knowsState
);
915 connection
->setReadyFlag(true);
917 if ( fControllingDriver
&& fParentsKnowState
)
919 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
920 // initially change into the state we are already in
921 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
922 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
923 adjustPowerState(tempDesire
);
926 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
929 //*********************************************************************************
930 // [private] addPowerChild3
932 // Step 3/3 of adding a power child. Called on the parent.
933 // Execution blocked behind addPowerChild2.
934 //*********************************************************************************
936 void IOService::addPowerChild3( IOPMRequest
* request
)
938 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
940 IOPMrootDomain
* rootDomain
= getPMRootDomain();
943 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
945 if (child
&& inPlane(gIOPowerPlane
))
947 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder"))
949 PM_LOG1("%s: strict PM order enforced\n", getName());
950 fStrictTreeOrder
= true;
954 rootDomain
->joinAggressiveness( child
);
958 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
961 connection
->release();
965 //*********************************************************************************
966 // [deprecated] setPowerParent
968 // Power Management is informing us who our parent is.
969 // If we have a controlling driver, find out, given our newly-informed
970 // power domain state, what state it would be in, and then tell it
971 // to assume that state.
972 //*********************************************************************************
974 IOReturn
IOService::setPowerParent(
975 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
977 return kIOReturnUnsupported
;
979 #endif /* !__LP64__ */
981 //*********************************************************************************
982 // [public] removePowerChild
984 // Called on a parent whose child is being removed by PMstop().
985 //*********************************************************************************
987 IOReturn
IOService::removePowerChild( IOPowerConnection
* theNub
)
989 IORegistryEntry
* theChild
;
992 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
996 // detach nub from child
997 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1000 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1001 theChild
->release();
1003 // detach from the nub
1004 detachFromChild(theNub
, gIOPowerPlane
);
1006 // Are we awaiting an ack from this child?
1007 if ( theNub
->getAwaitingAck() )
1009 // yes, pretend we got one
1010 theNub
->setAwaitingAck(false);
1011 if (fHeadNotePendingAcks
!= 0 )
1013 // that's one fewer ack to worry about
1014 fHeadNotePendingAcks
--;
1016 // is that the last?
1017 if ( fHeadNotePendingAcks
== 0 )
1021 // Request unblocked, work queue
1022 // should re-scan all busy requests.
1023 gIOPMWorkQueue
->incrementProducerCount();
1030 // A child has gone away, re-scan children desires and clamp bits.
1031 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1033 if (!fAdjustPowerScheduled
)
1035 IOPMRequest
* request
;
1036 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1039 submitPMRequest( request
);
1040 fAdjustPowerScheduled
= true;
1047 //*********************************************************************************
1048 // [public] registerPowerDriver
1050 // A driver has called us volunteering to control power to our device.
1051 //*********************************************************************************
1053 IOReturn
IOService::registerPowerDriver(
1054 IOService
* powerDriver
,
1055 IOPMPowerState
* powerStates
,
1056 unsigned long numberOfStates
)
1058 IOPMRequest
* request
;
1059 IOPMPSEntry
* powerStatesCopy
= 0;
1060 IOPMPowerStateIndex stateOrder
;
1061 IOReturn error
= kIOReturnSuccess
;
1064 return IOPMNotYetInitialized
;
1066 if (!powerStates
|| (numberOfStates
< 2))
1068 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1069 return kIOReturnBadArgument
;
1072 if (!powerDriver
|| !powerDriver
->initialized
)
1074 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1075 return kIOReturnBadArgument
;
1078 if (powerStates
[0].version
> kIOPMPowerStateVersion2
)
1080 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1081 return kIOReturnBadArgument
;
1085 // Make a copy of the supplied power state array.
1086 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1087 if (!powerStatesCopy
)
1089 error
= kIOReturnNoMemory
;
1093 // Initialize to bogus values
1094 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1095 powerStatesCopy
[i
].stateOrderToIndex
= kIOPMPowerStateMax
;
1097 for (uint32_t i
= 0; i
< numberOfStates
; i
++)
1099 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1100 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1101 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1102 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1103 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1104 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1105 if (powerStates
[i
].version
>= kIOPMPowerStateVersion2
)
1106 stateOrder
= powerStates
[i
].stateOrder
;
1110 if (stateOrder
< numberOfStates
)
1112 powerStatesCopy
[i
].stateOrder
= stateOrder
;
1113 powerStatesCopy
[stateOrder
].stateOrderToIndex
= i
;
1117 for (IOPMPowerStateIndex i
= 0; i
< numberOfStates
; i
++)
1119 if (powerStatesCopy
[i
].stateOrderToIndex
== kIOPMPowerStateMax
)
1121 // power state order missing
1122 error
= kIOReturnBadArgument
;
1126 if (kIOReturnSuccess
!= error
)
1129 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1132 error
= kIOReturnNoMemory
;
1136 powerDriver
->retain();
1137 request
->fArg0
= (void *) powerDriver
;
1138 request
->fArg1
= (void *) powerStatesCopy
;
1139 request
->fArg2
= (void *) numberOfStates
;
1141 submitPMRequest( request
);
1142 return kIOReturnSuccess
;
1146 if (powerStatesCopy
)
1147 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1152 //*********************************************************************************
1153 // [private] handleRegisterPowerDriver
1154 //*********************************************************************************
1156 void IOService::handleRegisterPowerDriver( IOPMRequest
* request
)
1158 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1159 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1160 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1161 unsigned long i
, stateIndex
;
1162 unsigned long lowestPowerState
;
1166 PM_ASSERT_IN_GATE();
1167 assert(powerStates
);
1168 assert(powerDriver
);
1169 assert(numberOfStates
> 1);
1171 if ( !fNumberOfPowerStates
)
1173 OUR_PMLog(kPMLogControllingDriver
,
1174 (unsigned long) numberOfStates
,
1175 (unsigned long) kIOPMPowerStateVersion1
);
1177 fPowerStates
= powerStates
;
1178 fNumberOfPowerStates
= numberOfStates
;
1179 fControllingDriver
= powerDriver
;
1180 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1182 lowestPowerState
= fPowerStates
[0].stateOrderToIndex
;
1183 fHighestPowerState
= fPowerStates
[numberOfStates
- 1].stateOrderToIndex
;
1185 // OR'in all the output power flags
1186 fMergedOutputPowerFlags
= 0;
1187 fDeviceUsablePowerState
= lowestPowerState
;
1188 for ( i
= 0; i
< numberOfStates
; i
++ )
1190 fMergedOutputPowerFlags
|= fPowerStates
[i
].outputPowerFlags
;
1192 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
1193 assert(stateIndex
< numberOfStates
);
1194 if ((fDeviceUsablePowerState
== lowestPowerState
) &&
1195 (fPowerStates
[stateIndex
].capabilityFlags
& IOPMDeviceUsable
))
1197 // The minimum power state that the device is usable
1198 fDeviceUsablePowerState
= stateIndex
;
1202 // Register powerDriver as interested, unless already done.
1203 // We don't want to register the default implementation since
1204 // it does nothing. One ramification of not always registering
1205 // is the one fewer retain count held.
1207 root
= getPlatform()->getProvider();
1210 ((OSMemberFunctionCast(void (*)(void),
1211 root
, &IOService::powerStateDidChangeTo
)) !=
1212 ((OSMemberFunctionCast(void (*)(void),
1213 this, &IOService::powerStateDidChangeTo
)))) ||
1214 ((OSMemberFunctionCast(void (*)(void),
1215 root
, &IOService::powerStateWillChangeTo
)) !=
1216 ((OSMemberFunctionCast(void (*)(void),
1217 this, &IOService::powerStateWillChangeTo
)))))
1219 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
)
1222 fInterestedDrivers
->appendNewInformee(powerDriver
);
1227 // Examine all existing power clients and perform limit check.
1229 if (fPowerClients
&&
1230 (iter
= OSCollectionIterator::withCollection(fPowerClients
)))
1232 const OSSymbol
* client
;
1233 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
1235 IOPMPowerStateIndex powerState
= getPowerStateForClient(client
);
1236 if (powerState
>= numberOfStates
)
1238 updatePowerClient(client
, fHighestPowerState
);
1244 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1246 IOPMPowerStateIndex tempDesire
;
1247 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1248 // initially change into the state we are already in
1249 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1250 adjustPowerState(tempDesire
);
1255 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1256 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1259 powerDriver
->release();
1262 //*********************************************************************************
1263 // [public] registerInterestedDriver
1265 // Add the caller to our list of interested drivers and return our current
1266 // power state. If we don't have a power-controlling driver yet, we will
1267 // call this interested driver again later when we do get a driver and find
1268 // out what the current power state of the device is.
1269 //*********************************************************************************
1271 IOPMPowerFlags
IOService::registerInterestedDriver( IOService
* driver
)
1273 IOPMRequest
* request
;
1276 if (!driver
|| !initialized
|| !fInterestedDrivers
)
1280 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1281 if (fInsertInterestSet
== NULL
)
1282 fInsertInterestSet
= OSSet::withCapacity(4);
1283 if (fInsertInterestSet
)
1285 fInsertInterestSet
->setObject(driver
);
1286 if (fRemoveInterestSet
)
1287 fRemoveInterestSet
->removeObject(driver
);
1293 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1295 submitPMRequest( request
);
1298 // This return value cannot be trusted, but return a value
1299 // for those clients that care.
1301 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1302 return kIOPMDeviceUsable
;
1305 //*********************************************************************************
1306 // [public] deRegisterInterestedDriver
1307 //*********************************************************************************
1309 IOReturn
IOService::deRegisterInterestedDriver( IOService
* driver
)
1311 IOPMinformeeList
* list
;
1312 IOPMinformee
* item
;
1313 IOPMRequest
* request
;
1317 return kIOReturnBadArgument
;
1318 if (!initialized
|| !fInterestedDrivers
)
1319 return IOPMNotPowerManaged
;
1322 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1323 if (fRemoveInterestSet
== NULL
)
1324 fRemoveInterestSet
= OSSet::withCapacity(4);
1325 if (fRemoveInterestSet
)
1327 fRemoveInterestSet
->setObject(driver
);
1328 if (fInsertInterestSet
)
1329 fInsertInterestSet
->removeObject(driver
);
1331 list
= fInterestedDrivers
;
1332 item
= list
->findItem(driver
);
1333 if (item
&& item
->active
)
1335 item
->active
= false;
1336 waitForPMDriverCall( driver
);
1343 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1345 submitPMRequest( request
);
1351 //*********************************************************************************
1352 // [private] handleInterestChanged
1354 // Handle interest added or removed.
1355 //*********************************************************************************
1357 void IOService::handleInterestChanged( IOPMRequest
* request
)
1360 IOPMinformee
* informee
;
1361 IOPMinformeeList
* list
= fInterestedDrivers
;
1365 if (fInsertInterestSet
)
1367 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject()))
1369 if (list
->findItem(driver
) == NULL
)
1371 informee
= list
->appendNewInformee(driver
);
1373 fInsertInterestSet
->removeObject(driver
);
1375 fInsertInterestSet
->release();
1376 fInsertInterestSet
= 0;
1379 if (fRemoveInterestSet
)
1381 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject()))
1383 informee
= list
->findItem(driver
);
1386 // Clean-up async interest acknowledgement
1387 if (fHeadNotePendingAcks
&& informee
->timer
)
1389 informee
->timer
= 0;
1390 fHeadNotePendingAcks
--;
1392 list
->removeFromList(driver
);
1394 fRemoveInterestSet
->removeObject(driver
);
1396 fRemoveInterestSet
->release();
1397 fRemoveInterestSet
= 0;
1403 //*********************************************************************************
1404 // [public] acknowledgePowerChange
1406 // After we notified one of the interested drivers or a power-domain child
1407 // of an impending change in power, it has called to say it is now
1408 // prepared for the change. If this object is the last to
1409 // acknowledge this change, we take whatever action we have been waiting
1411 // That may include acknowledging to our parent. In this case, we do it
1412 // last of all to insure that this doesn't cause the parent to call us some-
1413 // where else and alter data we are relying on here (like the very existance
1414 // of a "current change note".)
1415 //*********************************************************************************
1417 IOReturn
IOService::acknowledgePowerChange( IOService
* whichObject
)
1419 IOPMRequest
* request
;
1422 return IOPMNotYetInitialized
;
1424 return kIOReturnBadArgument
;
1426 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1428 return kIOReturnNoMemory
;
1430 whichObject
->retain();
1431 request
->fArg0
= whichObject
;
1433 submitPMRequest( request
);
1437 //*********************************************************************************
1438 // [private] handleAcknowledgePowerChange
1439 //*********************************************************************************
1441 bool IOService::handleAcknowledgePowerChange( IOPMRequest
* request
)
1443 IOPMinformee
* informee
;
1444 unsigned long childPower
= kIOPMUnknown
;
1445 IOService
* theChild
;
1446 IOService
* whichObject
;
1447 bool all_acked
= false;
1449 PM_ASSERT_IN_GATE();
1450 whichObject
= (IOService
*) request
->fArg0
;
1451 assert(whichObject
);
1453 // one of our interested drivers?
1454 informee
= fInterestedDrivers
->findItem( whichObject
);
1455 if ( informee
== NULL
)
1457 if ( !isChild(whichObject
, gIOPowerPlane
) )
1459 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1462 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1465 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1468 if ( fHeadNotePendingAcks
!= 0 )
1470 assert(fPowerStates
!= NULL
);
1472 // yes, make sure we're expecting acks
1473 if ( informee
!= NULL
)
1475 // it's an interested driver
1476 // make sure we're expecting this ack
1477 if ( informee
->timer
!= 0 )
1479 #if LOG_SETPOWER_TIMES
1480 if (informee
->timer
> 0)
1482 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1483 if (nsec
> LOG_SETPOWER_TIMES
) {
1484 getPMRootDomain()->pmStatsRecordApplicationResponse(
1485 gIOPMStatsDriverPSChangeSlow
, informee
->whatObject
->getName(),
1486 fDriverCallReason
, NS_TO_MS(nsec
), 0, NULL
, fHeadNotePowerState
);
1491 informee
->timer
= 0;
1492 // that's one fewer to worry about
1493 fHeadNotePendingAcks
--;
1495 // this driver has already acked
1496 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1500 // make sure we're expecting this ack
1501 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1503 // that's one fewer to worry about
1504 fHeadNotePendingAcks
--;
1505 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1506 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1509 childPower
= theChild
->currentPowerConsumption();
1510 theChild
->release();
1512 if ( childPower
== kIOPMUnknown
)
1514 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1516 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
1518 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1524 if ( fHeadNotePendingAcks
== 0 ) {
1525 // yes, stop the timer
1527 // and now we can continue
1531 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1536 whichObject
->release();
1541 //*********************************************************************************
1542 // [public] acknowledgeSetPowerState
1544 // After we instructed our controlling driver to change power states,
1545 // it has called to say it has finished doing so.
1546 // We continue to process the power state change.
1547 //*********************************************************************************
1549 IOReturn
IOService::acknowledgeSetPowerState( void )
1551 IOPMRequest
* request
;
1554 return IOPMNotYetInitialized
;
1556 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1558 return kIOReturnNoMemory
;
1560 submitPMRequest( request
);
1561 return kIOReturnSuccess
;
1564 //*********************************************************************************
1565 // [private] adjustPowerState
1566 //*********************************************************************************
1568 void IOService::adjustPowerState( uint32_t clamp
)
1570 PM_ASSERT_IN_GATE();
1571 computeDesiredState(clamp
, false);
1572 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
))
1574 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1576 // Indicate that children desires must be ignored, and do not ask
1577 // apps for permission to drop power. This is used by root domain
1578 // for demand sleep.
1580 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
1581 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1584 /* flags */ changeFlags
,
1585 /* power state */ fDesiredPowerState
,
1586 /* domain flags */ 0,
1588 /* parent flags */ 0);
1592 //*********************************************************************************
1593 // [public] synchronizePowerTree
1594 //*********************************************************************************
1596 IOReturn
IOService::synchronizePowerTree(
1597 IOOptionBits options
,
1598 IOService
* notifyRoot
)
1600 IOPMRequest
* request_c
= 0;
1601 IOPMRequest
* request_s
;
1603 if (this != getPMRootDomain())
1604 return kIOReturnBadArgument
;
1606 return kIOPMNotYetInitialized
;
1608 OUR_PMLog(kPMLogCSynchronizePowerTree
, options
, (notifyRoot
!= 0));
1614 // Cancels don't need to be synchronized.
1615 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1616 if (nr
) submitPMRequest(nr
);
1617 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1618 if (nr
) submitPMRequest(nr
);
1621 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1623 goto error_no_memory
;
1625 if (options
& kIOPMSyncCancelPowerDown
)
1626 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1629 request_c
->attachNextRequest( request_s
);
1630 submitPMRequest(request_c
);
1633 request_s
->fArg0
= (void *)(uintptr_t) options
;
1634 submitPMRequest(request_s
);
1636 return kIOReturnSuccess
;
1639 if (request_c
) releasePMRequest(request_c
);
1640 if (request_s
) releasePMRequest(request_s
);
1641 return kIOReturnNoMemory
;
1644 //*********************************************************************************
1645 // [private] handleSynchronizePowerTree
1646 //*********************************************************************************
1648 void IOService::handleSynchronizePowerTree( IOPMRequest
* request
)
1650 PM_ASSERT_IN_GATE();
1651 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1652 (fCurrentPowerState
== fHighestPowerState
))
1654 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1657 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1658 (options
& kIOPMSyncNoChildNotify
),
1659 /* power state */ fCurrentPowerState
,
1660 /* domain flags */ 0,
1662 /* parent flags */ 0);
1667 //*********************************************************************************
1668 // [deprecated] powerDomainWillChangeTo
1670 // Called by the power-hierarchy parent notifying of a new power state
1671 // in the power domain.
1672 // We enqueue a parent power-change to our queue of power changes.
1673 // This may or may not cause us to change power, depending on what
1674 // kind of change is occuring in the domain.
1675 //*********************************************************************************
1677 IOReturn
IOService::powerDomainWillChangeTo(
1678 IOPMPowerFlags newPowerFlags
,
1679 IOPowerConnection
* whichParent
)
1682 return kIOReturnUnsupported
;
1684 #endif /* !__LP64__ */
1686 //*********************************************************************************
1687 // [private] handlePowerDomainWillChangeTo
1688 //*********************************************************************************
1690 void IOService::handlePowerDomainWillChangeTo( IOPMRequest
* request
)
1692 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1693 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1694 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1695 IOPMPowerChangeFlags myChangeFlags
;
1698 IOPowerConnection
* connection
;
1699 IOPMPowerStateIndex maxPowerState
;
1700 IOPMPowerFlags combinedPowerFlags
;
1701 bool savedParentsKnowState
;
1702 IOReturn result
= IOPMAckImplied
;
1704 PM_ASSERT_IN_GATE();
1705 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1707 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1709 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1713 savedParentsKnowState
= fParentsKnowState
;
1715 // Combine parents' output power flags.
1717 combinedPowerFlags
= 0;
1719 iter
= getParentIterator(gIOPowerPlane
);
1722 while ( (next
= iter
->getNextObject()) )
1724 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1726 if ( connection
== whichParent
)
1727 combinedPowerFlags
|= parentPowerFlags
;
1729 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1735 // If our initial change has yet to occur, then defer the power change
1736 // until after the power domain has completed its power transition.
1738 if ( fControllingDriver
&& !fInitialPowerChange
)
1740 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1741 combinedPowerFlags
);
1743 // Use kIOPMSynchronize below instead of kIOPMRootBroadcastFlags
1744 // to avoid propagating the root change flags if any service must
1745 // change power state due to root's will-change notification.
1746 // Root does not change power state for kIOPMSynchronize.
1748 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1749 (parentChangeFlags
& kIOPMSynchronize
);
1751 result
= startPowerChange(
1752 /* flags */ myChangeFlags
,
1753 /* power state */ maxPowerState
,
1754 /* domain flags */ combinedPowerFlags
,
1755 /* connection */ whichParent
,
1756 /* parent flags */ parentPowerFlags
);
1759 // If parent is dropping power, immediately update the parent's
1760 // capability flags. Any future merging of parent(s) combined
1761 // power flags should account for this power drop.
1763 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1765 setParentInfo(parentPowerFlags
, whichParent
, true);
1768 // Parent is expecting an ACK from us. If we did not embark on a state
1769 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1770 // still required to issue an ACK to our parent.
1772 if (IOPMAckImplied
== result
)
1775 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1779 parent
->acknowledgePowerChange( whichParent
);
1785 // Drop the retain from notifyChild().
1786 if (whichParent
) whichParent
->release();
1790 //*********************************************************************************
1791 // [deprecated] powerDomainDidChangeTo
1793 // Called by the power-hierarchy parent after the power state of the power domain
1794 // has settled at a new level.
1795 // We enqueue a parent power-change to our queue of power changes.
1796 // This may or may not cause us to change power, depending on what
1797 // kind of change is occuring in the domain.
1798 //*********************************************************************************
1800 IOReturn
IOService::powerDomainDidChangeTo(
1801 IOPMPowerFlags newPowerFlags
,
1802 IOPowerConnection
* whichParent
)
1805 return kIOReturnUnsupported
;
1807 #endif /* !__LP64__ */
1809 //*********************************************************************************
1810 // [private] handlePowerDomainDidChangeTo
1811 //*********************************************************************************
1813 void IOService::handlePowerDomainDidChangeTo( IOPMRequest
* request
)
1815 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1816 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1817 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1818 IOPMPowerChangeFlags myChangeFlags
;
1819 IOPMPowerStateIndex maxPowerState
;
1820 IOPMPowerStateIndex initialDesire
= kPowerStateZero
;
1821 bool computeDesire
= false;
1822 bool desireChanged
= false;
1823 bool savedParentsKnowState
;
1824 IOReturn result
= IOPMAckImplied
;
1826 PM_ASSERT_IN_GATE();
1827 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1829 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1831 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1835 savedParentsKnowState
= fParentsKnowState
;
1837 setParentInfo(parentPowerFlags
, whichParent
, true);
1839 if ( fControllingDriver
)
1841 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1842 fParentsCurrentPowerFlags
);
1844 if (fInitialPowerChange
)
1846 computeDesire
= true;
1847 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1848 fParentsCurrentPowerFlags
);
1850 else if (parentChangeFlags
& kIOPMRootChangeUp
)
1852 if (fAdvisoryTickleUsed
)
1854 // On system wake, re-compute the desired power state since
1855 // gIOPMAdvisoryTickleEnabled will change for a full wake,
1856 // which is an input to computeDesiredState(). This is not
1857 // necessary for a dark wake because powerChangeDone() will
1858 // handle the dark to full wake case, but it does no harm.
1860 desireChanged
= true;
1863 if (fResetPowerStateOnWake
)
1865 // Query the driver for the desired power state on system wake.
1866 // Default implementation returns the lowest power state.
1868 IOPMPowerStateIndex wakePowerState
=
1869 fControllingDriver
->initialPowerStateForDomainState(
1870 kIOPMRootDomainState
| kIOPMPowerOn
);
1872 // fDesiredPowerState was adjusted before going to sleep
1873 // with fDeviceDesire at min.
1875 if (StateOrder(wakePowerState
) > StateOrder(fDesiredPowerState
))
1877 // Must schedule a power adjustment if we changed the
1878 // device desire. That will update the desired domain
1879 // power on the parent power connection and ping the
1880 // power parent if necessary.
1882 updatePowerClient(gIOPMPowerClientDevice
, wakePowerState
);
1883 desireChanged
= true;
1888 if (computeDesire
|| desireChanged
)
1889 computeDesiredState(initialDesire
, false);
1891 // Absorb and propagate parent's broadcast flags
1892 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1893 (parentChangeFlags
& kIOPMRootBroadcastFlags
);
1895 result
= startPowerChange(
1896 /* flags */ myChangeFlags
,
1897 /* power state */ maxPowerState
,
1898 /* domain flags */ fParentsCurrentPowerFlags
,
1899 /* connection */ whichParent
,
1900 /* parent flags */ 0);
1903 // Parent is expecting an ACK from us. If we did not embark on a state
1904 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1905 // still required to issue an ACK to our parent.
1907 if (IOPMAckImplied
== result
)
1910 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1914 parent
->acknowledgePowerChange( whichParent
);
1919 // If the parent registers its power driver late, then this is the
1920 // first opportunity to tell our parent about our desire. Or if the
1921 // child's desire changed during a parent change notify.
1923 if (fControllingDriver
&&
1924 ((!savedParentsKnowState
&& fParentsKnowState
) || desireChanged
))
1926 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState %d\n",
1927 getName(), fParentsKnowState
);
1928 requestDomainPower( fDesiredPowerState
);
1932 // Drop the retain from notifyChild().
1933 if (whichParent
) whichParent
->release();
1936 //*********************************************************************************
1937 // [private] setParentInfo
1939 // Set our connection data for one specific parent, and then combine all the parent
1941 //*********************************************************************************
1943 void IOService::setParentInfo(
1944 IOPMPowerFlags newPowerFlags
,
1945 IOPowerConnection
* whichParent
,
1950 IOPowerConnection
* conn
;
1952 PM_ASSERT_IN_GATE();
1954 // set our connection data
1955 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
1956 whichParent
->setParentKnowsState(knowsState
);
1958 // recompute our parent info
1959 fParentsCurrentPowerFlags
= 0;
1960 fParentsKnowState
= true;
1962 iter
= getParentIterator(gIOPowerPlane
);
1965 while ( (next
= iter
->getNextObject()) )
1967 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
1969 fParentsKnowState
&= conn
->parentKnowsState();
1970 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
1977 //******************************************************************************
1978 // [private] trackSystemSleepPreventers
1979 //******************************************************************************
1981 void IOService::trackSystemSleepPreventers(
1982 IOPMPowerStateIndex oldPowerState
,
1983 IOPMPowerStateIndex newPowerState
,
1984 IOPMPowerChangeFlags changeFlags __unused
)
1986 IOPMPowerFlags oldCapability
, newCapability
;
1988 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
1989 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1990 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
1991 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1993 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)
1995 if (oldCapability
== newCapability
)
1998 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
)
2000 bool enablePrevention
= ((oldCapability
& kIOPMPreventIdleSleep
) == 0);
2001 bool idleCancelAllowed
= getPMRootDomain()->updatePreventIdleSleepList(
2002 this, enablePrevention
);
2003 #if SUPPORT_IDLE_CANCEL
2004 if (idleCancelAllowed
&& enablePrevention
)
2006 IOPMRequest
* cancelRequest
;
2008 cancelRequest
= acquirePMRequest( getPMRootDomain(), kIOPMRequestTypeIdleCancel
);
2011 submitPMRequest( cancelRequest
);
2017 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
)
2019 getPMRootDomain()->updatePreventSystemSleepList(this,
2020 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2024 //*********************************************************************************
2025 // [public] requestPowerDomainState
2027 // Called on a power parent when a child's power requirement changes.
2028 //*********************************************************************************
2030 IOReturn
IOService::requestPowerDomainState(
2031 IOPMPowerFlags childRequestPowerFlags
,
2032 IOPowerConnection
* childConnection
,
2033 unsigned long specification
)
2035 IOPMPowerStateIndex order
, powerState
;
2036 IOPMPowerFlags outputPowerFlags
;
2038 IOPMRequest
* subRequest
;
2039 bool adjustPower
= false;
2042 return IOPMNotYetInitialized
;
2044 if (gIOPMWorkLoop
->onThread() == false)
2046 PM_LOG("%s::requestPowerDomainState\n", getName());
2047 return kIOReturnSuccess
;
2050 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2052 if (!isChild(childConnection
, gIOPowerPlane
))
2053 return kIOReturnNotAttached
;
2055 if (!fControllingDriver
|| !fNumberOfPowerStates
)
2056 return kIOReturnNotReady
;
2058 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2061 // Remove flags from child request which we can't possibly supply
2062 childRequestPowerFlags
&= fMergedOutputPowerFlags
;
2064 // Merge in the power flags contributed by this power parent
2065 // at its current or impending power state.
2067 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2068 if (fMachineState
!= kIOPM_Finished
)
2070 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
)
2072 // Use the lower power state when dropping power.
2073 // Must be careful since a power drop can be cancelled
2074 // from the following states:
2075 // - kIOPM_OurChangeTellClientsPowerDown
2076 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2078 // The child must not wait for this parent to raise power
2079 // if the power drop was cancelled. The solution is to cancel
2080 // the power drop if possible, then schedule an adjustment to
2081 // re-evaluate the parent's power state.
2083 // Root domain is excluded to avoid idle sleep issues. And allow
2084 // root domain children to pop up when system is going to sleep.
2086 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2087 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
2089 fDoNotPowerDown
= true; // cancel power drop
2090 adjustPower
= true; // schedule an adjustment
2091 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2092 getName(), fMachineState
, child
->getName());
2096 // Beyond cancellation point, report the impending state.
2098 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2101 else if (IS_POWER_RISE
)
2103 // When raising power, must report the output power flags from
2104 // child's perspective. A child power request may arrive while
2105 // parent is transitioning upwards. If a request arrives after
2106 // setParentInfo() has already recorded the output power flags
2107 // for the next power state, then using the power supplied by
2108 // fCurrentPowerState is incorrect, and might cause the child
2109 // to wait when it should not.
2111 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2114 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2116 // Map child's requested power flags to one of our power state.
2118 for (order
= 0; order
< fNumberOfPowerStates
; order
++)
2120 powerState
= fPowerStates
[order
].stateOrderToIndex
;
2121 if ((fPowerStates
[powerState
].outputPowerFlags
& childRequestPowerFlags
)
2122 == childRequestPowerFlags
)
2125 if (order
>= fNumberOfPowerStates
)
2127 powerState
= kPowerStateZero
;
2130 // Conditions that warrants a power adjustment on this parent.
2131 // Adjust power will also propagate any changes to the child's
2132 // prevent idle/sleep flags towards the root domain.
2134 if (!childConnection
->childHasRequestedPower() ||
2135 (powerState
!= childConnection
->getDesiredDomainState()))
2138 #if ENABLE_DEBUG_LOGS
2141 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2142 getName(), child
->getName(),
2143 !childConnection
->childHasRequestedPower(),
2144 (uint32_t) childConnection
->getDesiredDomainState(),
2145 (uint32_t) powerState
);
2149 // Record the child's desires on the connection.
2150 childConnection
->setChildHasRequestedPower();
2151 childConnection
->setDesiredDomainState( powerState
);
2153 // Schedule a request to re-evaluate all children desires and
2154 // adjust power state. Submit a request if one wasn't pending,
2155 // or if the current request is part of a call tree.
2157 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2158 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest()))
2160 subRequest
= acquirePMRequest(
2161 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2164 submitPMRequest( subRequest
);
2165 fAdjustPowerScheduled
= true;
2169 return kIOReturnSuccess
;
2172 //*********************************************************************************
2173 // [public] temporaryPowerClampOn
2175 // A power domain wants to clamp its power on till it has children which
2176 // will thendetermine the power domain state.
2178 // We enter the highest state until addPowerChild is called.
2179 //*********************************************************************************
2181 IOReturn
IOService::temporaryPowerClampOn( void )
2183 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2186 //*********************************************************************************
2187 // [public] makeUsable
2189 // Some client of our device is asking that we become usable. Although
2190 // this has not come from a subclassed device object, treat it exactly
2191 // as if it had. In this way, subsequent requests for lower power from
2192 // a subclassed device object will pre-empt this request.
2194 // We treat this as a subclass object request to switch to the
2195 // highest power state.
2196 //*********************************************************************************
2198 IOReturn
IOService::makeUsable( void )
2200 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2201 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2204 //*********************************************************************************
2205 // [public] currentCapability
2206 //*********************************************************************************
2208 IOPMPowerFlags
IOService::currentCapability( void )
2211 return IOPMNotPowerManaged
;
2213 return fCurrentCapabilityFlags
;
2216 //*********************************************************************************
2217 // [public] changePowerStateTo
2219 // Called by our power-controlling driver to change power state. The new desired
2220 // power state is computed and compared against the current power state. If those
2221 // power states differ, then a power state change is initiated.
2222 //*********************************************************************************
2224 IOReturn
IOService::changePowerStateTo( unsigned long ordinal
)
2226 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2227 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2230 //*********************************************************************************
2231 // [protected] changePowerStateToPriv
2233 // Called by our driver subclass to change power state. The new desired power
2234 // state is computed and compared against the current power state. If those
2235 // power states differ, then a power state change is initiated.
2236 //*********************************************************************************
2238 IOReturn
IOService::changePowerStateToPriv( unsigned long ordinal
)
2240 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2241 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2244 //*********************************************************************************
2245 // [public] changePowerStateWithOverrideTo
2247 // Called by our driver subclass to change power state. The new desired power
2248 // state is computed and compared against the current power state. If those
2249 // power states differ, then a power state change is initiated.
2250 // Override enforced - Children and Driver desires are ignored.
2251 //*********************************************************************************
2253 IOReturn
IOService::changePowerStateWithOverrideTo( IOPMPowerStateIndex ordinal
,
2254 IOPMRequestTag tag
)
2256 IOPMRequest
* request
;
2259 return kIOPMNotYetInitialized
;
2261 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2263 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2265 return kIOReturnNoMemory
;
2267 gIOPMPowerClientDevice
->retain();
2268 request
->fRequestTag
= tag
;
2269 request
->fArg0
= (void *) ordinal
;
2270 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2274 request
->installCompletionAction( action
, target
, param
);
2277 // Prevent needless downwards power transitions by clamping power
2278 // until the scheduled request is executed.
2280 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
))
2282 fTempClampPowerState
= StateMax(fTempClampPowerState
, ordinal
);
2284 fOverrideMaxPowerState
= ordinal
;
2285 request
->fArg2
= (void *) (uintptr_t) true;
2288 submitPMRequest( request
);
2292 //*********************************************************************************
2293 // [public] changePowerStateForRootDomain
2295 // Adjust the root domain's power desire on the target
2296 //*********************************************************************************
2298 IOReturn
IOService::changePowerStateForRootDomain( IOPMPowerStateIndex ordinal
)
2300 OUR_PMLog(kPMLogChangeStateForRootDomain
, ordinal
, 0);
2301 return requestPowerState( gIOPMPowerClientRootDomain
, ordinal
);
2304 //*********************************************************************************
2305 // [private] requestPowerState
2306 //*********************************************************************************
2308 IOReturn
IOService::requestPowerState(
2309 const OSSymbol
* client
,
2312 IOPMRequest
* request
;
2315 return kIOReturnBadArgument
;
2317 return kIOPMNotYetInitialized
;
2319 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2321 return kIOReturnNoMemory
;
2324 request
->fArg0
= (void *)(uintptr_t) state
;
2325 request
->fArg1
= (void *) client
;
2329 request
->installCompletionAction( action
, target
, param
);
2332 // Prevent needless downwards power transitions by clamping power
2333 // until the scheduled request is executed.
2335 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
))
2337 fTempClampPowerState
= StateMax(fTempClampPowerState
, state
);
2339 request
->fArg2
= (void *) (uintptr_t) true;
2342 submitPMRequest( request
);
2346 //*********************************************************************************
2347 // [private] handleRequestPowerState
2348 //*********************************************************************************
2350 void IOService::handleRequestPowerState( IOPMRequest
* request
)
2352 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2353 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2355 PM_ASSERT_IN_GATE();
2358 assert(fTempClampCount
!= 0);
2359 if (fTempClampCount
) fTempClampCount
--;
2360 if (!fTempClampCount
) fTempClampPowerState
= kPowerStateZero
;
2363 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
))
2364 state
= fHighestPowerState
;
2366 // The power suppression due to changePowerStateWithOverrideTo() expires
2367 // upon the next "device" power request - changePowerStateToPriv().
2369 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2370 (client
== gIOPMPowerClientDevice
))
2371 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2373 if ((state
== kPowerStateZero
) &&
2374 (client
!= gIOPMPowerClientDevice
) &&
2375 (client
!= gIOPMPowerClientDriver
) &&
2376 (client
!= gIOPMPowerClientChildProxy
))
2377 removePowerClient(client
);
2379 updatePowerClient(client
, state
);
2385 //*********************************************************************************
2386 // [private] Helper functions to update/remove power clients.
2387 //*********************************************************************************
2389 void IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2391 IOPMPowerStateIndex oldPowerState
= kPowerStateZero
;
2394 fPowerClients
= OSDictionary::withCapacity(4);
2395 if (fPowerClients
&& client
)
2397 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2400 oldPowerState
= num
->unsigned32BitValue();
2401 num
->setValue(powerState
);
2405 num
= OSNumber::withNumber(powerState
, 32);
2408 fPowerClients
->setObject(client
, num
);
2413 PM_ACTION_3(actionUpdatePowerClient
, client
, oldPowerState
, powerState
);
2417 void IOService::removePowerClient( const OSSymbol
* client
)
2419 if (fPowerClients
&& client
)
2420 fPowerClients
->removeObject(client
);
2423 uint32_t IOService::getPowerStateForClient( const OSSymbol
* client
)
2425 uint32_t powerState
= kPowerStateZero
;
2427 if (fPowerClients
&& client
)
2429 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2430 if (num
) powerState
= num
->unsigned32BitValue();
2435 //*********************************************************************************
2436 // [protected] powerOverrideOnPriv
2437 //*********************************************************************************
2439 IOReturn
IOService::powerOverrideOnPriv( void )
2441 IOPMRequest
* request
;
2444 return IOPMNotYetInitialized
;
2446 if (gIOPMWorkLoop
->inGate())
2448 fDeviceOverrideEnabled
= true;
2452 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2454 return kIOReturnNoMemory
;
2456 submitPMRequest( request
);
2460 //*********************************************************************************
2461 // [protected] powerOverrideOffPriv
2462 //*********************************************************************************
2464 IOReturn
IOService::powerOverrideOffPriv( void )
2466 IOPMRequest
* request
;
2469 return IOPMNotYetInitialized
;
2471 if (gIOPMWorkLoop
->inGate())
2473 fDeviceOverrideEnabled
= false;
2477 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2479 return kIOReturnNoMemory
;
2481 submitPMRequest( request
);
2485 //*********************************************************************************
2486 // [private] handlePowerOverrideChanged
2487 //*********************************************************************************
2489 void IOService::handlePowerOverrideChanged( IOPMRequest
* request
)
2491 PM_ASSERT_IN_GATE();
2492 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
)
2494 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2495 fDeviceOverrideEnabled
= true;
2499 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2500 fDeviceOverrideEnabled
= false;
2506 //*********************************************************************************
2507 // [private] computeDesiredState
2508 //*********************************************************************************
2510 void IOService::computeDesiredState( unsigned long localClamp
, bool computeOnly
)
2514 IOPowerConnection
* connection
;
2515 uint32_t desiredState
= kPowerStateZero
;
2516 uint32_t newPowerState
= kPowerStateZero
;
2517 bool hasChildren
= false;
2519 // Desired power state is always 0 without a controlling driver.
2521 if (!fNumberOfPowerStates
)
2523 fDesiredPowerState
= kPowerStateZero
;
2527 // Examine the children's desired power state.
2529 iter
= getChildIterator(gIOPowerPlane
);
2532 while ((next
= iter
->getNextObject()))
2534 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
2536 if (connection
->getReadyFlag() == false)
2538 PM_LOG3("[%s] %s: connection not ready\n",
2539 getName(), __FUNCTION__
);
2542 if (connection
->childHasRequestedPower())
2544 desiredState
= StateMax(connection
->getDesiredDomainState(), desiredState
);
2550 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2552 removePowerClient(gIOPMPowerClientChildren
);
2554 // Iterate through all power clients to determine the min power state.
2556 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2559 const OSSymbol
* client
;
2560 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
2562 // Ignore child and driver when override is in effect.
2563 if ((fDeviceOverrideEnabled
||
2564 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2565 ((client
== gIOPMPowerClientChildren
) ||
2566 (client
== gIOPMPowerClientDriver
)))
2569 // Ignore child proxy when children are present.
2570 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
))
2573 // Advisory tickles are irrelevant unless system is in full wake
2574 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2575 !gIOPMAdvisoryTickleEnabled
)
2578 desiredState
= getPowerStateForClient(client
);
2579 assert(desiredState
< fNumberOfPowerStates
);
2581 desiredState
, client
->getCStringNoCopy());
2583 newPowerState
= StateMax(newPowerState
, desiredState
);
2585 if (client
== gIOPMPowerClientDevice
)
2586 fDeviceDesire
= desiredState
;
2591 // Factor in the temporary power desires.
2593 newPowerState
= StateMax(newPowerState
, localClamp
);
2594 newPowerState
= StateMax(newPowerState
, fTempClampPowerState
);
2596 // Limit check against max power override.
2598 newPowerState
= StateMin(newPowerState
, fOverrideMaxPowerState
);
2600 // Limit check against number of power states.
2602 if (newPowerState
>= fNumberOfPowerStates
)
2603 newPowerState
= fHighestPowerState
;
2605 fDesiredPowerState
= newPowerState
;
2607 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2608 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2609 (uint32_t) fCurrentPowerState
, newPowerState
);
2613 // Restart idle timer if possible when device desire has increased.
2614 // Or if an advisory desire exists.
2616 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
2621 // Invalidate cached tickle power state when desires change, and not
2622 // due to a tickle request. In case the driver has requested a lower
2623 // power state, but the tickle is caching a higher power state which
2624 // will drop future tickles until the cached value is lowered or in-
2625 // validated. The invalidation must occur before the power transition
2626 // to avoid dropping a necessary tickle.
2628 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2629 (fActivityTicklePowerState
!= kInvalidTicklePowerState
))
2631 IOLockLock(fActivityLock
);
2632 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2633 IOLockUnlock(fActivityLock
);
2638 //*********************************************************************************
2639 // [public] currentPowerConsumption
2641 //*********************************************************************************
2643 unsigned long IOService::currentPowerConsumption( void )
2646 return kIOPMUnknown
;
2648 return fCurrentPowerConsumption
;
2651 //*********************************************************************************
2652 // [deprecated] getPMworkloop
2653 //*********************************************************************************
2655 IOWorkLoop
* IOService::getPMworkloop( void )
2657 return gIOPMWorkLoop
;
2662 //*********************************************************************************
2663 // Power Parent/Children Applier
2664 //*********************************************************************************
2667 applyToPowerChildren(
2668 IOService
* service
,
2669 IOServiceApplierFunction applier
,
2671 IOOptionBits options
)
2673 PM_ASSERT_IN_GATE();
2675 IORegistryEntry
* entry
;
2676 IORegistryIterator
* iter
;
2677 IOPowerConnection
* connection
;
2680 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2683 while ((entry
= iter
->getNextObject()))
2685 // Get child of IOPowerConnection objects
2686 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2688 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2691 (*applier
)(child
, context
);
2702 IOService
* service
,
2703 IOServiceApplierFunction applier
,
2705 IOOptionBits options
)
2707 PM_ASSERT_IN_GATE();
2709 IORegistryEntry
* entry
;
2710 IORegistryIterator
* iter
;
2711 IOPowerConnection
* connection
;
2714 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2715 options
| kIORegistryIterateParents
);
2718 while ((entry
= iter
->getNextObject()))
2720 // Get child of IOPowerConnection objects
2721 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2723 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2726 (*applier
)(parent
, context
);
2735 #endif /* NOT_YET */
2738 // MARK: Activity Tickle & Idle Timer
2740 void IOService::setAdvisoryTickleEnable( bool enable
)
2742 gIOPMAdvisoryTickleEnabled
= enable
;
2745 //*********************************************************************************
2746 // [public] activityTickle
2748 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2749 // flag to be set, and the device state checked. If the device has been
2750 // powered down, it is powered up again.
2751 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2752 // should be intercepted by a subclass.
2753 //*********************************************************************************
2755 bool IOService::activityTickle( unsigned long type
, unsigned long stateNumber
)
2757 IOPMRequest
* request
;
2758 bool noPowerChange
= true;
2759 uint32_t tickleFlags
;
2762 return true; // no power change
2764 if ((type
== kIOPMSuperclassPolicy1
) && StateOrder(stateNumber
))
2766 IOLockLock(fActivityLock
);
2768 // Record device activity for the idle timer handler.
2770 fDeviceWasActive
= true;
2771 fActivityTickleCount
++;
2772 clock_get_uptime(&fDeviceActiveTimestamp
);
2774 PM_ACTION_0(actionActivityTickle
);
2776 // Record the last tickle power state.
2777 // This helps to filter out redundant tickles as
2778 // this function may be called from the data path.
2780 if ((fActivityTicklePowerState
== kInvalidTicklePowerState
)
2781 || StateOrder(fActivityTicklePowerState
) < StateOrder(stateNumber
))
2783 fActivityTicklePowerState
= stateNumber
;
2784 noPowerChange
= false;
2786 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerRise
;
2787 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2790 request
->fArg0
= (void *) stateNumber
;
2791 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2792 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2793 submitPMRequest(request
);
2797 IOLockUnlock(fActivityLock
);
2800 else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2801 ((stateNumber
= fDeviceUsablePowerState
) != kPowerStateZero
))
2803 IOLockLock(fActivityLock
);
2805 fAdvisoryTickled
= true;
2807 if (fAdvisoryTicklePowerState
!= stateNumber
)
2809 fAdvisoryTicklePowerState
= stateNumber
;
2810 noPowerChange
= false;
2812 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerRise
;
2813 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2816 request
->fArg0
= (void *) stateNumber
;
2817 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
2818 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
2819 submitPMRequest(request
);
2823 IOLockUnlock(fActivityLock
);
2826 // Returns false if the activityTickle might cause a transition to a
2827 // higher powered state, true otherwise.
2829 return noPowerChange
;
2832 //*********************************************************************************
2833 // [private] handleActivityTickle
2834 //*********************************************************************************
2836 void IOService::handleActivityTickle( IOPMRequest
* request
)
2838 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2839 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
2840 uint32_t tickleGeneration
= (uint32_t)(uintptr_t) request
->fArg2
;
2841 bool adjustPower
= false;
2843 PM_ASSERT_IN_GATE();
2844 if (fResetPowerStateOnWake
&& (tickleGeneration
!= gIOPMTickleGeneration
))
2846 // Drivers that don't want power restored on wake will drop any
2847 // tickles that pre-dates the current system wake. The model is
2848 // that each wake is a fresh start, with power state depressed
2849 // until a new tickle or an explicit power up request from the
2850 // driver. It is possible for the PM work loop to enter the
2851 // system sleep path with tickle requests queued.
2856 if (tickleFlags
& kTickleTypeActivity
)
2858 IOPMPowerStateIndex deviceDesireOrder
= StateOrder(fDeviceDesire
);
2859 uint32_t idleTimerGeneration
= ticklePowerState
; // kTickleTypePowerDrop
2861 if (tickleFlags
& kTickleTypePowerRise
)
2863 if ((StateOrder(ticklePowerState
) > deviceDesireOrder
) &&
2864 (ticklePowerState
< fNumberOfPowerStates
))
2866 fIdleTimerMinPowerState
= ticklePowerState
;
2867 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2871 else if ((deviceDesireOrder
> StateOrder(fIdleTimerMinPowerState
)) &&
2872 (idleTimerGeneration
== fIdleTimerGeneration
))
2874 // Power drop due to idle timer expiration.
2875 // Do not allow idle timer to reduce power below tickle power.
2876 // This prevents the idle timer from decreasing the device desire
2877 // to zero and cancelling the effect of a pre-sleep tickle when
2878 // system wakes up to doze state, while the device is unable to
2879 // raise its power state to satisfy the tickle.
2881 deviceDesireOrder
--;
2882 if (deviceDesireOrder
< fNumberOfPowerStates
)
2884 ticklePowerState
= fPowerStates
[deviceDesireOrder
].stateOrderToIndex
;
2885 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2890 else // advisory tickle
2892 if (tickleFlags
& kTickleTypePowerRise
)
2894 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
2895 (ticklePowerState
< fNumberOfPowerStates
))
2897 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
2898 fHasAdvisoryDesire
= true;
2899 fAdvisoryTickleUsed
= true;
2904 IOLockLock(fActivityLock
);
2905 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
2906 IOLockUnlock(fActivityLock
);
2909 else if (fHasAdvisoryDesire
)
2911 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
2912 fHasAdvisoryDesire
= false;
2923 //******************************************************************************
2924 // [public] setIdleTimerPeriod
2926 // A subclass policy-maker is using our standard idleness detection service.
2927 // Start the idle timer. Period is in seconds.
2928 //******************************************************************************
2930 IOReturn
IOService::setIdleTimerPeriod( unsigned long period
)
2933 return IOPMNotYetInitialized
;
2935 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
2937 IOPMRequest
* request
=
2938 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
2940 return kIOReturnNoMemory
;
2942 request
->fArg0
= (void *) period
;
2943 submitPMRequest( request
);
2945 return kIOReturnSuccess
;
2948 IOReturn
IOService::setIgnoreIdleTimer( bool ignore
)
2951 return IOPMNotYetInitialized
;
2953 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
2955 IOPMRequest
* request
=
2956 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
2958 return kIOReturnNoMemory
;
2960 request
->fArg0
= (void *) ignore
;
2961 submitPMRequest( request
);
2963 return kIOReturnSuccess
;
2966 //******************************************************************************
2967 // [public] nextIdleTimeout
2969 // Returns how many "seconds from now" the device should idle into its
2970 // next lowest power state.
2971 //******************************************************************************
2973 SInt32
IOService::nextIdleTimeout(
2974 AbsoluteTime currentTime
,
2975 AbsoluteTime lastActivity
,
2976 unsigned int powerState
)
2983 // Calculate time difference using funky macro from clock.h.
2984 delta
= currentTime
;
2985 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
2987 // Figure it in seconds.
2988 absolutetime_to_nanoseconds(delta
, &delta_ns
);
2989 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
2991 // Be paranoid about delta somehow exceeding timer period.
2992 if (delta_secs
< (int) fIdleTimerPeriod
)
2993 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
2995 delay_secs
= (int) fIdleTimerPeriod
;
2997 return (SInt32
)delay_secs
;
3000 //*********************************************************************************
3001 // [public] start_PM_idle_timer
3002 //*********************************************************************************
3004 void IOService::start_PM_idle_timer( void )
3006 static const int maxTimeout
= 100000;
3007 static const int minTimeout
= 1;
3008 AbsoluteTime uptime
, deadline
;
3012 if (!initialized
|| !fIdleTimerPeriod
)
3015 IOLockLock(fActivityLock
);
3017 clock_get_uptime(&uptime
);
3019 // Subclasses may modify idle sleep algorithm
3020 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3022 // Check for out-of range responses
3023 if (idle_in
> maxTimeout
)
3025 // use standard implementation
3026 idle_in
= IOService::nextIdleTimeout(uptime
,
3027 fDeviceActiveTimestamp
,
3028 fCurrentPowerState
);
3029 } else if (idle_in
< minTimeout
) {
3030 idle_in
= fIdleTimerPeriod
;
3033 IOLockUnlock(fActivityLock
);
3035 fNextIdleTimerPeriod
= idle_in
;
3036 fIdleTimerStartTime
= uptime
;
3039 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3040 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3041 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3042 if (pending
) release();
3045 //*********************************************************************************
3046 // [private] restartIdleTimer
3047 //*********************************************************************************
3049 void IOService::restartIdleTimer( void )
3051 if (fDeviceDesire
!= kPowerStateZero
)
3053 fIdleTimerStopped
= false;
3054 fActivityTickleCount
= 0;
3055 start_PM_idle_timer();
3057 else if (fHasAdvisoryDesire
)
3059 fIdleTimerStopped
= false;
3060 start_PM_idle_timer();
3064 fIdleTimerStopped
= true;
3068 //*********************************************************************************
3069 // idle_timer_expired
3070 //*********************************************************************************
3074 thread_call_param_t arg0
, thread_call_param_t arg1
)
3076 IOService
* me
= (IOService
*) arg0
;
3079 gIOPMWorkLoop
->runAction(
3080 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3081 &IOService::idleTimerExpired
),
3087 //*********************************************************************************
3088 // [private] idleTimerExpired
3090 // The idle timer has expired. If there has been activity since the last
3091 // expiration, just restart the timer and return. If there has not been
3092 // activity, switch to the next lower power state and restart the timer.
3093 //*********************************************************************************
3095 void IOService::idleTimerExpired( void )
3097 IOPMRequest
* request
;
3098 bool restartTimer
= true;
3099 uint32_t tickleFlags
;
3101 if ( !initialized
|| !fIdleTimerPeriod
|| fIdleTimerStopped
||
3102 fLockedFlags
.PMStop
)
3105 fIdleTimerStartTime
= 0;
3107 IOLockLock(fActivityLock
);
3109 // Check for device activity (tickles) over last timer period.
3111 if (fDeviceWasActive
)
3113 // Device was active - do not drop power, restart timer.
3114 fDeviceWasActive
= false;
3116 else if (!fIdleTimerIgnored
)
3118 // No device activity - drop power state by one level.
3119 // Decrement the cached tickle power state when possible.
3120 // This value may be kInvalidTicklePowerState before activityTickle()
3121 // is called, but the power drop request must be issued regardless.
3123 if ((fActivityTicklePowerState
!= kInvalidTicklePowerState
) &&
3124 (fActivityTicklePowerState
!= kPowerStateZero
))
3125 fActivityTicklePowerState
--;
3127 tickleFlags
= kTickleTypeActivity
| kTickleTypePowerDrop
;
3128 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3131 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3132 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3133 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3134 submitPMRequest( request
);
3136 // Do not restart timer until after the tickle request has been
3139 restartTimer
= false;
3143 if (fAdvisoryTickled
)
3145 fAdvisoryTickled
= false;
3147 else if (fHasAdvisoryDesire
)
3149 // Want new tickles to turn into pm request after we drop the lock
3150 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3152 tickleFlags
= kTickleTypeAdvisory
| kTickleTypePowerDrop
;
3153 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3156 request
->fArg0
= (void *)(uintptr_t) fIdleTimerGeneration
;
3157 request
->fArg1
= (void *)(uintptr_t) tickleFlags
;
3158 request
->fArg2
= (void *)(uintptr_t) gIOPMTickleGeneration
;
3159 submitPMRequest( request
);
3161 // Do not restart timer until after the tickle request has been
3164 restartTimer
= false;
3168 IOLockUnlock(fActivityLock
);
3171 start_PM_idle_timer();
3175 //*********************************************************************************
3176 // [deprecated] PM_idle_timer_expiration
3177 //*********************************************************************************
3179 void IOService::PM_idle_timer_expiration( void )
3183 //*********************************************************************************
3184 // [deprecated] command_received
3185 //*********************************************************************************
3187 void IOService::command_received( void *statePtr
, void *, void * , void * )
3190 #endif /* !__LP64__ */
3192 //*********************************************************************************
3193 // [public] setAggressiveness
3195 // Pass on the input parameters to all power domain children. All those which are
3196 // power domains will pass it on to their children, etc.
3197 //*********************************************************************************
3199 IOReturn
IOService::setAggressiveness( unsigned long type
, unsigned long newLevel
)
3201 return kIOReturnSuccess
;
3204 //*********************************************************************************
3205 // [public] getAggressiveness
3207 // Called by the user client.
3208 //*********************************************************************************
3210 IOReturn
IOService::getAggressiveness( unsigned long type
, unsigned long * currentLevel
)
3212 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3215 return kIOReturnNotReady
;
3217 return rootDomain
->getAggressiveness( type
, currentLevel
);
3220 //*********************************************************************************
3221 // [public] getPowerState
3223 //*********************************************************************************
3225 UInt32
IOService::getPowerState( void )
3228 return kPowerStateZero
;
3230 return fCurrentPowerState
;
3234 //*********************************************************************************
3235 // [deprecated] systemWake
3237 // Pass this to all power domain children. All those which are
3238 // power domains will pass it on to their children, etc.
3239 //*********************************************************************************
3241 IOReturn
IOService::systemWake( void )
3245 IOPowerConnection
* connection
;
3246 IOService
* theChild
;
3248 iter
= getChildIterator(gIOPowerPlane
);
3251 while ( (next
= iter
->getNextObject()) )
3253 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
3255 if (connection
->getReadyFlag() == false)
3257 PM_LOG3("[%s] %s: connection not ready\n",
3258 getName(), __FUNCTION__
);
3262 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3265 theChild
->systemWake();
3266 theChild
->release();
3273 if ( fControllingDriver
!= NULL
)
3275 if ( fControllingDriver
->didYouWakeSystem() )
3284 //*********************************************************************************
3285 // [deprecated] temperatureCriticalForZone
3286 //*********************************************************************************
3288 IOReturn
IOService::temperatureCriticalForZone( IOService
* whichZone
)
3290 IOService
* theParent
;
3293 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3295 if ( inPlane(gIOPowerPlane
) && !IS_PM_ROOT
)
3297 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3300 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3304 theParent
->temperatureCriticalForZone(whichZone
);
3305 theParent
->release();
3311 #endif /* !__LP64__ */
3314 // MARK: Power Change (Common)
3316 //*********************************************************************************
3317 // [private] startPowerChange
3319 // All power state changes starts here.
3320 //*********************************************************************************
3322 IOReturn
IOService::startPowerChange(
3323 IOPMPowerChangeFlags changeFlags
,
3324 IOPMPowerStateIndex powerState
,
3325 IOPMPowerFlags domainFlags
,
3326 IOPowerConnection
* parentConnection
,
3327 IOPMPowerFlags parentFlags
)
3329 PM_ASSERT_IN_GATE();
3330 assert( fMachineState
== kIOPM_Finished
);
3331 assert( powerState
< fNumberOfPowerStates
);
3333 if (powerState
>= fNumberOfPowerStates
)
3334 return IOPMAckImplied
;
3336 fIsPreChange
= true;
3337 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3339 if (changeFlags
& kIOPMExpireIdleTimer
)
3341 // Root domain requested removal of tickle influence
3342 if (StateOrder(fDeviceDesire
) > StateOrder(powerState
))
3344 // Reset device desire down to the clamped power state
3345 updatePowerClient(gIOPMPowerClientDevice
, powerState
);
3346 computeDesiredState(kPowerStateZero
, true);
3348 // Invalidate tickle cache so the next tickle will issue a request
3349 IOLockLock(fActivityLock
);
3350 fDeviceWasActive
= false;
3351 fActivityTicklePowerState
= kInvalidTicklePowerState
;
3352 IOLockUnlock(fActivityLock
);
3354 fIdleTimerMinPowerState
= kPowerStateZero
;
3358 // Root domain's override handler may cancel the power change by
3359 // setting the kIOPMNotDone flag.
3361 if (changeFlags
& kIOPMNotDone
)
3362 return IOPMAckImplied
;
3364 // Forks to either Driver or Parent initiated power change paths.
3366 fHeadNoteChangeFlags
= changeFlags
;
3367 fHeadNotePowerState
= powerState
;
3368 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
3369 fHeadNoteParentConnection
= NULL
;
3371 if (changeFlags
& kIOPMSelfInitiated
)
3373 if (changeFlags
& kIOPMSynchronize
)
3381 assert(changeFlags
& kIOPMParentInitiated
);
3382 fHeadNoteDomainFlags
= domainFlags
;
3383 fHeadNoteParentFlags
= parentFlags
;
3384 fHeadNoteParentConnection
= parentConnection
;
3385 return ParentChangeStart();
3389 //*********************************************************************************
3390 // [private] notifyInterestedDrivers
3391 //*********************************************************************************
3393 bool IOService::notifyInterestedDrivers( void )
3395 IOPMinformee
* informee
;
3396 IOPMinformeeList
* list
= fInterestedDrivers
;
3397 DriverCallParam
* param
;
3400 PM_ASSERT_IN_GATE();
3401 assert( fDriverCallParamCount
== 0 );
3402 assert( fHeadNotePendingAcks
== 0 );
3404 fHeadNotePendingAcks
= 0;
3406 count
= list
->numberOfItems();
3408 goto done
; // no interested drivers
3410 // Allocate an array of interested drivers and their return values
3411 // for the callout thread. Everything else is still "owned" by the
3412 // PM work loop, which can run to process acknowledgePowerChange()
3415 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3416 if (count
> fDriverCallParamSlots
)
3418 if (fDriverCallParamSlots
)
3420 assert(fDriverCallParamPtr
);
3421 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3422 fDriverCallParamPtr
= 0;
3423 fDriverCallParamSlots
= 0;
3426 param
= IONew(DriverCallParam
, count
);
3428 goto done
; // no memory
3430 fDriverCallParamPtr
= (void *) param
;
3431 fDriverCallParamSlots
= count
;
3434 informee
= list
->firstInList();
3436 for (IOItemCount i
= 0; i
< count
; i
++)
3438 informee
->timer
= -1;
3439 param
[i
].Target
= informee
;
3441 informee
= list
->nextInList( informee
);
3444 fDriverCallParamCount
= count
;
3445 fHeadNotePendingAcks
= count
;
3447 // Block state machine and wait for callout completion.
3448 assert(!fDriverCallBusy
);
3449 fDriverCallBusy
= true;
3450 thread_call_enter( fDriverCallEntry
);
3454 // Return false if there are no interested drivers or could not schedule
3455 // callout thread due to error.
3459 //*********************************************************************************
3460 // [private] notifyInterestedDriversDone
3461 //*********************************************************************************
3463 void IOService::notifyInterestedDriversDone( void )
3465 IOPMinformee
* informee
;
3467 DriverCallParam
* param
;
3470 PM_ASSERT_IN_GATE();
3471 assert( fDriverCallBusy
== false );
3472 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3474 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3475 count
= fDriverCallParamCount
;
3479 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3481 informee
= (IOPMinformee
*) param
->Target
;
3482 result
= param
->Result
;
3484 if ((result
== IOPMAckImplied
) || (result
< 0))
3486 // Interested driver return IOPMAckImplied.
3487 // If informee timer is zero, it must have de-registered
3488 // interest during the thread callout. That also drops
3489 // the pending ack count.
3491 if (fHeadNotePendingAcks
&& informee
->timer
)
3492 fHeadNotePendingAcks
--;
3494 informee
->timer
= 0;
3496 else if (informee
->timer
)
3498 assert(informee
->timer
== -1);
3500 // Driver has not acked, and has returned a positive result.
3501 // Enforce a minimum permissible timeout value.
3502 // Make the min value large enough so timeout is less likely
3503 // to occur if a driver misinterpreted that the return value
3504 // should be in microsecond units. And make it large enough
3505 // to be noticeable if a driver neglects to ack.
3507 if (result
< kMinAckTimeoutTicks
)
3508 result
= kMinAckTimeoutTicks
;
3510 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3512 // else, child has already acked or driver has removed interest,
3513 // and head_note_pendingAcks decremented.
3514 // informee may have been removed from the interested drivers list,
3515 // thus the informee must be retained across the callout.
3517 informee
->release();
3520 fDriverCallParamCount
= 0;
3522 if ( fHeadNotePendingAcks
)
3524 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3529 MS_POP(); // pop the machine state passed to notifyAll()
3531 // If interest acks are outstanding, block the state machine until
3532 // fHeadNotePendingAcks drops to zero before notifying root domain.
3533 // Otherwise notify root domain directly.
3535 if (!fHeadNotePendingAcks
)
3541 MS_PUSH(fMachineState
);
3542 fMachineState
= kIOPM_NotifyChildrenStart
;
3546 //*********************************************************************************
3547 // [private] notifyRootDomain
3548 //*********************************************************************************
3550 void IOService::notifyRootDomain( void )
3552 assert( fDriverCallBusy
== false );
3554 // Only for root domain in the will-change phase
3555 if (!IS_ROOT_DOMAIN
|| (fMachineState
!= kIOPM_OurChangeSetPowerState
))
3561 MS_PUSH(fMachineState
); // push notifyAll() machine state
3562 fMachineState
= kIOPM_DriverThreadCallDone
;
3564 // Call IOPMrootDomain::willNotifyPowerChildren() on a thread call
3565 // to avoid a deadlock.
3566 fDriverCallReason
= kRootDomainInformPreChange
;
3567 fDriverCallBusy
= true;
3568 thread_call_enter( fDriverCallEntry
);
3571 void IOService::notifyRootDomainDone( void )
3573 assert( fDriverCallBusy
== false );
3574 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3576 MS_POP(); // pop notifyAll() machine state
3580 //*********************************************************************************
3581 // [private] notifyChildren
3582 //*********************************************************************************
3584 void IOService::notifyChildren( void )
3588 IOPowerConnection
* connection
;
3589 OSArray
* children
= 0;
3590 IOPMrootDomain
* rootDomain
;
3591 bool delayNotify
= false;
3593 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3594 (IS_POWER_DROP
== fIsPreChange
) &&
3595 ((rootDomain
= getPMRootDomain()) == this))
3597 rootDomain
->tracePoint( IS_POWER_DROP
?
3598 kIOPMTracePointSleepPowerPlaneDrivers
:
3599 kIOPMTracePointWakePowerPlaneDrivers
);
3602 if (fStrictTreeOrder
)
3603 children
= OSArray::withCapacity(8);
3605 // Sum child power consumption in notifyChild()
3606 fHeadNotePowerArrayEntry
->staticPower
= 0;
3608 iter
= getChildIterator(gIOPowerPlane
);
3611 while ((next
= iter
->getNextObject()))
3613 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3615 if (connection
->getReadyFlag() == false)
3617 PM_LOG3("[%s] %s: connection not ready\n",
3618 getName(), __FUNCTION__
);
3622 // Mechanism to postpone the did-change notification to
3623 // certain power children to order those children last.
3624 // Cannot be used together with strict tree ordering.
3626 if (!fIsPreChange
&&
3627 connection
->delayChildNotification
&&
3628 getPMRootDomain()->shouldDelayChildNotification(this))
3632 children
= OSArray::withCapacity(8);
3638 children
->setObject( connection
);
3643 if (!delayNotify
&& children
)
3644 children
->setObject( connection
);
3646 notifyChild( connection
);
3652 if (children
&& (children
->getCount() == 0))
3654 children
->release();
3659 assert(fNotifyChildArray
== 0);
3660 fNotifyChildArray
= children
;
3661 MS_PUSH(fMachineState
);
3665 // Block until all non-delayed children have acked their
3666 // notification. Then notify the remaining delayed child
3667 // in the array. This is used to hold off graphics child
3668 // notification while the rest of the system powers up.
3669 // If a hid tickle arrives during this time, the delayed
3670 // children are immediately notified and root domain will
3671 // not clamp power for dark wake.
3673 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3674 PM_LOG2("%s: %d children in delayed array\n",
3675 getName(), children
->getCount());
3679 // Child array created to support strict notification order.
3680 // Notify children in the array one at a time.
3682 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3687 //*********************************************************************************
3688 // [private] notifyChildrenOrdered
3689 //*********************************************************************************
3691 void IOService::notifyChildrenOrdered( void )
3693 PM_ASSERT_IN_GATE();
3694 assert(fNotifyChildArray
);
3695 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3697 // Notify one child, wait for it to ack, then repeat for next child.
3698 // This is a workaround for some drivers with multiple instances at
3699 // the same branch in the power tree, but the driver is slow to power
3700 // up unless the tree ordering is observed. Problem observed only on
3701 // system wake, not on system sleep.
3703 // We have the ability to power off in reverse child index order.
3704 // That works nicely on some machines, but not on all HW configs.
3706 if (fNotifyChildArray
->getCount())
3708 IOPowerConnection
* connection
;
3709 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3710 notifyChild( connection
);
3711 fNotifyChildArray
->removeObject(0);
3715 fNotifyChildArray
->release();
3716 fNotifyChildArray
= 0;
3718 MS_POP(); // pushed by notifyChildren()
3722 //*********************************************************************************
3723 // [private] notifyChildrenDelayed
3724 //*********************************************************************************
3726 void IOService::notifyChildrenDelayed( void )
3728 IOPowerConnection
* connection
;
3730 PM_ASSERT_IN_GATE();
3731 assert(fNotifyChildArray
);
3732 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3734 // Wait after all non-delayed children and interested drivers have ack'ed,
3735 // then notify all delayed children. If notify delay is canceled, child
3736 // acks may be outstanding with PM blocked on fHeadNotePendingAcks != 0.
3737 // But the handling for either case is identical.
3739 for (int i
= 0; ; i
++)
3741 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3745 notifyChild( connection
);
3748 PM_LOG2("%s: notified delayed children\n", getName());
3749 fNotifyChildArray
->release();
3750 fNotifyChildArray
= 0;
3752 MS_POP(); // pushed by notifyChildren()
3755 //*********************************************************************************
3756 // [private] notifyAll
3757 //*********************************************************************************
3759 IOReturn
IOService::notifyAll( uint32_t nextMS
)
3761 // Save the machine state to be restored by notifyInterestedDriversDone()
3763 PM_ASSERT_IN_GATE();
3765 fMachineState
= kIOPM_DriverThreadCallDone
;
3766 fDriverCallReason
= fIsPreChange
?
3767 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3769 if (!notifyInterestedDrivers())
3770 notifyInterestedDriversDone();
3772 return IOPMWillAckLater
;
3775 //*********************************************************************************
3776 // [private, static] pmDriverCallout
3778 // Thread call context
3779 //*********************************************************************************
3781 IOReturn
IOService::actionDriverCalloutDone(
3783 void * arg0
, void * arg1
,
3784 void * arg2
, void * arg3
)
3786 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3788 assert( fDriverCallBusy
);
3789 fDriverCallBusy
= false;
3791 assert(gIOPMWorkQueue
);
3792 gIOPMWorkQueue
->signalWorkAvailable();
3794 return kIOReturnSuccess
;
3797 void IOService::pmDriverCallout( IOService
* from
)
3800 switch (from
->fDriverCallReason
)
3802 case kDriverCallSetPowerState
:
3803 from
->driverSetPowerState();
3806 case kDriverCallInformPreChange
:
3807 case kDriverCallInformPostChange
:
3808 from
->driverInformPowerChange();
3811 case kRootDomainInformPreChange
:
3812 getPMRootDomain()->willNotifyPowerChildren(from
->fHeadNotePowerState
);
3816 panic("IOService::pmDriverCallout bad machine state %x",
3817 from
->fDriverCallReason
);
3820 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3822 /* arg0 */ (void *) from
->pwrMgt
);
3825 //*********************************************************************************
3826 // [private] driverSetPowerState
3828 // Thread call context
3829 //*********************************************************************************
3831 void IOService::driverSetPowerState( void )
3833 IOPMPowerStateIndex powerState
;
3834 DriverCallParam
* param
;
3835 IOPMDriverCallEntry callEntry
;
3838 uint32_t oldPowerState
= getPowerState();
3840 assert( fDriverCallBusy
);
3841 assert( fDriverCallParamPtr
);
3842 assert( fDriverCallParamCount
== 1 );
3844 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3845 powerState
= fHeadNotePowerState
;
3847 if (assertPMDriverCall(&callEntry
))
3849 OUR_PMLog( kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3850 clock_get_uptime(&fDriverCallStartTime
);
3851 result
= fControllingDriver
->setPowerState( powerState
, this );
3852 clock_get_uptime(&end
);
3853 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3855 deassertPMDriverCall(&callEntry
);
3857 // Record the most recent max power state residency timings.
3858 // Use with DeviceActiveTimestamp to diagnose tickle issues.
3859 if (powerState
== fHighestPowerState
)
3860 fMaxPowerStateEntryTime
= end
;
3861 else if (oldPowerState
== fHighestPowerState
)
3862 fMaxPowerStateExitTime
= end
;
3866 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
3867 fName
, OBFUSCATE(this), fCurrentPowerState
, powerState
, result
);
3870 #if LOG_SETPOWER_TIMES
3871 if ((result
== IOPMAckImplied
) || (result
< 0))
3875 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
3876 absolutetime_to_nanoseconds(end
, &nsec
);
3877 if (nsec
> LOG_SETPOWER_TIMES
) {
3878 getPMRootDomain()->pmStatsRecordApplicationResponse(
3879 gIOPMStatsDriverPSChangeSlow
,
3880 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), 0, NULL
, powerState
);
3886 result
= kIOPMAckImplied
;
3888 param
->Result
= result
;
3891 //*********************************************************************************
3892 // [private] driverInformPowerChange
3894 // Thread call context
3895 //*********************************************************************************
3897 void IOService::driverInformPowerChange( void )
3899 IOPMinformee
* informee
;
3901 DriverCallParam
* param
;
3902 IOPMDriverCallEntry callEntry
;
3903 IOPMPowerFlags powerFlags
;
3904 IOPMPowerStateIndex powerState
;
3909 assert( fDriverCallBusy
);
3910 assert( fDriverCallParamPtr
);
3911 assert( fDriverCallParamCount
);
3913 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3914 count
= fDriverCallParamCount
;
3916 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
3917 powerState
= fHeadNotePowerState
;
3919 for (IOItemCount i
= 0; i
< count
; i
++)
3921 informee
= (IOPMinformee
*) param
->Target
;
3922 driver
= informee
->whatObject
;
3924 if (assertPMDriverCall(&callEntry
, 0, informee
))
3926 if (fDriverCallReason
== kDriverCallInformPreChange
)
3928 OUR_PMLog(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
3929 clock_get_uptime(&informee
->startTime
);
3930 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
3931 clock_get_uptime(&end
);
3932 OUR_PMLog((UInt32
)-kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
3936 OUR_PMLog(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
3937 clock_get_uptime(&informee
->startTime
);
3938 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
3939 clock_get_uptime(&end
);
3940 OUR_PMLog((UInt32
)-kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
3943 deassertPMDriverCall(&callEntry
);
3945 #if LOG_SETPOWER_TIMES
3946 if ((result
== IOPMAckImplied
) || (result
< 0))
3950 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
3951 absolutetime_to_nanoseconds(end
, &nsec
);
3952 if (nsec
> LOG_SETPOWER_TIMES
) {
3953 getPMRootDomain()->pmStatsRecordApplicationResponse(
3954 gIOPMStatsDriverPSChangeSlow
, driver
->getName(),
3955 fDriverCallReason
, NS_TO_MS(nsec
), 0, NULL
, powerState
);
3961 result
= kIOPMAckImplied
;
3963 param
->Result
= result
;
3968 //*********************************************************************************
3969 // [private] notifyChild
3971 // Notify a power domain child of an upcoming power change.
3972 // If the object acknowledges the current change, we return TRUE.
3973 //*********************************************************************************
3975 bool IOService::notifyChild( IOPowerConnection
* theNub
)
3977 IOReturn ret
= IOPMAckImplied
;
3978 unsigned long childPower
;
3979 IOService
* theChild
;
3980 IOPMRequest
* childRequest
;
3981 IOPMPowerChangeFlags requestArg2
;
3984 PM_ASSERT_IN_GATE();
3985 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
3991 // Unless the child handles the notification immediately and returns
3992 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
3993 fHeadNotePendingAcks
++;
3994 theNub
->setAwaitingAck(true);
3996 requestArg2
= fHeadNoteChangeFlags
;
3997 if (StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
))
3998 requestArg2
|= kIOPMDomainPowerDrop
;
4000 requestType
= fIsPreChange
?
4001 kIOPMRequestTypePowerDomainWillChange
:
4002 kIOPMRequestTypePowerDomainDidChange
;
4004 childRequest
= acquirePMRequest( theChild
, requestType
);
4008 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
4009 childRequest
->fArg1
= (void *) theNub
;
4010 childRequest
->fArg2
= (void *)(uintptr_t) requestArg2
;
4011 theChild
->submitPMRequest( childRequest
);
4012 ret
= IOPMWillAckLater
;
4016 ret
= IOPMAckImplied
;
4017 fHeadNotePendingAcks
--;
4018 theNub
->setAwaitingAck(false);
4019 childPower
= theChild
->currentPowerConsumption();
4020 if ( childPower
== kIOPMUnknown
)
4022 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
4024 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
4025 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
4029 theChild
->release();
4030 return (IOPMAckImplied
== ret
);
4033 //*********************************************************************************
4034 // [private] notifyControllingDriver
4035 //*********************************************************************************
4037 bool IOService::notifyControllingDriver( void )
4039 DriverCallParam
* param
;
4041 PM_ASSERT_IN_GATE();
4042 assert( fDriverCallParamCount
== 0 );
4043 assert( fControllingDriver
);
4045 if (fInitialSetPowerState
)
4047 fInitialSetPowerState
= false;
4048 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
4050 // Driver specified flag to skip the inital setPowerState()
4051 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)
4057 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4060 param
= IONew(DriverCallParam
, 1);
4062 return false; // no memory
4064 fDriverCallParamPtr
= (void *) param
;
4065 fDriverCallParamSlots
= 1;
4068 param
->Target
= fControllingDriver
;
4069 fDriverCallParamCount
= 1;
4072 // Block state machine and wait for callout completion.
4073 assert(!fDriverCallBusy
);
4074 fDriverCallBusy
= true;
4075 thread_call_enter( fDriverCallEntry
);
4080 //*********************************************************************************
4081 // [private] notifyControllingDriverDone
4082 //*********************************************************************************
4084 void IOService::notifyControllingDriverDone( void )
4086 DriverCallParam
* param
;
4089 PM_ASSERT_IN_GATE();
4090 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4092 assert( fDriverCallBusy
== false );
4093 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4095 if (param
&& fDriverCallParamCount
)
4097 assert(fDriverCallParamCount
== 1);
4099 // the return value from setPowerState()
4100 result
= param
->Result
;
4102 if ((result
== IOPMAckImplied
) || (result
< 0))
4106 else if (fDriverTimer
)
4108 assert(fDriverTimer
== -1);
4110 // Driver has not acked, and has returned a positive result.
4111 // Enforce a minimum permissible timeout value.
4112 // Make the min value large enough so timeout is less likely
4113 // to occur if a driver misinterpreted that the return value
4114 // should be in microsecond units. And make it large enough
4115 // to be noticeable if a driver neglects to ack.
4117 if (result
< kMinAckTimeoutTicks
)
4118 result
= kMinAckTimeoutTicks
;
4120 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4122 // else, child has already acked and driver_timer reset to 0.
4124 fDriverCallParamCount
= 0;
4128 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4133 MS_POP(); // pushed by OurChangeSetPowerState()
4134 fIsPreChange
= false;
4137 //*********************************************************************************
4138 // [private] all_done
4140 // A power change is done.
4141 //*********************************************************************************
4143 void IOService::all_done( void )
4145 IOPMPowerStateIndex prevPowerState
;
4146 const IOPMPSEntry
* powerStatePtr
;
4147 IOPMDriverCallEntry callEntry
;
4148 uint32_t prevMachineState
= fMachineState
;
4149 bool callAction
= false;
4152 fMachineState
= kIOPM_Finished
;
4154 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4155 ((prevMachineState
== kIOPM_Finished
) ||
4156 (prevMachineState
== kIOPM_SyncFinish
)))
4158 // Sync operation and no power change occurred.
4159 // Do not inform driver and clients about this request completion,
4160 // except for the originator (root domain).
4162 PM_ACTION_2(actionPowerChangeDone
,
4163 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4165 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
4167 powerChangeDone(fCurrentPowerState
);
4169 else if (fAdvisoryTickleUsed
)
4171 // Not root domain and advisory tickle target.
4172 // Re-adjust power after power tree sync at the 'did' pass
4173 // to recompute desire and adjust power state between dark
4174 // and full wake transitions. Root domain is responsible
4175 // for calling setAdvisoryTickleEnable() before starting
4176 // the kIOPMSynchronize power change.
4178 if (!fAdjustPowerScheduled
&&
4179 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
))
4181 IOPMRequest
* request
;
4182 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4185 submitPMRequest( request
);
4186 fAdjustPowerScheduled
= true;
4195 if ( fHeadNoteChangeFlags
& kIOPMSelfInitiated
)
4197 // could our driver switch to the new state?
4198 if ( !( fHeadNoteChangeFlags
& kIOPMNotDone
) )
4200 trackSystemSleepPreventers(
4201 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4203 // we changed, tell our parent
4204 requestDomainPower(fHeadNotePowerState
);
4206 // yes, did power raise?
4207 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4209 // yes, inform clients and apps
4210 tellChangeUp (fHeadNotePowerState
);
4212 prevPowerState
= fCurrentPowerState
;
4214 fCurrentPowerState
= fHeadNotePowerState
;
4217 ts
= mach_absolute_time();
4218 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4222 fPMVars
->myCurrentState
= fCurrentPowerState
;
4224 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4225 PM_ACTION_2(actionPowerChangeDone
,
4226 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4229 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4230 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4231 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4232 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4234 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4236 // Bump tickle generation count once the entire tree is down
4237 gIOPMTickleGeneration
++;
4240 // inform subclass policy-maker
4241 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4242 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4244 powerChangeDone(prevPowerState
);
4245 deassertPMDriverCall(&callEntry
);
4248 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
4250 // changePowerStateWithOverrideTo() was cancelled
4251 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4255 // parent's power change
4256 if ( fHeadNoteChangeFlags
& kIOPMParentInitiated
)
4258 if (fHeadNoteChangeFlags
& kIOPMRootChangeDown
)
4259 ParentChangeRootChangeDown();
4261 if (((fHeadNoteChangeFlags
& kIOPMDomainWillChange
) &&
4262 (StateOrder(fCurrentPowerState
) >= StateOrder(fHeadNotePowerState
))) ||
4263 ((fHeadNoteChangeFlags
& kIOPMDomainDidChange
) &&
4264 (StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
))))
4266 trackSystemSleepPreventers(
4267 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4270 if ( StateOrder(fCurrentPowerState
) < StateOrder(fHeadNotePowerState
) )
4272 // yes, inform clients and apps
4273 tellChangeUp (fHeadNotePowerState
);
4276 prevPowerState
= fCurrentPowerState
;
4277 fCurrentPowerState
= fHeadNotePowerState
;
4280 ts
= mach_absolute_time();
4281 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
4285 fPMVars
->myCurrentState
= fCurrentPowerState
;
4287 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fHeadNoteDomainFlags
);
4289 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, prevPowerState
);
4290 PM_ACTION_2(actionPowerChangeDone
,
4291 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4294 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4295 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4296 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4297 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4299 // inform subclass policy-maker
4300 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4301 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4303 powerChangeDone(prevPowerState
);
4304 deassertPMDriverCall(&callEntry
);
4309 // When power rises enough to satisfy the tickle's desire for more power,
4310 // the condition preventing idle-timer from dropping power is removed.
4312 if (StateOrder(fCurrentPowerState
) >= StateOrder(fIdleTimerMinPowerState
))
4314 fIdleTimerMinPowerState
= kPowerStateZero
;
4319 PM_ACTION_2(actionPowerChangeDone
,
4320 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4325 // MARK: Power Change Initiated by Driver
4327 //*********************************************************************************
4328 // [private] OurChangeStart
4330 // Begin the processing of a power change initiated by us.
4331 //*********************************************************************************
4333 void IOService::OurChangeStart( void )
4335 PM_ASSERT_IN_GATE();
4336 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4338 // fMaxPowerState is our maximum possible power state based on the current
4339 // power state of our parents. If we are trying to raise power beyond the
4340 // maximum, send an async request for more power to all parents.
4342 if (!IS_PM_ROOT
&& (StateOrder(fMaxPowerState
) < StateOrder(fHeadNotePowerState
)))
4344 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4345 requestDomainPower(fHeadNotePowerState
);
4350 // Redundant power changes skips to the end of the state machine.
4352 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
4357 fInitialPowerChange
= false;
4359 // Change started, but may not complete...
4360 // Can be canceled (power drop) or deferred (power rise).
4362 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4364 // Two separate paths, depending if power is being raised or lowered.
4365 // Lowering power is subject to approval by clients of this service.
4369 fDoNotPowerDown
= false;
4371 // Ask for persmission to drop power state
4372 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4373 fOutOfBandParameter
= kNotifyApps
;
4374 askChangeDown(fHeadNotePowerState
);
4378 // This service is raising power and parents are able to support the
4379 // new power state. However a parent may have already committed to
4380 // drop power, which might force this object to temporarily drop power.
4381 // This results in "oscillations" before the state machines converge
4382 // to a steady state.
4384 // To prevent this, a child must make a power reservation against all
4385 // parents before raising power. If the reservation fails, indicating
4386 // that the child will be unable to sustain the higher power state,
4387 // then the child will signal the parent to adjust power, and the child
4388 // will defer its power change.
4392 // Reserve parent power necessary to achieve fHeadNotePowerState.
4393 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4394 if (ret
!= kIOReturnSuccess
)
4396 // Reservation failed, defer power rise.
4397 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4402 OurChangeTellCapabilityWillChange();
4406 //*********************************************************************************
4407 // [private] requestDomainPowerApplier
4409 // Call requestPowerDomainState() on all power parents.
4410 //*********************************************************************************
4412 struct IOPMRequestDomainPowerContext
{
4413 IOService
* child
; // the requesting child
4414 IOPMPowerFlags requestPowerFlags
; // power flags requested by child
4418 requestDomainPowerApplier(
4419 IORegistryEntry
* entry
,
4422 IOPowerConnection
* connection
;
4424 IOPMRequestDomainPowerContext
* context
;
4426 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0)
4428 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4433 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4435 if (connection
->parentKnowsState() && connection
->getReadyFlag())
4437 parent
->requestPowerDomainState(
4438 context
->requestPowerFlags
,
4446 //*********************************************************************************
4447 // [private] requestDomainPower
4449 // Called by a power child to broadcast its desired power state to all parents.
4450 // If the child self-initiates a power change, it must call this function to
4451 // allow its parents to adjust power state.
4452 //*********************************************************************************
4454 IOReturn
IOService::requestDomainPower(
4455 IOPMPowerStateIndex ourPowerState
,
4456 IOOptionBits options
)
4458 IOPMPowerFlags requestPowerFlags
;
4459 IOPMPowerStateIndex maxPowerState
;
4460 IOPMRequestDomainPowerContext context
;
4462 PM_ASSERT_IN_GATE();
4463 assert(ourPowerState
< fNumberOfPowerStates
);
4464 if (ourPowerState
>= fNumberOfPowerStates
)
4465 return kIOReturnBadArgument
;
4467 return kIOReturnSuccess
;
4469 // Fetch our input power flags for the requested power state.
4470 // Parent request is stated in terms of required power flags.
4472 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4474 // Disregard the "previous request" for power reservation.
4476 if (((options
& kReserveDomainPower
) == 0) &&
4477 (fPreviousRequestPowerFlags
== requestPowerFlags
))
4479 // skip if domain already knows our requirements
4482 fPreviousRequestPowerFlags
= requestPowerFlags
;
4484 // The results will be collected by fHeadNoteDomainTargetFlags
4485 context
.child
= this;
4486 context
.requestPowerFlags
= requestPowerFlags
;
4487 fHeadNoteDomainTargetFlags
= 0;
4488 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4490 if (options
& kReserveDomainPower
)
4492 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4493 fHeadNoteDomainTargetFlags
);
4495 if (StateOrder(maxPowerState
) < StateOrder(ourPowerState
))
4497 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4499 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4500 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4501 return kIOReturnNoPower
;
4506 return kIOReturnSuccess
;
4509 //*********************************************************************************
4510 // [private] OurSyncStart
4511 //*********************************************************************************
4513 void IOService::OurSyncStart( void )
4515 PM_ASSERT_IN_GATE();
4517 if (fInitialPowerChange
)
4520 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4522 if (fHeadNoteChangeFlags
& kIOPMNotDone
)
4528 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
)
4530 fDoNotPowerDown
= false;
4532 // Ask for permission to drop power state
4533 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4534 fOutOfBandParameter
= kNotifyApps
;
4535 askChangeDown(fHeadNotePowerState
);
4539 // Only inform capability app and clients.
4540 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4544 //*********************************************************************************
4545 // [private] OurChangeTellClientsPowerDown
4547 // All applications and kernel clients have acknowledged our permission to drop
4548 // power. Here we notify them that we will lower the power and wait for acks.
4549 //*********************************************************************************
4551 void IOService::OurChangeTellClientsPowerDown( void )
4554 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4557 fMachineState
= kIOPM_OurChangeTellUserPMPolicyPowerDown
;
4559 tellChangeDown1(fHeadNotePowerState
);
4562 //*********************************************************************************
4563 // [private] OurChangeTellUserPMPolicyPowerDown
4565 // All applications and kernel clients have acknowledged our permission to drop
4566 // power. Here we notify power management policy in user-space and wait for acks
4567 // one last time before we lower power
4568 //*********************************************************************************
4569 void IOService::OurChangeTellUserPMPolicyPowerDown ( void )
4571 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4572 fOutOfBandParameter
= kNotifyApps
;
4574 tellClientsWithResponse(kIOPMMessageLastCallBeforeSleep
);
4577 //*********************************************************************************
4578 // [private] OurChangeTellPriorityClientsPowerDown
4580 // All applications and kernel clients have acknowledged our intention to drop
4581 // power. Here we notify "priority" clients that we are lowering power.
4582 //*********************************************************************************
4584 void IOService::OurChangeTellPriorityClientsPowerDown( void )
4586 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4587 tellChangeDown2(fHeadNotePowerState
);
4590 //*********************************************************************************
4591 // [private] OurChangeTellCapabilityWillChange
4593 // Extra stage for root domain to notify apps and drivers about the
4594 // system capability change when raising power state.
4595 //*********************************************************************************
4597 void IOService::OurChangeTellCapabilityWillChange( void )
4599 if (!IS_ROOT_DOMAIN
)
4600 return OurChangeNotifyInterestedDriversWillChange();
4602 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4605 //*********************************************************************************
4606 // [private] OurChangeNotifyInterestedDriversWillChange
4608 // All applications and kernel clients have acknowledged our power state change.
4609 // Here we notify interested drivers pre-change.
4610 //*********************************************************************************
4612 void IOService::OurChangeNotifyInterestedDriversWillChange( void )
4614 IOPMrootDomain
* rootDomain
;
4615 if ((rootDomain
= getPMRootDomain()) == this)
4619 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4622 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4625 notifyAll( kIOPM_OurChangeSetPowerState
);
4628 //*********************************************************************************
4629 // [private] OurChangeSetPowerState
4631 // Instruct our controlling driver to program the hardware for the power state
4632 // change. Wait for async completions.
4633 //*********************************************************************************
4635 void IOService::OurChangeSetPowerState( void )
4637 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4638 fMachineState
= kIOPM_DriverThreadCallDone
;
4639 fDriverCallReason
= kDriverCallSetPowerState
;
4641 if (notifyControllingDriver() == false)
4642 notifyControllingDriverDone();
4645 //*********************************************************************************
4646 // [private] OurChangeWaitForPowerSettle
4648 // Our controlling driver has completed the power state change we initiated.
4649 // Wait for the driver specified settle time to expire.
4650 //*********************************************************************************
4652 void IOService::OurChangeWaitForPowerSettle( void )
4654 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4658 //*********************************************************************************
4659 // [private] OurChangeNotifyInterestedDriversDidChange
4661 // Power has settled on a power change we initiated. Here we notify
4662 // all our interested drivers post-change.
4663 //*********************************************************************************
4665 void IOService::OurChangeNotifyInterestedDriversDidChange( void )
4667 IOPMrootDomain
* rootDomain
;
4668 if ((rootDomain
= getPMRootDomain()) == this)
4670 rootDomain
->tracePoint( IS_POWER_DROP
?
4671 kIOPMTracePointSleepDidChangeInterests
:
4672 kIOPMTracePointWakeDidChangeInterests
);
4675 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4678 //*********************************************************************************
4679 // [private] OurChangeTellCapabilityDidChange
4681 // For root domain to notify capability power-change.
4682 //*********************************************************************************
4684 void IOService::OurChangeTellCapabilityDidChange( void )
4686 if (!IS_ROOT_DOMAIN
)
4687 return OurChangeFinish();
4689 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4690 kIOPMTracePointSleepCapabilityClients
:
4691 kIOPMTracePointWakeCapabilityClients
);
4693 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4696 //*********************************************************************************
4697 // [private] OurChangeFinish
4699 // Done with this self-induced power state change.
4700 //*********************************************************************************
4702 void IOService::OurChangeFinish( void )
4708 // MARK: Power Change Initiated by Parent
4710 //*********************************************************************************
4711 // [private] ParentChangeStart
4713 // Here we begin the processing of a power change initiated by our parent.
4714 //*********************************************************************************
4716 IOReturn
IOService::ParentChangeStart( void )
4718 PM_ASSERT_IN_GATE();
4719 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4721 // Root power domain has transitioned to its max power state
4722 if ((fHeadNoteChangeFlags
& (kIOPMDomainDidChange
| kIOPMRootChangeUp
)) ==
4723 (kIOPMDomainDidChange
| kIOPMRootChangeUp
))
4725 // Restart the idle timer stopped by ParentChangeRootChangeDown()
4726 if (fIdleTimerPeriod
&& fIdleTimerStopped
)
4732 // Power domain is forcing us to lower power
4733 if ( StateOrder(fHeadNotePowerState
) < StateOrder(fCurrentPowerState
) )
4735 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4737 // Tell apps and kernel clients
4738 fInitialPowerChange
= false;
4739 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4740 tellChangeDown1(fHeadNotePowerState
);
4741 return IOPMWillAckLater
;
4744 // Power domain is allowing us to raise power up to fHeadNotePowerState
4745 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4747 if ( StateOrder(fDesiredPowerState
) > StateOrder(fCurrentPowerState
) )
4749 if ( StateOrder(fDesiredPowerState
) < StateOrder(fHeadNotePowerState
) )
4751 // We power up, but not all the way
4752 fHeadNotePowerState
= fDesiredPowerState
;
4753 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4754 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4757 // We don't need to change
4758 fHeadNotePowerState
= fCurrentPowerState
;
4759 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4760 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4764 if ( fHeadNoteChangeFlags
& kIOPMDomainDidChange
)
4766 if ( StateOrder(fHeadNotePowerState
) > StateOrder(fCurrentPowerState
) )
4768 PM_ACTION_2(actionPowerChangeStart
,
4769 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4771 // Parent did change up - start our change up
4772 fInitialPowerChange
= false;
4773 ParentChangeTellCapabilityWillChange();
4774 return IOPMWillAckLater
;
4776 else if (fHeadNoteChangeFlags
& kIOPMRootBroadcastFlags
)
4778 // No need to change power state, but broadcast change
4780 fMachineState
= kIOPM_SyncNotifyDidChange
;
4781 fDriverCallReason
= kDriverCallInformPreChange
;
4783 return IOPMWillAckLater
;
4788 return IOPMAckImplied
;
4791 //******************************************************************************
4792 // [private] ParentChangeRootChangeDown
4794 // Root domain has finished the transition to the system sleep state. And all
4795 // drivers in the power plane should have powered down. Cancel the idle timer,
4796 // and also reset the device desire for those drivers that don't want power
4797 // automatically restored on wake.
4798 //******************************************************************************
4800 void IOService::ParentChangeRootChangeDown( void )
4802 // Always stop the idle timer before root power down
4803 if (fIdleTimerPeriod
&& !fIdleTimerStopped
)
4805 fIdleTimerStopped
= true;
4806 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
4810 if (fResetPowerStateOnWake
)
4812 // Reset device desire down to the lowest power state.
4813 // Advisory tickle desire is intentionally untouched since
4814 // it has no effect until system is promoted to full wake.
4816 if (fDeviceDesire
!= kPowerStateZero
)
4818 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4819 computeDesiredState(kPowerStateZero
, true);
4820 PM_LOG1("%s: tickle desire removed\n", fName
);
4823 // Invalidate tickle cache so the next tickle will issue a request
4824 IOLockLock(fActivityLock
);
4825 fDeviceWasActive
= false;
4826 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4827 IOLockUnlock(fActivityLock
);
4829 fIdleTimerMinPowerState
= kPowerStateZero
;
4831 else if (fAdvisoryTickleUsed
)
4833 // Less aggressive mechanism to accelerate idle timer expiration
4834 // before system sleep. May not always allow the driver to wake
4835 // up from system sleep in the min power state.
4839 bool dropTickleDesire
= false;
4841 if (fIdleTimerPeriod
&& !fIdleTimerIgnored
&&
4842 (fIdleTimerMinPowerState
== kPowerStateZero
) &&
4843 (fDeviceDesire
!= kPowerStateZero
))
4845 IOLockLock(fActivityLock
);
4847 if (!fDeviceWasActive
)
4849 // No tickles since the last idle timer expiration.
4850 // Safe to drop the device desire to zero.
4851 dropTickleDesire
= true;
4855 // Was tickled since the last idle timer expiration,
4856 // but not in the last minute.
4857 clock_get_uptime(&now
);
4858 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
4859 absolutetime_to_nanoseconds(now
, &nsec
);
4860 if (nsec
>= kNoTickleCancelWindow
)
4862 dropTickleDesire
= true;
4866 if (dropTickleDesire
)
4868 // Force the next tickle to raise power state
4869 fDeviceWasActive
= false;
4870 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4873 IOLockUnlock(fActivityLock
);
4876 if (dropTickleDesire
)
4878 // Advisory tickle desire is intentionally untouched since
4879 // it has no effect until system is promoted to full wake.
4881 updatePowerClient(gIOPMPowerClientDevice
, kPowerStateZero
);
4882 computeDesiredState(kPowerStateZero
, true);
4883 PM_LOG1("%s: tickle desire dropped\n", fName
);
4888 //*********************************************************************************
4889 // [private] ParentChangeTellPriorityClientsPowerDown
4891 // All applications and kernel clients have acknowledged our intention to drop
4892 // power. Here we notify "priority" clients that we are lowering power.
4893 //*********************************************************************************
4895 void IOService::ParentChangeTellPriorityClientsPowerDown( void )
4897 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
4898 tellChangeDown2(fHeadNotePowerState
);
4901 //*********************************************************************************
4902 // [private] ParentChangeTellCapabilityWillChange
4904 // All (legacy) applications and kernel clients have acknowledged, extra stage for
4905 // root domain to notify apps and drivers about the system capability change.
4906 //*********************************************************************************
4908 void IOService::ParentChangeTellCapabilityWillChange( void )
4910 if (!IS_ROOT_DOMAIN
)
4911 return ParentChangeNotifyInterestedDriversWillChange();
4913 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
4916 //*********************************************************************************
4917 // [private] ParentChangeNotifyInterestedDriversWillChange
4919 // All applications and kernel clients have acknowledged our power state change.
4920 // Here we notify interested drivers pre-change.
4921 //*********************************************************************************
4923 void IOService::ParentChangeNotifyInterestedDriversWillChange( void )
4925 notifyAll( kIOPM_ParentChangeSetPowerState
);
4928 //*********************************************************************************
4929 // [private] ParentChangeSetPowerState
4931 // Instruct our controlling driver to program the hardware for the power state
4932 // change. Wait for async completions.
4933 //*********************************************************************************
4935 void IOService::ParentChangeSetPowerState( void )
4937 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
4938 fMachineState
= kIOPM_DriverThreadCallDone
;
4939 fDriverCallReason
= kDriverCallSetPowerState
;
4941 if (notifyControllingDriver() == false)
4942 notifyControllingDriverDone();
4945 //*********************************************************************************
4946 // [private] ParentChangeWaitForPowerSettle
4948 // Our controlling driver has completed the power state change initiated by our
4949 // parent. Wait for the driver specified settle time to expire.
4950 //*********************************************************************************
4952 void IOService::ParentChangeWaitForPowerSettle( void )
4954 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
4958 //*********************************************************************************
4959 // [private] ParentChangeNotifyInterestedDriversDidChange
4961 // Power has settled on a power change initiated by our parent. Here we notify
4962 // all our interested drivers post-change.
4963 //*********************************************************************************
4965 void IOService::ParentChangeNotifyInterestedDriversDidChange( void )
4967 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
4970 //*********************************************************************************
4971 // [private] ParentChangeTellCapabilityDidChange
4973 // For root domain to notify capability power-change.
4974 //*********************************************************************************
4976 void IOService::ParentChangeTellCapabilityDidChange( void )
4978 if (!IS_ROOT_DOMAIN
)
4979 return ParentChangeAcknowledgePowerChange();
4981 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
4984 //*********************************************************************************
4985 // [private] ParentAcknowledgePowerChange
4987 // Acknowledge our power parent that our power change is done.
4988 //*********************************************************************************
4990 void IOService::ParentChangeAcknowledgePowerChange( void )
4992 IORegistryEntry
* nub
;
4995 nub
= fHeadNoteParentConnection
;
4998 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
5001 parent
->acknowledgePowerChange((IOService
*)nub
);
5008 // MARK: Ack and Settle timers
5010 //*********************************************************************************
5011 // [private] settleTimerExpired
5013 // Power has settled after our last change. Notify interested parties that
5014 // there is a new power state.
5015 //*********************************************************************************
5017 void IOService::settleTimerExpired( void )
5020 gIOPMWorkQueue
->signalWorkAvailable();
5023 //*********************************************************************************
5024 // settle_timer_expired
5026 // Holds a retain while the settle timer callout is in flight.
5027 //*********************************************************************************
5030 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5032 IOService
* me
= (IOService
*) arg0
;
5034 if (gIOPMWorkLoop
&& gIOPMWorkQueue
)
5036 gIOPMWorkLoop
->runAction(
5037 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
5043 //*********************************************************************************
5044 // [private] startSettleTimer
5046 // Calculate a power-settling delay in microseconds and start a timer.
5047 //*********************************************************************************
5049 void IOService::startSettleTimer( void )
5052 // This function is broken and serves no useful purpose since it never
5053 // updates fSettleTimeUS to a non-zero value to stall the state machine,
5054 // yet it starts a delay timer. It appears no driver relies on a delay
5055 // from settleUpTime and settleDownTime in the power state table.
5057 AbsoluteTime deadline
;
5058 IOPMPowerStateIndex stateIndex
;
5059 IOPMPowerStateIndex currentOrder
, newOrder
, i
;
5060 uint32_t settleTime
= 0;
5063 PM_ASSERT_IN_GATE();
5065 currentOrder
= StateOrder(fCurrentPowerState
);
5066 newOrder
= StateOrder(fHeadNotePowerState
);
5071 if ( newOrder
< currentOrder
)
5073 while ( i
> newOrder
)
5075 stateIndex
= fPowerStates
[i
].stateOrderToIndex
;
5076 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleDownTime
;
5082 if ( newOrder
> currentOrder
)
5084 while ( i
< newOrder
)
5086 stateIndex
= fPowerStates
[i
+1].stateOrderToIndex
;
5087 settleTime
+= (uint32_t) fPowerStates
[stateIndex
].settleUpTime
;
5095 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
5096 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
5097 if (pending
) release();
5102 //*********************************************************************************
5103 // [private] ackTimerTick
5105 // The acknowledgement timeout periodic timer has ticked.
5106 // If we are awaiting acks for a power change notification,
5107 // we decrement the timer word of each interested driver which hasn't acked.
5108 // If a timer word becomes zero, we pretend the driver aknowledged.
5109 // If we are waiting for the controlling driver to change the power
5110 // state of the hardware, we decrement its timer word, and if it becomes
5111 // zero, we pretend the driver acknowledged.
5113 // Returns true if the timer tick made it possible to advance to the next
5114 // machine state, false otherwise.
5115 //*********************************************************************************
5118 void IOService::ack_timer_ticked ( void )
5122 #endif /* !__LP64__ */
5124 bool IOService::ackTimerTick( void )
5126 IOPMinformee
* nextObject
;
5129 PM_ASSERT_IN_GATE();
5130 switch (fMachineState
) {
5131 case kIOPM_OurChangeWaitForPowerSettle
:
5132 case kIOPM_ParentChangeWaitForPowerSettle
:
5133 // are we waiting for controlling driver to acknowledge?
5134 if ( fDriverTimer
> 0 )
5136 // yes, decrement timer tick
5138 if ( fDriverTimer
== 0 )
5140 // controlling driver is tardy
5141 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
5142 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
5143 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
5144 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
5145 fName
, OBFUSCATE(this), fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5147 if (gIOKitDebug
& kIOLogDebugPower
)
5149 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
5150 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
5154 // Unblock state machine and pretend driver has acked.
5158 // still waiting, set timer again
5164 case kIOPM_NotifyChildrenStart
:
5165 // are we waiting for interested parties to acknowledge?
5166 if ( fHeadNotePendingAcks
!= 0 )
5168 // yes, go through the list of interested drivers
5169 nextObject
= fInterestedDrivers
->firstInList();
5170 // and check each one
5171 while ( nextObject
!= NULL
)
5173 if ( nextObject
->timer
> 0 )
5175 nextObject
->timer
--;
5176 // this one should have acked by now
5177 if ( nextObject
->timer
== 0 )
5179 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5180 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5181 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5182 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5183 nextObject
->whatObject
->getName(),
5184 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5185 OBFUSCATE(nextObject
->whatObject
), fName
, fCurrentPowerState
, fHeadNotePowerState
,
5188 // Pretend driver has acked.
5189 fHeadNotePendingAcks
--;
5192 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5195 // is that the last?
5196 if ( fHeadNotePendingAcks
== 0 )
5198 // yes, we can continue
5201 // no, set timer again
5207 // TODO: aggreggate this
5208 case kIOPM_OurChangeTellClientsPowerDown
:
5209 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
5210 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5211 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5212 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5213 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5214 case kIOPM_SyncTellClientsPowerDown
:
5215 case kIOPM_SyncTellPriorityClientsPowerDown
:
5216 case kIOPM_SyncNotifyWillChange
:
5217 case kIOPM_TellCapabilityChangeDone
:
5218 // apps didn't respond in time
5219 cleanClientResponses(true);
5220 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5221 // tardy equates to approval
5226 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5227 getName(), fMachineState
);
5233 //*********************************************************************************
5234 // [private] start_watchdog_timer
5235 //*********************************************************************************
5236 void IOService::start_watchdog_timer( void )
5238 AbsoluteTime deadline
;
5241 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5244 if (thread_call_isactive(fWatchdogTimer
)) return;
5246 clock_interval_to_deadline(WATCHDOG_TIMER_PERIOD
, kSecondScale
, &deadline
);
5249 pending
= thread_call_enter_delayed(fWatchdogTimer
, deadline
);
5250 if (pending
) release();
5254 //*********************************************************************************
5255 // [private] stop_watchdog_timer
5256 // Returns true if watchdog was enabled and stopped now
5257 //*********************************************************************************
5259 bool IOService::stop_watchdog_timer( void )
5263 if (!fWatchdogTimer
|| (kIOSleepWakeWdogOff
& gIOKitDebug
))
5266 pending
= thread_call_cancel(fWatchdogTimer
);
5267 if (pending
) release();
5272 //*********************************************************************************
5273 // reset_watchdog_timer
5274 //*********************************************************************************
5276 void IOService::reset_watchdog_timer( void )
5278 if (stop_watchdog_timer())
5279 start_watchdog_timer();
5283 //*********************************************************************************
5284 // [static] watchdog_timer_expired
5286 // Inside PM work loop's gate.
5287 //*********************************************************************************
5290 IOService::watchdog_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5292 IOService
* me
= (IOService
*) arg0
;
5295 gIOPMWatchDogThread
= current_thread();
5296 getPMRootDomain()->sleepWakeDebugTrig(true);
5297 gIOPMWatchDogThread
= 0;
5298 thread_call_free(me
->fWatchdogTimer
);
5299 me
->fWatchdogTimer
= 0;
5305 //*********************************************************************************
5306 // [private] start_ack_timer
5307 //*********************************************************************************
5309 void IOService::start_ack_timer( void )
5311 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5314 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
5316 AbsoluteTime deadline
;
5319 clock_interval_to_deadline(interval
, scale
, &deadline
);
5322 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5323 if (pending
) release();
5325 // Stop watchdog if ack is delayed by more than a sec
5326 if (interval
* scale
> kSecondScale
) {
5327 stop_watchdog_timer();
5331 //*********************************************************************************
5332 // [private] stop_ack_timer
5333 //*********************************************************************************
5335 void IOService::stop_ack_timer( void )
5339 pending
= thread_call_cancel(fAckTimer
);
5340 if (pending
) release();
5342 start_watchdog_timer();
5345 //*********************************************************************************
5346 // [static] actionAckTimerExpired
5348 // Inside PM work loop's gate.
5349 //*********************************************************************************
5352 IOService::actionAckTimerExpired(
5354 void * arg0
, void * arg1
,
5355 void * arg2
, void * arg3
)
5357 IOService
* me
= (IOService
*) target
;
5360 // done will be true if the timer tick unblocks the machine state,
5361 // otherwise no need to signal the work loop.
5363 done
= me
->ackTimerTick();
5364 if (done
&& gIOPMWorkQueue
)
5366 gIOPMWorkQueue
->signalWorkAvailable();
5367 me
->start_watchdog_timer();
5370 return kIOReturnSuccess
;
5373 //*********************************************************************************
5374 // ack_timer_expired
5376 // Thread call function. Holds a retain while the callout is in flight.
5377 //*********************************************************************************
5380 IOService::ack_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
5382 IOService
* me
= (IOService
*) arg0
;
5386 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5392 // MARK: Client Messaging
5394 //*********************************************************************************
5395 // [private] tellSystemCapabilityChange
5396 //*********************************************************************************
5398 void IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5401 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5402 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5406 // Notify app first on pre-change.
5407 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5411 // Notify kernel clients first on post-change.
5412 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5415 tellClientsWithResponse( fOutOfBandMessage
);
5418 //*********************************************************************************
5419 // [public] askChangeDown
5421 // Ask registered applications and kernel clients if we can change to a lower
5424 // Subclass can override this to send a different message type. Parameter is
5425 // the destination state number.
5427 // Return true if we don't have to wait for acknowledgements
5428 //*********************************************************************************
5430 bool IOService::askChangeDown( unsigned long stateNum
)
5432 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5435 //*********************************************************************************
5436 // [private] tellChangeDown1
5438 // Notify registered applications and kernel clients that we are definitely
5441 // Return true if we don't have to wait for acknowledgements
5442 //*********************************************************************************
5444 bool IOService::tellChangeDown1( unsigned long stateNum
)
5446 fOutOfBandParameter
= kNotifyApps
;
5447 return tellChangeDown(stateNum
);
5450 //*********************************************************************************
5451 // [private] tellChangeDown2
5453 // Notify priority clients that we are definitely dropping power.
5455 // Return true if we don't have to wait for acknowledgements
5456 //*********************************************************************************
5458 bool IOService::tellChangeDown2( unsigned long stateNum
)
5460 fOutOfBandParameter
= kNotifyPriority
;
5461 return tellChangeDown(stateNum
);
5464 //*********************************************************************************
5465 // [public] tellChangeDown
5467 // Notify registered applications and kernel clients that we are definitely
5470 // Subclass can override this to send a different message type. Parameter is
5471 // the destination state number.
5473 // Return true if we don't have to wait for acknowledgements
5474 //*********************************************************************************
5476 bool IOService::tellChangeDown( unsigned long stateNum
)
5478 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5481 //*********************************************************************************
5482 // cleanClientResponses
5484 //*********************************************************************************
5486 static void logAppTimeouts( OSObject
* object
, void * arg
)
5488 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5490 unsigned int clientIndex
;
5494 if (OSDynamicCast(_IOServiceInterestNotifier
, object
))
5496 // Discover the 'counter' value or index assigned to this client
5497 // when it was notified, by searching for the array index of the
5498 // client in an array holding the cached interested clients.
5500 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5502 if ((clientIndex
!= (unsigned int) -1) &&
5503 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5504 (flag
!= kOSBooleanTrue
))
5506 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5510 pid
= clientID
->unsigned32BitValue();
5511 proc_name(pid
, name
, sizeof(name
));
5512 clientID
->release();
5515 PM_ERROR(context
->errorLog
, pid
, name
);
5517 // TODO: record message type if possible
5518 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5519 gIOPMStatsApplicationResponseTimedOut
,
5520 name
, 0, (30*1000), pid
, object
);
5526 void IOService::cleanClientResponses( bool logErrors
)
5528 if (logErrors
&& fResponseArray
)
5530 switch ( fOutOfBandParameter
) {
5532 case kNotifyCapabilityChangeApps
:
5533 if (fNotifyClientArray
)
5535 IOPMInterestContext context
;
5537 context
.responseArray
= fResponseArray
;
5538 context
.notifyClients
= fNotifyClientArray
;
5539 context
.serialNumber
= fSerialNumber
;
5540 context
.messageType
= kIOMessageCopyClientID
;
5541 context
.notifyType
= kNotifyApps
;
5542 context
.isPreChange
= fIsPreChange
;
5543 context
.enableTracing
= false;
5545 context
.maxTimeRequested
= 0;
5546 context
.stateNumber
= fHeadNotePowerState
;
5547 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5548 context
.changeFlags
= fHeadNoteChangeFlags
;
5549 context
.errorLog
= "PM notification timeout (pid %d, %s)\n";
5551 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5556 // kNotifyPriority, kNotifyCapabilityChangePriority
5557 // TODO: identify the priority client that has not acked
5558 PM_ERROR("PM priority notification timeout\n");
5559 if (gIOKitDebug
& kIOLogDebugPower
)
5561 panic("PM priority notification timeout");
5569 fResponseArray
->release();
5570 fResponseArray
= NULL
;
5572 if (fNotifyClientArray
)
5574 fNotifyClientArray
->release();
5575 fNotifyClientArray
= NULL
;
5579 //*********************************************************************************
5580 // [protected] tellClientsWithResponse
5582 // Notify registered applications and kernel clients that we are definitely
5585 // Return true if we don't have to wait for acknowledgements
5586 //*********************************************************************************
5588 bool IOService::tellClientsWithResponse( int messageType
)
5590 IOPMInterestContext context
;
5591 bool isRootDomain
= IS_ROOT_DOMAIN
;
5593 PM_ASSERT_IN_GATE();
5594 assert( fResponseArray
== NULL
);
5595 assert( fNotifyClientArray
== NULL
);
5597 if(messageType
== (int)kIOPMMessageLastCallBeforeSleep
)
5598 RD_LOG("tellClientsWithResponse( kIOPMMessageLastCallBeforeSleep, %d )\n",
5599 fOutOfBandParameter
);
5601 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5602 getIOMessageString(messageType
), fOutOfBandParameter
);
5604 fResponseArray
= OSArray::withCapacity( 1 );
5605 if (!fResponseArray
)
5608 fResponseArray
->setCapacityIncrement(8);
5609 if (++fSerialNumber
== 0)
5612 context
.responseArray
= fResponseArray
;
5613 context
.notifyClients
= 0;
5614 context
.serialNumber
= fSerialNumber
;
5615 context
.messageType
= messageType
;
5616 context
.notifyType
= fOutOfBandParameter
;
5617 context
.isPreChange
= fIsPreChange
;
5618 context
.enableTracing
= false;
5620 context
.maxTimeRequested
= 0;
5621 context
.stateNumber
= fHeadNotePowerState
;
5622 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5623 context
.changeFlags
= fHeadNoteChangeFlags
;
5624 context
.messageFilter
= (isRootDomain
) ?
5625 OSMemberFunctionCast(
5628 &IOPMrootDomain::systemMessageFilter
) : 0;
5630 switch ( fOutOfBandParameter
) {
5632 applyToInterested( gIOAppPowerStateInterest
,
5633 pmTellAppWithResponse
, (void *) &context
);
5636 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5637 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
) &&
5638 (context
.messageType
!= kIOPMMessageLastCallBeforeSleep
))
5640 // Notify capability app for tellChangeDown1()
5641 // but not for askChangeDown().
5642 context
.notifyType
= kNotifyCapabilityChangeApps
;
5643 context
.messageType
= kIOMessageSystemCapabilityChange
;
5644 applyToInterested( gIOAppPowerStateInterest
,
5645 pmTellCapabilityAppWithResponse
, (void *) &context
);
5646 context
.notifyType
= fOutOfBandParameter
;
5647 context
.messageType
= messageType
;
5649 context
.maxTimeRequested
= k30Seconds
;
5651 applyToInterested( gIOGeneralInterest
,
5652 pmTellClientWithResponse
, (void *) &context
);
5654 fNotifyClientArray
= context
.notifyClients
;
5657 case kNotifyPriority
:
5658 context
.enableTracing
= isRootDomain
;
5659 applyToInterested( gIOPriorityPowerStateInterest
,
5660 pmTellClientWithResponse
, (void *) &context
);
5664 // Notify capability clients for tellChangeDown2().
5665 context
.notifyType
= kNotifyCapabilityChangePriority
;
5666 context
.messageType
= kIOMessageSystemCapabilityChange
;
5667 applyToInterested( gIOPriorityPowerStateInterest
,
5668 pmTellCapabilityClientWithResponse
, (void *) &context
);
5672 case kNotifyCapabilityChangeApps
:
5673 applyToInterested( gIOAppPowerStateInterest
,
5674 pmTellCapabilityAppWithResponse
, (void *) &context
);
5675 fNotifyClientArray
= context
.notifyClients
;
5676 context
.maxTimeRequested
= k30Seconds
;
5679 case kNotifyCapabilityChangePriority
:
5680 applyToInterested( gIOPriorityPowerStateInterest
,
5681 pmTellCapabilityClientWithResponse
, (void *) &context
);
5685 // do we have to wait for somebody?
5686 if ( !checkForDone() )
5688 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5689 if (context
.enableTracing
)
5690 getPMRootDomain()->traceDetail( context
.maxTimeRequested
/ 1000 );
5691 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5696 // everybody responded
5699 fResponseArray
->release();
5700 fResponseArray
= NULL
;
5702 if (fNotifyClientArray
)
5704 fNotifyClientArray
->release();
5705 fNotifyClientArray
= NULL
;
5711 //*********************************************************************************
5712 // [static private] pmTellAppWithResponse
5714 // We send a message to an application, and we expect a response, so we compute a
5715 // cookie we can identify the response with.
5716 //*********************************************************************************
5718 void IOService::pmTellAppWithResponse( OSObject
* object
, void * arg
)
5720 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5721 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5722 uint32_t msgIndex
, msgRef
, msgType
;
5723 OSNumber
*clientID
= NULL
;
5725 boolean_t proc_suspended
= FALSE
;
5726 OSObject
* waitForReply
= kOSBooleanTrue
;
5727 #if LOG_APP_RESPONSE_TIMES
5731 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5734 if (context
->us
== getPMRootDomain())
5736 if ((clientID
= copyClientIDForNotification(object
, context
)))
5738 uint32_t clientPID
= clientID
->unsigned32BitValue();
5739 clientID
->release();
5740 proc
= proc_find(clientPID
);
5744 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
5749 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
5756 if (context
->messageFilter
&&
5757 !context
->messageFilter(context
->us
, object
, context
, 0, &waitForReply
))
5759 if (kIOLogDebugPower
& gIOKitDebug
)
5761 logClientIDForNotification(object
, context
, "DROP App");
5766 // Create client array (for tracking purposes) only if the service
5767 // has app clients. Usually only root domain does.
5768 if (0 == context
->notifyClients
)
5769 context
->notifyClients
= OSArray::withCapacity( 32 );
5771 msgType
= context
->messageType
;
5772 msgIndex
= context
->responseArray
->getCount();
5773 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5775 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
5776 if (kIOLogDebugPower
& gIOKitDebug
)
5778 logClientIDForNotification(object
, context
, "MESG App");
5781 if (waitForReply
== kOSBooleanTrue
)
5783 #if LOG_APP_RESPONSE_TIMES
5785 clock_get_uptime(&now
);
5786 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
5789 context
->responseArray
->setObject(msgIndex
, num
);
5794 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
5798 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
5799 if (kIOLogDebugPower
& gIOKitDebug
)
5801 logClientIDForNotification(object
, context
, "App response ignored");
5805 if (context
->notifyClients
)
5806 context
->notifyClients
->setObject(msgIndex
, object
);
5808 context
->us
->messageClient(msgType
, object
, (void *)(uintptr_t) msgRef
);
5811 //*********************************************************************************
5812 // [static private] pmTellClientWithResponse
5814 // We send a message to an in-kernel client, and we expect a response,
5815 // so we compute a cookie we can identify the response with.
5816 //*********************************************************************************
5818 void IOService::pmTellClientWithResponse( OSObject
* object
, void * arg
)
5820 IOPowerStateChangeNotification notify
;
5821 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5822 OSObject
* replied
= kOSBooleanTrue
;
5823 _IOServiceInterestNotifier
* notifier
;
5824 uint32_t msgIndex
, msgRef
, msgType
;
5827 if (context
->messageFilter
&&
5828 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5830 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5831 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5833 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5834 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5835 context
->us
->getName(),
5836 getIOMessageString(context
->messageType
),
5837 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
5842 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5843 msgType
= context
->messageType
;
5844 msgIndex
= context
->responseArray
->getCount();
5845 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5847 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5848 if (gIOKitDebug
& kIOLogPower
) {
5849 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
5850 if (OSDynamicCast(IOService
, object
)) {
5851 const char *who
= ((IOService
*) object
)->getName();
5852 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
5854 else if (notifier
) {
5855 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
5858 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
5860 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5861 context
->us
->getName(),
5862 getIOMessageString(msgType
),
5863 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
5866 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
5867 notify
.returnValue
= 0;
5868 notify
.stateNumber
= context
->stateNumber
;
5869 notify
.stateFlags
= context
->stateFlags
;
5871 if (context
->enableTracing
&& (notifier
!= 0))
5873 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
5874 ((msgType
& 0xfff) << 12) |
5875 (((uintptr_t) notifier
->handler
) & 0xfff);
5876 getPMRootDomain()->traceDetail( detail
);
5879 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
5881 if (kIOReturnSuccess
== retCode
)
5883 if (0 == notify
.returnValue
) {
5884 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
5886 replied
= kOSBooleanFalse
;
5887 if ( notify
.returnValue
> context
->maxTimeRequested
)
5889 if (notify
.returnValue
> kPriorityClientMaxWait
)
5891 context
->maxTimeRequested
= kPriorityClientMaxWait
;
5892 PM_ERROR("%s: client %p returned %llu for %s\n",
5893 context
->us
->getName(),
5894 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
5895 (uint64_t) notify
.returnValue
,
5896 getIOMessageString(msgType
));
5899 context
->maxTimeRequested
= notify
.returnValue
;
5903 // not a client of ours
5904 // so we won't be waiting for response
5905 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
5908 context
->responseArray
->setObject(msgIndex
, replied
);
5911 //*********************************************************************************
5912 // [static private] pmTellCapabilityAppWithResponse
5913 //*********************************************************************************
5915 void IOService::pmTellCapabilityAppWithResponse( OSObject
* object
, void * arg
)
5917 IOPMSystemCapabilityChangeParameters msgArg
;
5918 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5919 OSObject
* replied
= kOSBooleanTrue
;
5920 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5921 uint32_t msgIndex
, msgRef
, msgType
;
5922 #if LOG_APP_RESPONSE_TIMES
5926 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5929 memset(&msgArg
, 0, sizeof(msgArg
));
5930 if (context
->messageFilter
&&
5931 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
))
5936 // Create client array (for tracking purposes) only if the service
5937 // has app clients. Usually only root domain does.
5938 if (0 == context
->notifyClients
)
5939 context
->notifyClients
= OSArray::withCapacity( 32 );
5941 msgType
= context
->messageType
;
5942 msgIndex
= context
->responseArray
->getCount();
5943 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5945 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
5946 if (kIOLogDebugPower
& gIOKitDebug
)
5948 // Log client pid/name and client array index.
5949 OSNumber
* clientID
= NULL
;
5950 OSString
* clientIDString
= NULL
;;
5951 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
5953 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
5956 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
5957 context
->us
->getName(),
5958 msgIndex
, getIOMessageString(msgType
),
5959 (replied
!= kOSBooleanTrue
),
5960 clientIDString
? clientIDString
->getCStringNoCopy() : "");
5961 if (clientID
) clientID
->release();
5962 if (clientIDString
) clientIDString
->release();
5965 msgArg
.notifyRef
= msgRef
;
5966 msgArg
.maxWaitForReply
= 0;
5968 if (replied
== kOSBooleanTrue
)
5970 msgArg
.notifyRef
= 0;
5971 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
5972 if (context
->notifyClients
)
5973 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
5977 #if LOG_APP_RESPONSE_TIMES
5979 clock_get_uptime(&now
);
5980 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
5983 context
->responseArray
->setObject(msgIndex
, num
);
5988 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
5990 if (context
->notifyClients
)
5991 context
->notifyClients
->setObject(msgIndex
, object
);
5994 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
5997 //*********************************************************************************
5998 // [static private] pmTellCapabilityClientWithResponse
5999 //*********************************************************************************
6001 void IOService::pmTellCapabilityClientWithResponse(
6002 OSObject
* object
, void * arg
)
6004 IOPMSystemCapabilityChangeParameters msgArg
;
6005 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6006 OSObject
* replied
= kOSBooleanTrue
;
6007 _IOServiceInterestNotifier
* notifier
;
6008 uint32_t msgIndex
, msgRef
, msgType
;
6011 memset(&msgArg
, 0, sizeof(msgArg
));
6012 if (context
->messageFilter
&&
6013 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, 0))
6015 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6016 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6018 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6019 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6020 context
->us
->getName(),
6021 getIOMessageString(context
->messageType
),
6022 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6027 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
6028 msgType
= context
->messageType
;
6029 msgIndex
= context
->responseArray
->getCount();
6030 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
6032 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
6033 if (gIOKitDebug
& kIOLogPower
) {
6034 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
6035 if (OSDynamicCast(IOService
, object
)) {
6036 const char *who
= ((IOService
*) object
)->getName();
6037 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
6039 else if (notifier
) {
6040 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
6043 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
6045 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6046 context
->us
->getName(),
6047 getIOMessageString(msgType
),
6048 OBFUSCATE(object
), OBFUSCATE(notifier
->handler
));
6051 msgArg
.notifyRef
= msgRef
;
6052 msgArg
.maxWaitForReply
= 0;
6054 if (context
->enableTracing
&& (notifier
!= 0))
6056 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
6057 ((msgType
& 0xfff) << 12) |
6058 (((uintptr_t) notifier
->handler
) & 0xfff);
6059 getPMRootDomain()->traceDetail( detail
);
6062 retCode
= context
->us
->messageClient(
6063 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
6065 if ( kIOReturnSuccess
== retCode
)
6067 if ( 0 == msgArg
.maxWaitForReply
)
6069 // client doesn't want time to respond
6070 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
6074 replied
= kOSBooleanFalse
;
6075 if ( msgArg
.maxWaitForReply
> context
->maxTimeRequested
)
6077 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
)
6079 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
6080 PM_ERROR("%s: client %p returned %u for %s\n",
6081 context
->us
->getName(),
6082 notifier
? (void *) OBFUSCATE(notifier
->handler
) : OBFUSCATE(object
),
6083 msgArg
.maxWaitForReply
,
6084 getIOMessageString(msgType
));
6087 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
6093 // not a client of ours
6094 // so we won't be waiting for response
6095 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
6098 context
->responseArray
->setObject(msgIndex
, replied
);
6101 //*********************************************************************************
6102 // [public] tellNoChangeDown
6104 // Notify registered applications and kernel clients that we are not
6107 // Subclass can override this to send a different message type. Parameter is
6108 // the aborted destination state number.
6109 //*********************************************************************************
6111 void IOService::tellNoChangeDown( unsigned long )
6113 return tellClients( kIOMessageDeviceWillNotPowerOff
);
6116 //*********************************************************************************
6117 // [public] tellChangeUp
6119 // Notify registered applications and kernel clients that we are raising power.
6121 // Subclass can override this to send a different message type. Parameter is
6122 // the aborted destination state number.
6123 //*********************************************************************************
6125 void IOService::tellChangeUp( unsigned long )
6127 return tellClients( kIOMessageDeviceHasPoweredOn
);
6130 //*********************************************************************************
6131 // [protected] tellClients
6133 // Notify registered applications and kernel clients of something.
6134 //*********************************************************************************
6136 void IOService::tellClients( int messageType
)
6138 IOPMInterestContext context
;
6140 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
6142 memset(&context
, 0, sizeof(context
));
6143 context
.messageType
= messageType
;
6144 context
.isPreChange
= fIsPreChange
;
6146 context
.stateNumber
= fHeadNotePowerState
;
6147 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
6148 context
.changeFlags
= fHeadNoteChangeFlags
;
6149 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
6150 OSMemberFunctionCast(
6153 &IOPMrootDomain::systemMessageFilter
) : 0;
6155 context
.notifyType
= kNotifyPriority
;
6156 applyToInterested( gIOPriorityPowerStateInterest
,
6157 tellKernelClientApplier
, (void *) &context
);
6159 context
.notifyType
= kNotifyApps
;
6160 applyToInterested( gIOAppPowerStateInterest
,
6161 tellAppClientApplier
, (void *) &context
);
6163 applyToInterested( gIOGeneralInterest
,
6164 tellKernelClientApplier
, (void *) &context
);
6167 //*********************************************************************************
6168 // [private] tellKernelClientApplier
6170 // Message a kernel client.
6171 //*********************************************************************************
6173 static void tellKernelClientApplier( OSObject
* object
, void * arg
)
6175 IOPowerStateChangeNotification notify
;
6176 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6178 if (context
->messageFilter
&&
6179 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6181 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6182 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6184 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6185 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
6186 context
->us
->getName(),
6187 IOService::getIOMessageString(context
->messageType
),
6188 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6193 notify
.powerRef
= (void *) 0;
6194 notify
.returnValue
= 0;
6195 notify
.stateNumber
= context
->stateNumber
;
6196 notify
.stateFlags
= context
->stateFlags
;
6198 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
6200 if ((kIOLogDebugPower
& gIOKitDebug
) &&
6201 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
6203 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
6204 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
6205 context
->us
->getName(),
6206 IOService::getIOMessageString(context
->messageType
),
6207 OBFUSCATE(object
), OBFUSCATE(n
->handler
));
6211 static OSNumber
* copyClientIDForNotification(
6213 IOPMInterestContext
*context
)
6215 OSNumber
*clientID
= NULL
;
6216 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
6220 static void logClientIDForNotification(
6222 IOPMInterestContext
*context
,
6223 const char *logString
)
6225 OSString
*logClientID
= NULL
;
6226 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
6231 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
6233 PM_LOG("%s %s %s, %s\n",
6234 context
->us
->getName(), logString
,
6235 IOService::getIOMessageString(context
->messageType
),
6236 logClientID
? logClientID
->getCStringNoCopy() : "");
6239 logClientID
->release();
6243 clientID
->release();
6248 static void tellAppClientApplier( OSObject
* object
, void * arg
)
6250 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6251 OSNumber
* clientID
= NULL
;
6253 boolean_t proc_suspended
= FALSE
;
6255 if (context
->us
== IOService::getPMRootDomain())
6257 if ((clientID
= copyClientIDForNotification(object
, context
)))
6259 uint32_t clientPID
= clientID
->unsigned32BitValue();
6260 clientID
->release();
6261 proc
= proc_find(clientPID
);
6265 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6270 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6277 if (context
->messageFilter
&&
6278 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6280 if (kIOLogDebugPower
& gIOKitDebug
)
6282 logClientIDForNotification(object
, context
, "DROP App");
6287 if (kIOLogDebugPower
& gIOKitDebug
)
6289 logClientIDForNotification(object
, context
, "MESG App");
6292 context
->us
->messageClient(context
->messageType
, object
, 0);
6295 //*********************************************************************************
6296 // [private] checkForDone
6297 //*********************************************************************************
6299 bool IOService::checkForDone( void )
6304 if (fResponseArray
== NULL
) {
6308 for (i
= 0; ; i
++) {
6309 theFlag
= fResponseArray
->getObject(i
);
6311 if (NULL
== theFlag
) {
6315 if (kOSBooleanTrue
!= theFlag
) {
6322 //*********************************************************************************
6323 // [public] responseValid
6324 //*********************************************************************************
6326 bool IOService::responseValid( uint32_t refcon
, int pid
)
6328 UInt16 serialComponent
;
6329 UInt16 ordinalComponent
;
6331 OSObject
*object
= 0;
6333 serialComponent
= (refcon
>> 16) & 0xFFFF;
6334 ordinalComponent
= (refcon
& 0xFFFF);
6336 if ( serialComponent
!= fSerialNumber
)
6341 if ( fResponseArray
== NULL
)
6346 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6353 if (fNotifyClientArray
)
6354 object
= fNotifyClientArray
->getObject(ordinalComponent
);
6357 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
6359 #if LOG_APP_RESPONSE_TIMES
6366 proc_name(pid
, name
, sizeof(name
));
6367 clock_get_uptime(&now
);
6368 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6369 SUB_ABSOLUTETIME(&now
, &start
);
6370 absolutetime_to_nanoseconds(now
, &nsec
);
6372 if (kIOLogDebugPower
& gIOKitDebug
)
6374 PM_LOG("Ack(%u) %u ms\n",
6375 (uint32_t) ordinalComponent
,
6380 if (nsec
> LOG_APP_RESPONSE_TIMES
)
6382 IOLog("PM response took %d ms (%d, %s)\n", NS_TO_MS(nsec
),
6386 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
6388 // TODO: populate the messageType argument
6389 getPMRootDomain()->pmStatsRecordApplicationResponse(
6390 gIOPMStatsApplicationResponseSlow
,
6391 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6395 getPMRootDomain()->pmStatsRecordApplicationResponse(
6396 gIOPMStatsApplicationResponsePrompt
,
6397 name
, 0, NS_TO_MS(nsec
), pid
, object
);
6401 theFlag
= kOSBooleanFalse
;
6404 getPMRootDomain()->pmStatsRecordApplicationResponse(
6405 gIOPMStatsApplicationResponsePrompt
,
6406 0, 0, 0, pid
, object
);
6410 if ( kOSBooleanFalse
== theFlag
)
6412 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6418 //*********************************************************************************
6419 // [public] allowPowerChange
6421 // Our power state is about to lower, and we have notified applications
6422 // and kernel clients, and one of them has acknowledged. If this is the last to do
6423 // so, and all acknowledgements are positive, we continue with the power change.
6424 //*********************************************************************************
6426 IOReturn
IOService::allowPowerChange( unsigned long refcon
)
6428 IOPMRequest
* request
;
6433 return kIOReturnSuccess
;
6436 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6438 return kIOReturnNoMemory
;
6440 request
->fArg0
= (void *) refcon
;
6441 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6442 request
->fArg2
= (void *) 0;
6443 submitPMRequest( request
);
6445 return kIOReturnSuccess
;
6449 IOReturn
IOService::serializedAllowPowerChange2( unsigned long refcon
)
6451 // [deprecated] public
6452 return kIOReturnUnsupported
;
6454 #endif /* !__LP64__ */
6456 //*********************************************************************************
6457 // [public] cancelPowerChange
6459 // Our power state is about to lower, and we have notified applications
6460 // and kernel clients, and one of them has vetoed the change. If this is the last
6461 // client to respond, we abandon the power change.
6462 //*********************************************************************************
6464 IOReturn
IOService::cancelPowerChange( unsigned long refcon
)
6466 IOPMRequest
* request
;
6468 pid_t pid
= proc_selfpid();
6473 return kIOReturnSuccess
;
6477 proc_name(pid
, name
, sizeof(name
));
6478 PM_ERROR("PM notification cancel (pid %d, %s)\n", pid
, name
);
6480 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6483 return kIOReturnNoMemory
;
6486 request
->fArg0
= (void *) refcon
;
6487 request
->fArg1
= (void *)(uintptr_t) proc_selfpid();
6488 request
->fArg2
= (void *) OSString::withCString(name
);
6489 submitPMRequest( request
);
6491 return kIOReturnSuccess
;
6495 IOReturn
IOService::serializedCancelPowerChange2( unsigned long refcon
)
6497 // [deprecated] public
6498 return kIOReturnUnsupported
;
6501 //*********************************************************************************
6502 // PM_Clamp_Timer_Expired
6504 // called when clamp timer expires...set power state to 0.
6505 //*********************************************************************************
6507 void IOService::PM_Clamp_Timer_Expired( void )
6511 //*********************************************************************************
6514 // Set to highest available power state for a minimum of duration milliseconds
6515 //*********************************************************************************
6517 void IOService::clampPowerOn( unsigned long duration
)
6520 #endif /* !__LP64__ */
6522 //*********************************************************************************
6523 // configurePowerStateReport
6525 // Configures the IOStateReport for kPMPowerStateChannel
6526 //*********************************************************************************
6527 IOReturn
IOService::configurePowerStatesReport( IOReportConfigureAction action
, void *result
)
6530 IOReturn rc
= kIOReturnSuccess
;
6536 return kIOReturnUnsupported
;
6538 if (!fNumberOfPowerStates
)
6539 return kIOReturnSuccess
; // For drivers which are in power plane, but haven't called registerPowerDriver()
6544 case kIOReportEnable
:
6550 reportSize
= STATEREPORT_BUFSIZE(fNumberOfPowerStates
);
6551 fReportBuf
= IOMalloc(reportSize
);
6553 rc
= kIOReturnNoMemory
;
6556 memset(fReportBuf
, 0, reportSize
);
6558 STATEREPORT_INIT(fNumberOfPowerStates
, fReportBuf
, reportSize
,
6559 getRegistryEntryID(), kPMPowerStatesChID
, kIOReportCategoryPower
);
6561 for (i
= 0; i
< fNumberOfPowerStates
; i
++) {
6564 if (fPowerStates
[i
].capabilityFlags
& kIOPMPowerOn
)
6565 bits
|= kPMReportPowerOn
;
6566 if (fPowerStates
[i
].capabilityFlags
& kIOPMDeviceUsable
)
6567 bits
|= kPMReportDeviceUsable
;
6568 if (fPowerStates
[i
].capabilityFlags
& kIOPMLowPower
)
6569 bits
|= kPMReportLowPower
;
6571 STATEREPORT_SETSTATEID(fReportBuf
, i
, ((bits
& 0xff) << 8) |
6572 ((StateOrder(fMaxPowerState
) & 0xf) << 4) | (StateOrder(i
) & 0xf));
6574 ts
= mach_absolute_time();
6575 STATEREPORT_SETSTATE(fReportBuf
, fCurrentPowerState
, ts
);
6578 case kIOReportDisable
:
6579 if (fReportClientCnt
== 0) {
6580 rc
= kIOReturnBadArgument
;
6583 if (fReportClientCnt
== 1)
6585 IOFree(fReportBuf
, STATEREPORT_BUFSIZE(fNumberOfPowerStates
));
6591 case kIOReportGetDimensions
:
6593 STATEREPORT_UPDATERES(fReportBuf
, kIOReportGetDimensions
, result
);
6602 //*********************************************************************************
6603 // updatePowerStateReport
6605 // Updates the IOStateReport for kPMPowerStateChannel
6606 //*********************************************************************************
6607 IOReturn
IOService::updatePowerStatesReport( IOReportConfigureAction action
, void *result
, void *destination
)
6612 IOReturn rc
= kIOReturnSuccess
;
6613 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6617 return kIOReturnUnsupported
;
6618 if (!fNumberOfPowerStates
)
6619 return kIOReturnSuccess
;
6621 if ( !result
|| !dest
) return kIOReturnBadArgument
;
6625 case kIOReportCopyChannelData
:
6626 if ( !fReportBuf
) {
6627 rc
= kIOReturnNotOpen
;
6631 ts
= mach_absolute_time();
6632 STATEREPORT_UPDATEPREP(fReportBuf
, ts
, data2cpy
, size2cpy
);
6633 if (size2cpy
> (dest
->getCapacity() - dest
->getLength()) ) {
6634 rc
= kIOReturnOverrun
;
6638 STATEREPORT_UPDATERES(fReportBuf
, kIOReportCopyChannelData
, result
);
6639 dest
->appendBytes(data2cpy
, size2cpy
);
6652 //*********************************************************************************
6653 // configureSimplePowerReport
6655 // Configures the IOSimpleReport for given channel id
6656 //*********************************************************************************
6657 IOReturn
IOService::configureSimplePowerReport(IOReportConfigureAction action
, void *result
)
6660 IOReturn rc
= kIOReturnSuccess
;
6663 return kIOReturnUnsupported
;
6665 if ( !fNumberOfPowerStates
)
6670 case kIOReportEnable
:
6671 case kIOReportDisable
:
6674 case kIOReportGetDimensions
:
6675 SIMPLEREPORT_UPDATERES(kIOReportGetDimensions
, result
);
6683 //*********************************************************************************
6684 // updateSimplePowerReport
6686 // Updates the IOSimpleReport for the given chanel id
6687 //*********************************************************************************
6688 IOReturn
IOService::updateSimplePowerReport( IOReportConfigureAction action
, void *result
, void *destination
)
6692 uint64_t buf
[SIMPLEREPORT_BUFSIZE
/sizeof(uint64_t)+1]; // Force a 8-byte alignment
6693 IOBufferMemoryDescriptor
*dest
= OSDynamicCast(IOBufferMemoryDescriptor
, (OSObject
*)destination
);
6694 IOReturn rc
= kIOReturnSuccess
;
6699 return kIOReturnUnsupported
;
6700 if ( !result
|| !dest
) return kIOReturnBadArgument
;
6702 if ( !fNumberOfPowerStates
)
6707 case kIOReportCopyChannelData
:
6709 SIMPLEREPORT_INIT(buf
, sizeof(buf
), getRegistryEntryID(), kPMCurrStateChID
, kIOReportCategoryPower
);
6711 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMPowerOn
)
6712 bits
|= kPMReportPowerOn
;
6713 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMDeviceUsable
)
6714 bits
|= kPMReportDeviceUsable
;
6715 if (fPowerStates
[fCurrentPowerState
].capabilityFlags
& kIOPMLowPower
)
6716 bits
|= kPMReportLowPower
;
6719 SIMPLEREPORT_SETVALUE(buf
, ((bits
& 0xff) << 8) | ((StateOrder(fMaxPowerState
) & 0xf) << 4) |
6720 (StateOrder(fCurrentPowerState
) & 0xf));
6722 SIMPLEREPORT_UPDATEPREP(buf
, data2cpy
, size2cpy
);
6723 if (size2cpy
> (dest
->getCapacity() - dest
->getLength())) {
6724 rc
= kIOReturnOverrun
;
6728 SIMPLEREPORT_UPDATERES(kIOReportCopyChannelData
, result
);
6729 dest
->appendBytes(data2cpy
, size2cpy
);
6738 return kIOReturnSuccess
;
6745 // MARK: Driver Overrides
6747 //*********************************************************************************
6748 // [public] setPowerState
6750 // Does nothing here. This should be implemented in a subclass driver.
6751 //*********************************************************************************
6753 IOReturn
IOService::setPowerState(
6754 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
6759 //*********************************************************************************
6760 // [public] maxCapabilityForDomainState
6762 // Finds the highest power state in the array whose input power requirement
6763 // is equal to the input parameter. Where a more intelligent decision is
6764 // possible, override this in the subclassed driver.
6765 //*********************************************************************************
6767 IOPMPowerStateIndex
IOService::getPowerStateForDomainFlags( IOPMPowerFlags flags
)
6769 IOPMPowerStateIndex stateIndex
;
6771 if (!fNumberOfPowerStates
)
6772 return kPowerStateZero
;
6774 for ( int order
= fNumberOfPowerStates
- 1; order
>= 0; order
-- )
6776 stateIndex
= fPowerStates
[order
].stateOrderToIndex
;
6778 if ( (flags
& fPowerStates
[stateIndex
].inputPowerFlags
) ==
6779 fPowerStates
[stateIndex
].inputPowerFlags
)
6784 return kPowerStateZero
;
6787 unsigned long IOService::maxCapabilityForDomainState( IOPMPowerFlags domainState
)
6789 return getPowerStateForDomainFlags(domainState
);
6792 //*********************************************************************************
6793 // [public] initialPowerStateForDomainState
6795 // Called to query the power state for the initial power transition.
6796 //*********************************************************************************
6798 unsigned long IOService::initialPowerStateForDomainState( IOPMPowerFlags domainState
)
6800 if (fResetPowerStateOnWake
&& (domainState
& kIOPMRootDomainState
))
6802 // Return lowest power state for any root power domain changes
6803 return kPowerStateZero
;
6806 return getPowerStateForDomainFlags(domainState
);
6809 //*********************************************************************************
6810 // [public] powerStateForDomainState
6812 // This method is not called from PM.
6813 //*********************************************************************************
6815 unsigned long IOService::powerStateForDomainState( IOPMPowerFlags domainState
)
6817 return getPowerStateForDomainFlags(domainState
);
6821 //*********************************************************************************
6822 // [deprecated] didYouWakeSystem
6824 // Does nothing here. This should be implemented in a subclass driver.
6825 //*********************************************************************************
6827 bool IOService::didYouWakeSystem( void )
6831 #endif /* !__LP64__ */
6833 //*********************************************************************************
6834 // [public] powerStateWillChangeTo
6836 // Does nothing here. This should be implemented in a subclass driver.
6837 //*********************************************************************************
6839 IOReturn
IOService::powerStateWillChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
6841 return kIOPMAckImplied
;
6844 //*********************************************************************************
6845 // [public] powerStateDidChangeTo
6847 // Does nothing here. This should be implemented in a subclass driver.
6848 //*********************************************************************************
6850 IOReturn
IOService::powerStateDidChangeTo( IOPMPowerFlags
, unsigned long, IOService
* )
6852 return kIOPMAckImplied
;
6855 //*********************************************************************************
6856 // [protected] powerChangeDone
6858 // Called from PM work loop thread.
6859 // Does nothing here. This should be implemented in a subclass policy-maker.
6860 //*********************************************************************************
6862 void IOService::powerChangeDone( unsigned long )
6867 //*********************************************************************************
6868 // [deprecated] newTemperature
6870 // Does nothing here. This should be implemented in a subclass driver.
6871 //*********************************************************************************
6873 IOReturn
IOService::newTemperature( long currentTemp
, IOService
* whichZone
)
6877 #endif /* !__LP64__ */
6879 //*********************************************************************************
6880 // [public] systemWillShutdown
6882 // System shutdown and restart notification.
6883 //*********************************************************************************
6885 void IOService::systemWillShutdown( IOOptionBits specifier
)
6887 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
6889 rootDomain
->acknowledgeSystemWillShutdown( this );
6893 // MARK: PM State Machine
6895 //*********************************************************************************
6896 // [private static] acquirePMRequest
6897 //*********************************************************************************
6900 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
6901 IOPMRequest
* active
)
6903 IOPMRequest
* request
;
6907 request
= IOPMRequest::create();
6910 request
->init( target
, requestType
);
6913 IOPMRequest
* root
= active
->getRootRequest();
6914 if (root
) request
->attachRootRequest(root
);
6919 PM_ERROR("%s: No memory for PM request type 0x%x\n",
6920 target
->getName(), (uint32_t) requestType
);
6925 //*********************************************************************************
6926 // [private static] releasePMRequest
6927 //*********************************************************************************
6929 void IOService::releasePMRequest( IOPMRequest
* request
)
6938 //*********************************************************************************
6939 // [private] submitPMRequest
6940 //*********************************************************************************
6942 void IOService::submitPMRequest( IOPMRequest
* request
)
6945 assert( gIOPMReplyQueue
);
6946 assert( gIOPMRequestQueue
);
6948 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6949 (long)request
->getType(), OBFUSCATE(request
),
6950 OBFUSCATE(request
->getTarget()), request
->getTarget()->getName(),
6951 OBFUSCATE(request
->fArg0
),
6952 OBFUSCATE(request
->fArg1
), OBFUSCATE(request
->fArg2
));
6954 if (request
->isReplyType())
6955 gIOPMReplyQueue
->queuePMRequest( request
);
6957 gIOPMRequestQueue
->queuePMRequest( request
);
6960 void IOService::submitPMRequest( IOPMRequest
** requests
, IOItemCount count
)
6963 assert( count
> 0 );
6964 assert( gIOPMRequestQueue
);
6966 for (IOItemCount i
= 0; i
< count
; i
++)
6968 IOPMRequest
* req
= requests
[i
];
6969 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6970 (long)req
->getType(), OBFUSCATE(req
),
6971 OBFUSCATE(req
->getTarget()), req
->getTarget()->getName(),
6972 OBFUSCATE(req
->fArg0
),
6973 OBFUSCATE(req
->fArg1
), OBFUSCATE(req
->fArg2
));
6976 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
6979 //*********************************************************************************
6980 // [private] servicePMRequestQueue
6982 // Called from IOPMRequestQueue::checkForWork().
6983 //*********************************************************************************
6985 bool IOService::servicePMRequestQueue(
6986 IOPMRequest
* request
,
6987 IOPMRequestQueue
* queue
)
6993 // Work queue will immediately execute the queue'd request if possible.
6994 // If execution blocks, the work queue will wait for a producer signal.
6995 // Only need to signal more when completing attached requests.
6997 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
7001 // Calling PM without PMinit() is not allowed, fail the request.
7003 PM_LOG("%s: PM not initialized\n", getName());
7004 fAdjustPowerScheduled
= false;
7005 more
= gIOPMFreeQueue
->queuePMRequest(request
);
7006 if (more
) gIOPMWorkQueue
->incrementProducerCount();
7010 //*********************************************************************************
7011 // [private] servicePMFreeQueue
7013 // Called from IOPMCompletionQueue::checkForWork().
7014 //*********************************************************************************
7016 bool IOService::servicePMFreeQueue(
7017 IOPMRequest
* request
,
7018 IOPMCompletionQueue
* queue
)
7020 bool more
= request
->getNextRequest();
7021 IOPMRequest
* root
= request
->getRootRequest();
7023 if (root
&& (root
!= request
))
7026 gIOPMWorkQueue
->incrementProducerCount();
7028 releasePMRequest( request
);
7032 //*********************************************************************************
7033 // [private] retirePMRequest
7035 // Called by IOPMWorkQueue to retire a completed request.
7036 //*********************************************************************************
7038 bool IOService::retirePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7040 assert(request
&& queue
);
7042 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
7043 request
->getType(), OBFUSCATE(request
),
7044 OBFUSCATE(this), getName(),
7045 fMachineState
, gIOPMBusyCount
);
7047 // Catch requests created by idleTimerExpired().
7049 if (request
->getType() == kIOPMRequestTypeActivityTickle
)
7051 uint32_t tickleFlags
= (uint32_t)(uintptr_t) request
->fArg1
;
7053 if ((tickleFlags
& kTickleTypePowerDrop
) && fIdleTimerPeriod
)
7057 else if (tickleFlags
== (kTickleTypeActivity
| kTickleTypePowerRise
))
7059 // Invalidate any idle power drop that got queued while
7060 // processing this request.
7061 fIdleTimerGeneration
++;
7065 // If the request is linked, then Work queue has already incremented its
7068 return (gIOPMFreeQueue
->queuePMRequest( request
));
7071 //*********************************************************************************
7072 // [private] isPMBlocked
7074 // Check if machine state transition is blocked.
7075 //*********************************************************************************
7077 bool IOService::isPMBlocked( IOPMRequest
* request
, int count
)
7082 if (kIOPM_Finished
== fMachineState
)
7085 if (kIOPM_DriverThreadCallDone
== fMachineState
)
7087 // 5 = kDriverCallInformPreChange
7088 // 6 = kDriverCallInformPostChange
7089 // 7 = kDriverCallSetPowerState
7090 // 8 = kRootDomainInformPreChange
7091 if (fDriverCallBusy
)
7092 reason
= 5 + fDriverCallReason
;
7096 // Waiting on driver's setPowerState() timeout.
7102 // Child or interested driver acks pending.
7103 if (fHeadNotePendingAcks
)
7108 // Waiting on apps or priority power interest clients.
7114 // Waiting on settle timer expiration.
7121 fWaitReason
= reason
;
7127 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
7128 request
->getType(), OBFUSCATE(request
),
7129 OBFUSCATE(this), getName(),
7130 fMachineState
, reason
);
7139 //*********************************************************************************
7140 // [private] servicePMRequest
7142 // Service a request from our work queue.
7143 //*********************************************************************************
7145 bool IOService::servicePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
7150 assert(request
&& queue
);
7152 while (isPMBlocked(request
, loop
++) == false)
7154 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
7155 request
->getType(), OBFUSCATE(request
),
7156 OBFUSCATE(this), getName(), fMachineState
);
7158 gIOPMRequest
= request
;
7161 // Every PM machine states must be handled in one of the cases below.
7163 switch ( fMachineState
)
7165 case kIOPM_Finished
:
7166 start_watchdog_timer();
7168 executePMRequest( request
);
7171 case kIOPM_OurChangeTellClientsPowerDown
:
7172 // Root domain might self cancel due to assertions.
7175 bool cancel
= (bool) fDoNotPowerDown
;
7176 getPMRootDomain()->askChangeDownDone(
7177 &fHeadNoteChangeFlags
, &cancel
);
7178 fDoNotPowerDown
= cancel
;
7181 // askChangeDown() done, was it vetoed?
7182 if (!fDoNotPowerDown
)
7184 // no, we can continue
7185 OurChangeTellClientsPowerDown();
7189 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7190 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7191 // yes, rescind the warning
7192 tellNoChangeDown(fHeadNotePowerState
);
7193 // mark the change note un-actioned
7194 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7200 case kIOPM_OurChangeTellUserPMPolicyPowerDown
:
7201 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7202 if (fDoNotPowerDown
)
7204 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7205 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7206 // yes, rescind the warning
7207 tellNoChangeDown(fHeadNotePowerState
);
7208 // mark the change note un-actioned
7209 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7214 OurChangeTellUserPMPolicyPowerDown();
7217 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
7218 // PMRD: LastCallBeforeSleep notify done
7219 // Non-PMRD: tellChangeDown/kNotifyApps done
7220 if (fDoNotPowerDown
)
7222 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7223 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7224 // no, tell clients we're back in the old state
7225 tellChangeUp(fCurrentPowerState
);
7226 // mark the change note un-actioned
7227 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7233 // yes, we can continue
7234 OurChangeTellPriorityClientsPowerDown();
7238 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
7239 OurChangeNotifyInterestedDriversWillChange();
7242 case kIOPM_OurChangeSetPowerState
:
7243 OurChangeSetPowerState();
7246 case kIOPM_OurChangeWaitForPowerSettle
:
7247 OurChangeWaitForPowerSettle();
7250 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
7251 OurChangeNotifyInterestedDriversDidChange();
7254 case kIOPM_OurChangeTellCapabilityDidChange
:
7255 OurChangeTellCapabilityDidChange();
7258 case kIOPM_OurChangeFinish
:
7262 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
7263 ParentChangeTellPriorityClientsPowerDown();
7266 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
7267 ParentChangeNotifyInterestedDriversWillChange();
7270 case kIOPM_ParentChangeSetPowerState
:
7271 ParentChangeSetPowerState();
7274 case kIOPM_ParentChangeWaitForPowerSettle
:
7275 ParentChangeWaitForPowerSettle();
7278 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
7279 ParentChangeNotifyInterestedDriversDidChange();
7282 case kIOPM_ParentChangeTellCapabilityDidChange
:
7283 ParentChangeTellCapabilityDidChange();
7286 case kIOPM_ParentChangeAcknowledgePowerChange
:
7287 ParentChangeAcknowledgePowerChange();
7290 case kIOPM_DriverThreadCallDone
:
7291 switch (fDriverCallReason
)
7293 case kDriverCallInformPreChange
:
7294 case kDriverCallInformPostChange
:
7295 notifyInterestedDriversDone();
7297 case kDriverCallSetPowerState
:
7298 notifyControllingDriverDone();
7300 case kRootDomainInformPreChange
:
7301 notifyRootDomainDone();
7304 panic("%s: bad call reason %x",
7305 getName(), fDriverCallReason
);
7309 case kIOPM_NotifyChildrenOrdered
:
7310 notifyChildrenOrdered();
7313 case kIOPM_NotifyChildrenDelayed
:
7314 notifyChildrenDelayed();
7317 case kIOPM_NotifyChildrenStart
:
7318 // pop notifyAll() state saved by notifyInterestedDriversDone()
7323 case kIOPM_SyncTellClientsPowerDown
:
7324 // Root domain might self cancel due to assertions.
7327 bool cancel
= (bool) fDoNotPowerDown
;
7328 getPMRootDomain()->askChangeDownDone(
7329 &fHeadNoteChangeFlags
, &cancel
);
7330 fDoNotPowerDown
= cancel
;
7332 if (!fDoNotPowerDown
)
7334 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
7335 fOutOfBandParameter
= kNotifyApps
;
7336 tellChangeDown(fHeadNotePowerState
);
7340 // Cancelled by IOPMrootDomain::askChangeDownDone() or
7341 // askChangeDown/kNotifyApps
7342 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7343 PM_ERROR("%s: idle cancel, state %u\n", fName
, fMachineState
);
7344 tellNoChangeDown(fHeadNotePowerState
);
7345 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7350 case kIOPM_SyncTellPriorityClientsPowerDown
:
7351 // PMRD: tellChangeDown/kNotifyApps done, was it cancelled?
7352 if (!fDoNotPowerDown
)
7354 fMachineState
= kIOPM_SyncNotifyWillChange
;
7355 fOutOfBandParameter
= kNotifyPriority
;
7356 tellChangeDown(fHeadNotePowerState
);
7360 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7361 PM_ERROR("%s: idle revert, state %u\n", fName
, fMachineState
);
7362 tellChangeUp(fCurrentPowerState
);
7363 fHeadNoteChangeFlags
|= kIOPMNotDone
;
7368 case kIOPM_SyncNotifyWillChange
:
7369 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
)
7371 fMachineState
= kIOPM_SyncFinish
;
7374 fMachineState
= kIOPM_SyncNotifyDidChange
;
7375 fDriverCallReason
= kDriverCallInformPreChange
;
7379 case kIOPM_SyncNotifyDidChange
:
7380 fIsPreChange
= false;
7382 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7384 fMachineState
= kIOPM_SyncFinish
;
7388 assert(IS_ROOT_DOMAIN
);
7389 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
7392 fDriverCallReason
= kDriverCallInformPostChange
;
7396 case kIOPM_SyncTellCapabilityDidChange
:
7397 tellSystemCapabilityChange( kIOPM_SyncFinish
);
7400 case kIOPM_SyncFinish
:
7401 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
7402 ParentChangeAcknowledgePowerChange();
7407 case kIOPM_TellCapabilityChangeDone
:
7410 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
)
7412 MS_POP(); // tellSystemCapabilityChange()
7415 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
7419 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
)
7421 MS_POP(); // tellSystemCapabilityChange()
7424 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
7426 tellClientsWithResponse( fOutOfBandMessage
);
7430 panic("servicePMWorkQueue: unknown machine state %x",
7436 if (fMachineState
== kIOPM_Finished
)
7438 stop_watchdog_timer();
7447 //*********************************************************************************
7448 // [private] executePMRequest
7449 //*********************************************************************************
7451 void IOService::executePMRequest( IOPMRequest
* request
)
7453 assert( kIOPM_Finished
== fMachineState
);
7455 switch (request
->getType())
7457 case kIOPMRequestTypePMStop
:
7458 handlePMstop( request
);
7461 case kIOPMRequestTypeAddPowerChild1
:
7462 addPowerChild1( request
);
7465 case kIOPMRequestTypeAddPowerChild2
:
7466 addPowerChild2( request
);
7469 case kIOPMRequestTypeAddPowerChild3
:
7470 addPowerChild3( request
);
7473 case kIOPMRequestTypeRegisterPowerDriver
:
7474 handleRegisterPowerDriver( request
);
7477 case kIOPMRequestTypeAdjustPowerState
:
7478 fAdjustPowerScheduled
= false;
7482 case kIOPMRequestTypePowerDomainWillChange
:
7483 handlePowerDomainWillChangeTo( request
);
7486 case kIOPMRequestTypePowerDomainDidChange
:
7487 handlePowerDomainDidChangeTo( request
);
7490 case kIOPMRequestTypeRequestPowerState
:
7491 case kIOPMRequestTypeRequestPowerStateOverride
:
7492 handleRequestPowerState( request
);
7495 case kIOPMRequestTypePowerOverrideOnPriv
:
7496 case kIOPMRequestTypePowerOverrideOffPriv
:
7497 handlePowerOverrideChanged( request
);
7500 case kIOPMRequestTypeActivityTickle
:
7501 handleActivityTickle( request
);
7504 case kIOPMRequestTypeSynchronizePowerTree
:
7505 handleSynchronizePowerTree( request
);
7508 case kIOPMRequestTypeSetIdleTimerPeriod
:
7510 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7511 fNextIdleTimerPeriod
= fIdleTimerPeriod
;
7512 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
7517 case kIOPMRequestTypeIgnoreIdleTimer
:
7518 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7522 panic("executePMRequest: unknown request type %x", request
->getType());
7526 //*********************************************************************************
7527 // [private] servicePMReplyQueue
7528 //*********************************************************************************
7530 bool IOService::servicePMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7534 assert( request
&& queue
);
7535 assert( request
->isReplyType() );
7537 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7538 request
->getType(), OBFUSCATE(request
),
7539 OBFUSCATE(this), getName(), fMachineState
);
7541 switch ( request
->getType() )
7543 case kIOPMRequestTypeAllowPowerChange
:
7544 case kIOPMRequestTypeCancelPowerChange
:
7545 // Check if we are expecting this response.
7546 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7547 (int)(uintptr_t) request
->fArg1
))
7549 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
7551 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7552 // flag is set. Only root domain will set this flag.
7553 // However, there is one exception to this rule. User-space PM
7554 // policy may choose to cancel sleep even after all clients have
7555 // been notified that we will lower power.
7557 if ((fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7558 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7559 || ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0))
7561 fDoNotPowerDown
= true;
7563 OSString
* name
= (OSString
*) request
->fArg2
;
7564 getPMRootDomain()->pmStatsRecordApplicationResponse(
7565 gIOPMStatsApplicationResponseCancel
,
7566 name
? name
->getCStringNoCopy() : "", 0,
7567 0, (int)(uintptr_t) request
->fArg1
, 0);
7574 cleanClientResponses(false);
7578 // OSString containing app name in Arg2 must be released.
7579 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
7581 OSObject
* obj
= (OSObject
*) request
->fArg2
;
7582 if (obj
) obj
->release();
7586 case kIOPMRequestTypeAckPowerChange
:
7587 more
= handleAcknowledgePowerChange( request
);
7590 case kIOPMRequestTypeAckSetPowerState
:
7591 if (fDriverTimer
== -1)
7593 // driver acked while setPowerState() call is in-flight.
7594 // take this ack, return value from setPowerState() is irrelevant.
7595 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
7596 (uintptr_t) this, fDriverTimer
);
7599 else if (fDriverTimer
> 0)
7601 // expected ack, stop the timer
7604 #if LOG_SETPOWER_TIMES
7605 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
7606 if (nsec
> LOG_SETPOWER_TIMES
) {
7607 getPMRootDomain()->pmStatsRecordApplicationResponse(
7608 gIOPMStatsDriverPSChangeSlow
,
7609 fName
, kDriverCallSetPowerState
, NS_TO_MS(nsec
), 0, NULL
, fHeadNotePowerState
);
7612 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
7619 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
7623 case kIOPMRequestTypeInterestChanged
:
7624 handleInterestChanged( request
);
7628 case kIOPMRequestTypeIdleCancel
:
7629 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
7630 || (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
)
7631 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7632 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
7633 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
7635 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7636 PM_LOG2("%s: cancel from machine state %d\n",
7637 getName(), fMachineState
);
7638 fDoNotPowerDown
= true;
7639 // Stop waiting for app replys.
7640 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
7641 (fMachineState
== kIOPM_OurChangeTellUserPMPolicyPowerDown
) ||
7642 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
7643 cleanClientResponses(false);
7648 case kIOPMRequestTypeChildNotifyDelayCancel
:
7649 if (fMachineState
== kIOPM_NotifyChildrenDelayed
)
7651 PM_LOG2("%s: delay notify cancelled\n", getName());
7652 notifyChildrenDelayed();
7657 panic("servicePMReplyQueue: unknown reply type %x",
7658 request
->getType());
7661 more
|= gIOPMFreeQueue
->queuePMRequest(request
);
7663 gIOPMWorkQueue
->incrementProducerCount();
7668 //*********************************************************************************
7669 // [private] assertPMDriverCall / deassertPMDriverCall
7670 //*********************************************************************************
7672 bool IOService::assertPMDriverCall(
7673 IOPMDriverCallEntry
* entry
,
7674 IOOptionBits options
,
7675 IOPMinformee
* inform
)
7677 IOService
* target
= 0;
7685 if (fLockedFlags
.PMStop
)
7690 if (((options
& kIOPMADC_NoInactiveCheck
) == 0) && isInactive())
7697 if (!inform
->active
)
7701 target
= inform
->whatObject
;
7702 if (target
->isInactive())
7708 entry
->thread
= current_thread();
7709 entry
->target
= target
;
7710 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7719 void IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
7721 bool wakeup
= false;
7725 assert( !queue_empty(&fPMDriverCallQueue
) );
7726 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7727 if (fLockedFlags
.PMDriverCallWait
)
7735 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
7738 void IOService::waitForPMDriverCall( IOService
* target
)
7740 const IOPMDriverCallEntry
* entry
;
7741 thread_t thread
= current_thread();
7742 AbsoluteTime deadline
;
7749 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
7751 // Target of interested driver call
7752 if (target
&& (target
!= entry
->target
))
7755 if (entry
->thread
== thread
)
7759 PM_LOG("%s: %s(%s) on PM thread\n",
7760 fName
, __FUNCTION__
, target
? target
->getName() : "");
7761 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
7762 fName
, __FUNCTION__
, target
? target
->getName() : "");
7774 fLockedFlags
.PMDriverCallWait
= true;
7775 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
7776 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
7777 fLockedFlags
.PMDriverCallWait
= false;
7778 if (THREAD_TIMED_OUT
== waitResult
)
7780 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
7787 //*********************************************************************************
7788 // [private] Debug helpers
7789 //*********************************************************************************
7791 const char * IOService::getIOMessageString( uint32_t msg
)
7793 #define MSG_ENTRY(x) {(int) x, #x}
7795 static const IONamedValue msgNames
[] = {
7796 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
7797 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
7798 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
7799 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
7800 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
7801 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
7802 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
7803 MSG_ENTRY( kIOMessageCanSystemSleep
),
7804 MSG_ENTRY( kIOMessageSystemWillSleep
),
7805 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
7806 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
7807 MSG_ENTRY( kIOMessageSystemWillRestart
),
7808 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
7809 MSG_ENTRY( kIOMessageSystemCapabilityChange
),
7810 MSG_ENTRY( kIOPMMessageLastCallBeforeSleep
)
7813 return IOFindNameForValue(msg
, msgNames
);
7818 // MARK: IOPMRequest
7820 //*********************************************************************************
7821 // IOPMRequest Class
7823 // Requests from PM clients, and also used for inter-object messaging within PM.
7824 //*********************************************************************************
7826 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
7828 IOPMRequest
* IOPMRequest::create( void )
7830 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
7831 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
7839 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
7841 if (!IOCommand::init())
7847 fCompletionStatus
= kIOReturnSuccess
;
7856 void IOPMRequest::reset( void )
7858 assert( fWorkWaitCount
== 0 );
7859 assert( fFreeWaitCount
== 0 );
7861 detachNextRequest();
7862 detachRootRequest();
7864 fType
= kIOPMRequestTypeInvalid
;
7867 if (fCompletionAction
)
7869 fCompletionAction(fCompletionTarget
, fCompletionParam
, fCompletionStatus
);
7880 bool IOPMRequest::attachNextRequest( IOPMRequest
* next
)
7886 // Postpone the execution of the next request after
7888 fRequestNext
= next
;
7889 fRequestNext
->fWorkWaitCount
++;
7890 #if LOG_REQUEST_ATTACH
7891 PM_LOG("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7892 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestNext
),
7893 (uint32_t) fRequestNext
->fType
,
7894 (uint32_t) fRequestNext
->fWorkWaitCount
,
7895 fTarget
->getName());
7902 bool IOPMRequest::detachNextRequest( void )
7908 assert(fRequestNext
->fWorkWaitCount
);
7909 if (fRequestNext
->fWorkWaitCount
)
7910 fRequestNext
->fWorkWaitCount
--;
7911 #if LOG_REQUEST_ATTACH
7912 PM_LOG("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7913 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestNext
),
7914 (uint32_t) fRequestNext
->fType
,
7915 (uint32_t) fRequestNext
->fWorkWaitCount
,
7916 fTarget
->getName());
7924 bool IOPMRequest::attachRootRequest( IOPMRequest
* root
)
7930 // Delay the completion of the root request after
7932 fRequestRoot
= root
;
7933 fRequestRoot
->fFreeWaitCount
++;
7934 #if LOG_REQUEST_ATTACH
7935 PM_LOG("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7936 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
7937 (uint32_t) fRequestRoot
->fType
,
7938 (uint32_t) fRequestRoot
->fFreeWaitCount
,
7939 fTarget
->getName());
7946 bool IOPMRequest::detachRootRequest( void )
7952 assert(fRequestRoot
->fFreeWaitCount
);
7953 if (fRequestRoot
->fFreeWaitCount
)
7954 fRequestRoot
->fFreeWaitCount
--;
7955 #if LOG_REQUEST_ATTACH
7956 PM_LOG("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7957 OBFUSCATE(this), (uint32_t) fType
, OBFUSCATE(fRequestRoot
),
7958 (uint32_t) fRequestRoot
->fType
,
7959 (uint32_t) fRequestRoot
->fFreeWaitCount
,
7960 fTarget
->getName());
7969 // MARK: IOPMRequestQueue
7971 //*********************************************************************************
7972 // IOPMRequestQueue Class
7974 // Global queues. Queues are created once and never released.
7975 //*********************************************************************************
7977 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
7979 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
7981 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
7982 if (me
&& !me
->init(inOwner
, inAction
))
7990 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
7992 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
7995 queue_init(&fQueue
);
7996 fLock
= IOLockAlloc();
7997 return (fLock
!= 0);
8000 void IOPMRequestQueue::free( void )
8007 return IOEventSource::free();
8010 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
8014 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
8015 IOLockUnlock(fLock
);
8016 if (workLoop
) signalWorkAvailable();
8020 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
8024 assert(requests
&& count
);
8030 queue_enter(&fQueue
, next
, IOPMRequest
*, fCommandChain
);
8032 IOLockUnlock(fLock
);
8033 if (workLoop
) signalWorkAvailable();
8036 bool IOPMRequestQueue::checkForWork( void )
8038 Action dqAction
= (Action
) action
;
8039 IOPMRequest
* request
;
8043 IOLockLock( fLock
);
8045 while (!queue_empty(&fQueue
))
8047 queue_remove_first( &fQueue
, request
, IOPMRequest
*, fCommandChain
);
8048 IOLockUnlock( fLock
);
8049 target
= request
->getTarget();
8051 more
|= (*dqAction
)( target
, request
, this );
8052 IOLockLock( fLock
);
8055 IOLockUnlock( fLock
);
8060 // MARK: IOPMWorkQueue
8062 //*********************************************************************************
8063 // IOPMWorkQueue Class
8065 // Queue of IOServicePM objects with busy IOPMRequest(s).
8066 //*********************************************************************************
8068 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
8071 IOPMWorkQueue::create( IOService
* inOwner
, Action work
, Action retire
)
8073 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
8074 if (me
&& !me
->init(inOwner
, work
, retire
))
8082 bool IOPMWorkQueue::init( IOService
* inOwner
, Action work
, Action retire
)
8084 if (!work
|| !retire
||
8085 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
8088 queue_init(&fWorkQueue
);
8091 fRetireAction
= retire
;
8092 fConsumerCount
= fProducerCount
= 0;
8097 bool IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
8104 assert( onThread() );
8105 assert( queue_next(&request
->fCommandChain
) ==
8106 queue_prev(&request
->fCommandChain
) );
8110 // Add new request to the tail of the per-service request queue.
8111 // Then immediately check the request queue to minimize latency
8112 // if the queue was empty.
8114 empty
= queue_empty(&pwrMgt
->RequestHead
);
8115 queue_enter(&pwrMgt
->RequestHead
, request
, IOPMRequest
*, fCommandChain
);
8118 more
= checkRequestQueue(&pwrMgt
->RequestHead
, &empty
);
8121 // New Request is blocked, add IOServicePM to work queue.
8122 assert( queue_next(&pwrMgt
->WorkChain
) ==
8123 queue_prev(&pwrMgt
->WorkChain
) );
8125 queue_enter(&fWorkQueue
, pwrMgt
, IOServicePM
*, WorkChain
);
8127 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
8128 fQueueLength
, pwrMgt
->Name
, OBFUSCATE(pwrMgt
));
8135 bool IOPMWorkQueue::checkRequestQueue( queue_head_t
* queue
, bool * empty
)
8137 IOPMRequest
* request
;
8142 assert(!queue_empty(queue
));
8144 request
= (IOPMRequest
*) queue_first(queue
);
8145 if (request
->isWorkBlocked())
8146 break; // cannot start, blocked on attached request
8148 target
= request
->getTarget();
8149 done
= (*fWorkAction
)( target
, request
, this );
8151 break; // work started, blocked on PM state machine
8153 assert(gIOPMBusyCount
> 0);
8157 queue_remove_first(queue
, request
, IOPMRequest
*, fCommandChain
);
8158 more
|= (*fRetireAction
)( target
, request
, this );
8159 done
= queue_empty(queue
);
8166 // Retired request blocks another request, since the
8167 // blocked request may reside in the work queue, we
8168 // must bump the producer count to avoid work stall.
8175 bool IOPMWorkQueue::checkForWork( void )
8177 IOServicePM
* entry
;
8182 #if WORK_QUEUE_STATS
8183 fStatCheckForWork
++;
8186 // Each producer signal triggers a full iteration over
8187 // all IOServicePM entries in the work queue.
8189 while (fConsumerCount
!= fProducerCount
)
8191 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
8192 fProducerCount
, fConsumerCount
);
8194 fConsumerCount
= fProducerCount
;
8196 #if WORK_QUEUE_STATS
8197 if (queue_empty(&fWorkQueue
))
8203 uint32_t cachedWorkCount
= gIOPMWorkCount
;
8206 entry
= (IOServicePM
*) queue_first(&fWorkQueue
);
8207 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
))
8209 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
8211 // Get next entry, points to head if current entry is last.
8212 next
= (IOServicePM
*) queue_next(&entry
->WorkChain
);
8214 // if request queue is empty, remove IOServicePM from queue.
8217 assert(fQueueLength
);
8218 if (fQueueLength
) fQueueLength
--;
8219 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
8220 fQueueLength
, entry
->Name
, OBFUSCATE(entry
));
8221 queue_remove(&fWorkQueue
, entry
, IOServicePM
*, WorkChain
);
8226 #if WORK_QUEUE_STATS
8227 if (cachedWorkCount
== gIOPMWorkCount
)
8235 void IOPMWorkQueue::signalWorkAvailable( void )
8238 IOEventSource::signalWorkAvailable();
8241 void IOPMWorkQueue::incrementProducerCount( void )
8247 // MARK: IOPMCompletionQueue
8249 //*********************************************************************************
8250 // IOPMCompletionQueue Class
8251 //*********************************************************************************
8253 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
8255 IOPMCompletionQueue
*
8256 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
8258 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
8259 if (me
&& !me
->init(inOwner
, inAction
))
8267 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
8269 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
8272 queue_init(&fQueue
);
8276 bool IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
8281 // unblock dependent request
8282 more
= request
->detachNextRequest();
8283 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
8287 bool IOPMCompletionQueue::checkForWork( void )
8289 Action dqAction
= (Action
) action
;
8290 IOPMRequest
* request
;
8295 request
= (IOPMRequest
*) queue_first(&fQueue
);
8296 while (!queue_end(&fQueue
, (queue_entry_t
) request
))
8298 next
= (IOPMRequest
*) queue_next(&request
->fCommandChain
);
8299 if (!request
->isFreeBlocked())
8301 queue_remove(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
8302 target
= request
->getTarget();
8304 more
|= (*dqAction
)( target
, request
, this );
8313 // MARK: IOServicePM
8315 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
8317 //*********************************************************************************
8320 // Serialize IOServicePM for debugging.
8321 //*********************************************************************************
8324 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
8326 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
8329 dict
->setObject(key
, num
);
8334 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
) const
8336 OSDictionary
* dict
;
8338 int powerClamp
= -1;
8341 if (IdleTimerPeriod
)
8344 if (PMActions
.parameter
& kPMActionsFlagLimitPower
)
8348 if (PMActions
.parameter
&
8349 (kPMActionsFlagIsDisplayWrangler
| kPMActionsFlagIsGraphicsDevice
))
8353 #if WORK_QUEUE_STATS
8354 if (gIOPMRootNode
== ControllingDriver
)
8359 dict
= OSDictionary::withDictionary(
8360 PowerClients
, PowerClients
->getCount() + dictSize
);
8362 dict
= OSDictionary::withCapacity(dictSize
);
8366 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
8367 setPMProperty(dict
, "CapabilityFlags", CurrentCapabilityFlags
);
8368 if (NumberOfPowerStates
)
8369 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
-1);
8370 if (DesiredPowerState
!= CurrentPowerState
)
8371 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
8372 if (kIOPM_Finished
!= MachineState
)
8373 setPMProperty(dict
, "MachineState", MachineState
);
8374 if (DeviceOverrideEnabled
)
8375 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
8376 if (powerClamp
>= 0)
8377 setPMProperty(dict
, "PowerClamp", powerClamp
);
8379 if (IdleTimerPeriod
)
8385 clock_get_uptime(&now
);
8387 // The idle timer period in milliseconds
8388 setPMProperty(dict
, "IdleTimerPeriod", NextIdleTimerPeriod
* 1000ULL);
8390 // Number of tickles since the last idle timer expiration
8391 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
8393 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
8395 // Milliseconds since the last activity tickle
8397 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
8398 absolutetime_to_nanoseconds(delta
, &nsecs
);
8399 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
8402 if (!IdleTimerStopped
&& AbsoluteTime_to_scalar(&IdleTimerStartTime
))
8404 // Idle timer elapsed time in milliseconds
8406 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
8407 absolutetime_to_nanoseconds(delta
, &nsecs
);
8408 setPMProperty(dict
, "IdleTimerElapsedTime", NS_TO_MS(nsecs
));
8412 #if WORK_QUEUE_STATS
8413 if (gIOPMRootNode
== Owner
)
8415 setPMProperty(dict
, "WQ-CheckForWork",
8416 gIOPMWorkQueue
->fStatCheckForWork
);
8417 setPMProperty(dict
, "WQ-ScanEntries",
8418 gIOPMWorkQueue
->fStatScanEntries
);
8419 setPMProperty(dict
, "WQ-QueueEmpty",
8420 gIOPMWorkQueue
->fStatQueueEmpty
);
8421 setPMProperty(dict
, "WQ-NoWorkDone",
8422 gIOPMWorkQueue
->fStatNoWorkDone
);
8426 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
)
8428 // Don't report advisory tickle when it has no influence
8429 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
8432 ok
= dict
->serialize(s
);
8436 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
8439 bool IOServicePM::serialize( OSSerialize
* s
) const
8441 IOReturn ret
= kIOReturnNotReady
;
8443 if (gIOPMWatchDogThread
== current_thread())
8445 // Calling without lock as this data is collected for debug purpose, before reboot.
8446 // The workloop is probably already hung in state machine.
8447 ret
= gatedSerialize(s
);
8449 else if (gIOPMWorkLoop
)
8451 ret
= gIOPMWorkLoop
->runAction(
8452 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
8453 (OSObject
*) this, (void *) s
);
8456 return (kIOReturnSuccess
== ret
);
8459 void IOServicePM::pmPrint(
8462 uintptr_t param2
) const
8464 gPlatform
->PMLog(Name
, event
, param1
, param2
);
8467 void IOServicePM::pmTrace(
8470 uintptr_t param2
) const
8472 const char * who
= Name
;
8473 uint64_t regId
= Owner
->getRegistryEntryID();
8476 static const uint32_t sStartStopBitField
[] =
8477 { 0x00000000, 0x00000040 }; // Only Program Hardware so far
8479 // Arcane formula from Hacker's Delight by Warren
8480 // abs(x) = ((int) x >> 31) ^ (x + ((int) x >> 31))
8481 uint32_t sgnevent
= ((int) event
>> 31);
8482 uint32_t absevent
= sgnevent
^ (event
+ sgnevent
);
8483 uint32_t code
= IODBG_POWER(absevent
);
8485 uint32_t bit
= 1 << (absevent
& 0x1f);
8486 if ((absevent
< (sizeof(sStartStopBitField
) * 8)) &&
8487 (sStartStopBitField
[absevent
>> 5] & bit
))
8489 // Or in the START or END bits, Start = 1 & END = 2
8490 // If sgnevent == 0 then START - 0 => START
8491 // else if sgnevent == -1 then START - -1 => END
8492 code
|= DBG_FUNC_START
- sgnevent
;
8495 // Copy the first characters of the name into an uintptr_t
8496 for (uint32_t i
= 0; (i
< sizeof(uintptr_t) && who
[i
] != 0); i
++)
8498 ((char *) &name
)[sizeof(uintptr_t) - i
- 1] = who
[i
];
8501 IOTimeStampConstant(code
, name
, (uintptr_t) regId
, param1
, param2
);