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@
32 #include <IOKit/assert.h>
33 #include <IOKit/IOKitDebug.h>
34 #include <IOKit/IOLib.h>
35 #include <IOKit/IOMessage.h>
36 #include <IOKit/IOPlatformExpert.h>
37 #include <IOKit/IOService.h>
38 #include <IOKit/IOEventSource.h>
39 #include <IOKit/IOWorkLoop.h>
40 #include <IOKit/IOCommand.h>
42 #include <IOKit/pwr_mgt/IOPMlog.h>
43 #include <IOKit/pwr_mgt/IOPMinformee.h>
44 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
45 #include <IOKit/pwr_mgt/IOPowerConnection.h>
46 #include <IOKit/pwr_mgt/RootDomain.h>
47 #include <IOKit/pwr_mgt/IOPMPrivate.h>
50 #include <libkern/OSDebug.h>
52 // Required for notification instrumentation
53 #include "IOServicePrivate.h"
54 #include "IOServicePMPrivate.h"
55 #include "IOKitKernelInternal.h"
57 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
58 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
59 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
60 static void tellAppClientApplier(OSObject
* object
, void * arg
);
62 static uint64_t computeTimeDeltaNS( const AbsoluteTime
* start
)
67 clock_get_uptime(&now
);
68 SUB_ABSOLUTETIME(&now
, start
);
69 absolutetime_to_nanoseconds(now
, &nsec
);
74 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
77 // Container class for recording system power events
78 OSDefineMetaClassAndStructors( PMEventDetails
, OSObject
);
80 //******************************************************************************
82 //******************************************************************************
84 static bool gIOPMInitialized
= false;
85 static uint32_t gIOPMBusyCount
= 0;
86 static uint32_t gIOPMWorkCount
= 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 IOPlatformExpert
* gPlatform
= 0;
94 static IOService
* gIOPMRootNode
= 0;
96 static const OSSymbol
* gIOPMPowerClientDevice
= 0;
97 static const OSSymbol
* gIOPMPowerClientDriver
= 0;
98 static const OSSymbol
* gIOPMPowerClientChildProxy
= 0;
99 static const OSSymbol
* gIOPMPowerClientChildren
= 0;
101 static uint32_t getPMRequestType( void )
103 uint32_t type
= kIOPMRequestTypeInvalid
;
105 type
= gIOPMRequest
->getType();
109 //******************************************************************************
111 //******************************************************************************
113 #define PM_ERROR(x...) do { kprintf(x); IOLog(x); } while (false)
114 #define PM_LOG(x...) do { kprintf(x); } while (false)
116 #define PM_LOG1(x...) do { \
117 if (kIOLogDebugPower & gIOKitDebug) \
118 kprintf(x); } while (false)
120 #define PM_LOG2(x...) do { \
121 if (kIOLogDebugPower & gIOKitDebug) \
122 kprintf(x); } while (false)
125 #define PM_LOG3(x...) do { kprintf(x); } while (false)
127 #define PM_LOG3(x...)
130 #define RD_LOG(x...) do { \
131 if ((kIOLogPMRootDomain & gIOKitDebug) && \
132 (getPMRootDomain() == this)) \
133 kprintf("PMRD: " x); } while (false)
135 #define PM_ASSERT_IN_GATE(x) \
137 assert(gIOPMWorkLoop->inGate()); \
140 #define PM_LOCK() IOLockLock(fPMLock)
141 #define PM_UNLOCK() IOLockUnlock(fPMLock)
142 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
143 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
145 #define ns_per_us 1000
146 #define k30seconds (30*1000000)
147 #define kMinAckTimeoutTicks (10*1000000)
148 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
149 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
150 #define kPwrMgtKey "IOPowerManagement"
152 #define OUR_PMLog(t, a, b) \
153 do { gPlatform->PMLog( fName, t, a, b); } while(0)
155 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
156 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
159 #define SUPPORT_IDLE_CANCEL 1
162 #define kIOPMPowerStateMax 0xFFFFFFFF
164 #define IS_PM_ROOT (this == gIOPMRootNode)
165 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
166 #define IS_POWER_DROP (fHeadNotePowerState < fCurrentPowerState)
167 #define IS_POWER_RISE (fHeadNotePowerState > fCurrentPowerState)
169 // log setPowerStates longer than (ns):
170 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
171 // log app responses longer than (ns):
172 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
173 // use message tracer to log messages longer than (ns):
174 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
177 kReserveDomainPower
= 1
181 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
182 assert(kIOPM_BadMachineState != n); \
183 fSavedMachineState = n; } while (false)
186 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
187 fMachineState = fSavedMachineState; \
188 fSavedMachineState = kIOPM_BadMachineState; } while (false)
190 #define PM_ACTION_0(a) \
191 do { if (fPMActions.a) { \
192 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
195 #define PM_ACTION_2(a, x, y) \
196 do { if (fPMActions.a) { \
197 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y); } \
200 //*********************************************************************************
203 // Check kgmacros after modifying machine states.
204 //*********************************************************************************
209 kIOPM_OurChangeTellClientsPowerDown
= 1,
210 kIOPM_OurChangeTellPriorityClientsPowerDown
= 2,
211 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 3,
212 kIOPM_OurChangeSetPowerState
= 4,
213 kIOPM_OurChangeWaitForPowerSettle
= 5,
214 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 6,
215 kIOPM_OurChangeTellCapabilityDidChange
= 7,
216 kIOPM_OurChangeFinish
= 8,
218 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
219 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
220 kIOPM_ParentChangeSetPowerState
= 12,
221 kIOPM_ParentChangeWaitForPowerSettle
= 13,
222 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
223 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
224 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
226 kIOPM_NotifyChildrenStart
= 17,
227 kIOPM_NotifyChildrenOrdered
= 18,
228 kIOPM_NotifyChildrenDelayed
= 19,
229 kIOPM_SyncTellClientsPowerDown
= 20,
230 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
231 kIOPM_SyncNotifyWillChange
= 22,
232 kIOPM_SyncNotifyDidChange
= 23,
233 kIOPM_SyncTellCapabilityDidChange
= 24,
234 kIOPM_SyncFinish
= 25,
235 kIOPM_TellCapabilityChangeDone
= 26,
236 kIOPM_DriverThreadCallDone
= 27,
238 kIOPM_BadMachineState
= 0xFFFFFFFF
243 Power Management defines a few roles that drivers can play in their own,
244 and other drivers', power management. We briefly define those here.
246 Many drivers implement their policy maker and power controller within the same
247 IOService object, but that is not required.
250 * Virtual IOService PM methods a "policy maker" may implement
251 * maxCapabilityForDomainState()
252 * initialPowerStateForDomainState()
253 * powerStateForDomainState()
255 * Virtual IOService PM methods a "policy maker" may CALL
258 == Power Controller ==
259 * Virtual IOService PM methods a "power controller" may implement
262 * Virtual IOService PM methods a "power controller" may CALL
264 * registerPowerDriver()
266 =======================
267 There are two different kinds of power state changes.
268 * One is initiated by a subclassed device object which has either decided
269 to change power state, or its controlling driver has suggested it, or
270 some other driver wants to use the idle device and has asked it to become
272 * The second kind of power state change is initiated by the power domain
274 The two are handled through different code paths.
276 We maintain a queue of "change notifications," or change notes.
277 * Usually the queue is empty.
278 * When it isn't, usually there is one change note in it
279 * It's possible to have more than one power state change pending at one
280 time, so a queue is implemented.
282 * The subclass device decides it's idle and initiates a change to a lower
283 power state. This causes interested parties to be notified, but they
284 don't all acknowledge right away. This causes the change note to sit
285 in the queue until all the acks are received. During this time, the
286 device decides it isn't idle anymore and wants to raise power back up
287 again. This change can't be started, however, because the previous one
288 isn't complete yet, so the second one waits in the queue. During this
289 time, the parent decides to lower or raise the power state of the entire
290 power domain and notifies the device, and that notification goes into
291 the queue, too, and can't be actioned until the others are.
294 This is how a power change initiated by the subclass device is handled:
295 -> First, all interested parties are notified of the change via their
296 powerStateWillChangeTo method. If they all don't acknowledge via return
297 code, then we have to wait. If they do, or when they finally all
298 acknowledge via our acknowledgePowerChange method, then we can continue.
299 -> We call the controlling driver, instructing it to change to the new state
300 -> Then we wait for power to settle. If there is no settling-time, or after
302 -> we notify interested parties again, this time via their
303 powerStateDidChangeTo methods.
304 -> When they have all acked, we're done.
305 If we lowered power and don't need the power domain to be in its current power
306 state, we suggest to the parent that it lower the power domain state.
308 == PowerDomainDownInitiated ==
309 How a change to a lower power domain state initiated by the parent is handled:
310 -> First, we figure out what power state we will be in when the new domain
312 -> Then all interested parties are notified that we are moving to that new
314 -> When they have acknowledged, we call the controlling driver to assume
315 that state and we wait for power to settle.
316 -> Then we acknowledge our preparedness to our parent. When all its
317 interested parties have acknowledged,
318 -> it lowers power and then notifies its interested parties again.
319 -> When we get this call, we notify our interested parties that the power
320 state has changed, and when they have all acknowledged, we're done.
322 == PowerDomainUpInitiated ==
323 How a change to a higher power domain state initiated by the parent is handled:
324 -> We figure out what power state we will be in when the new domain state is
326 -> If it is different from our current state we acknowledge the parent.
327 -> When all the parent's interested parties have acknowledged, it raises
328 power in the domain and waits for power to settle.
329 -> Then it notifies everyone that the new state has been reached.
330 -> When we get this call, we call the controlling driver, instructing it to
331 assume the new state, and wait for power to settle.
332 -> Then we notify our interested parties. When they all acknowledge we are
335 In either of the two power domain state cases above, it is possible that we
336 will not be changing state even though the domain is.
338 * A change to a lower domain state may not affect us because we are already
339 in a low enough state,
340 * We will not take advantage of a change to a higher domain state, because
341 we have no need of the higher power. In such cases, there is nothing to
342 do but acknowledge the parent. So when the parent calls our
343 powerDomainWillChange method, and we decide that we will not be changing
344 state, we merely acknowledge the parent, via return code, and wait.
345 When the parent subsequently calls powerStateDidChange, we acknowledge again
346 via return code, and the change is complete.
348 == 4 Paths Through State Machine ==
349 Power state changes are processed in a state machine, and since there are four
350 varieties of power state changes, there are four major paths through the state
353 == 5. No Need To change ==
354 The fourth is nearly trivial. In this path, the parent is changing the domain
355 state, but we are not changing the device state. The change starts when the
356 parent calls powerDomainWillChange. All we do is acknowledge the parent. When
357 the parent calls powerStateDidChange, we acknowledge the parent again, and
360 == 1. OurChange Down == XXX gvdl
361 The first is fairly simple. It starts:
362 * when a power domain child calls requestPowerDomainState and we decide to
363 change power states to accomodate the child,
364 * or if our power-controlling driver calls changePowerStateTo,
365 * or if some other driver which is using our device calls makeUsable,
366 * or if a subclassed object calls changePowerStateToPriv.
367 These are all power changes initiated by us, not forced upon us by the parent.
369 -> We start by notifying interested parties.
370 -> If they all acknowledge via return code, we can go on to state
372 -> Otherwise, we start the ack timer and wait for the stragglers to
373 acknowlege by calling acknowledgePowerChange.
374 -> We move on to state "msSetPowerState" when all the
375 stragglers have acknowledged, or when the ack timer expires on
376 all those which didn't acknowledge.
377 In "msSetPowerState" we call the power-controlling driver to change the
378 power state of the hardware.
379 -> If it returns saying it has done so, we go on to state
380 "msWaitForPowerSettle".
381 -> Otherwise, we have to wait for it, so we set the ack timer and wait.
382 -> When it calls acknowledgeSetPowerState, or when the ack timer
384 In "msWaitForPowerSettle", we look in the power state array to see if
385 there is any settle time required when changing from our current state to the
387 -> If not, we go right away to "msNotifyInterestedDriversDidChange".
388 -> Otherwise, we set the settle timer and wait. When it expires, we move on.
389 In "msNotifyInterestedDriversDidChange" state, we notify all our
390 interested parties via their powerStateDidChange methods that we have finished
391 changing power state.
392 -> If they all acknowledge via return code, we move on to "msFinish".
393 -> Otherwise we set the ack timer and wait. When they have all
394 acknowledged, or when the ack timer has expired for those that didn't,
395 we move on to "msFinish".
396 In "msFinish" we remove the used change note from the head of the queue
397 and start the next one if one exists.
399 == 2. Parent Change Down ==
400 Start at Stage 2 of OurChange Down XXX gvdl
403 Start at Stage 4 of OurChange Down XXX gvdl
405 Note all parent requested changes need to acknowledge the power has changed to the parent when done.
408 //*********************************************************************************
411 // Initialize power management.
412 //*********************************************************************************
414 void IOService::PMinit ( void )
418 if ( !gIOPMInitialized
)
420 gPlatform
= getPlatform();
421 gIOPMWorkLoop
= IOWorkLoop::workLoop();
424 gIOPMRequestQueue
= IOPMRequestQueue::create(
425 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
426 this, &IOService::servicePMRequestQueue
));
428 gIOPMReplyQueue
= IOPMRequestQueue::create(
429 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
430 this, &IOService::servicePMReplyQueue
));
432 gIOPMWorkQueue
= IOPMWorkQueue::create(
434 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
435 &IOService::servicePMRequest
),
436 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
437 &IOService::retirePMRequest
));
439 gIOPMFreeQueue
= IOPMCompletionQueue::create(
440 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
441 this, &IOService::servicePMFreeQueue
));
443 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
446 gIOPMRequestQueue
->release();
447 gIOPMRequestQueue
= 0;
450 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
453 gIOPMReplyQueue
->release();
457 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
460 gIOPMWorkQueue
->release();
464 if (gIOPMWorkLoop
->addEventSource(gIOPMFreeQueue
) !=
467 gIOPMFreeQueue
->release();
471 gIOPMPowerClientDevice
=
472 OSSymbol::withCStringNoCopy( "DevicePowerState" );
474 gIOPMPowerClientDriver
=
475 OSSymbol::withCStringNoCopy( "DriverPowerState" );
477 gIOPMPowerClientChildProxy
=
478 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
480 gIOPMPowerClientChildren
=
481 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
484 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMFreeQueue
)
485 gIOPMInitialized
= true;
487 if (!gIOPMInitialized
)
490 pwrMgt
= new IOServicePM
;
492 setProperty(kPwrMgtKey
, pwrMgt
);
494 queue_init(&pwrMgt
->WorkChain
);
495 queue_init(&pwrMgt
->RequestHead
);
496 queue_init(&pwrMgt
->PMDriverCallQueue
);
499 fPMLock
= IOLockAlloc();
500 fInterestedDrivers
= new IOPMinformeeList
;
501 fInterestedDrivers
->initialize();
502 fDesiredPowerState
= 0;
504 fInitialPowerChange
= true;
505 fInitialSetPowerState
= true;
506 fPreviousRequestPowerFlags
= 0;
507 fDeviceOverrideEnabled
= false;
508 fMachineState
= kIOPM_Finished
;
509 fSavedMachineState
= kIOPM_BadMachineState
;
510 fIdleTimerMinPowerState
= 0;
511 fActivityLock
= IOLockAlloc();
512 fStrictTreeOrder
= false;
513 fActivityTicklePowerState
= -1;
514 fControllingDriver
= NULL
;
516 fNumberOfPowerStates
= 0;
517 fCurrentPowerState
= 0;
518 fParentsCurrentPowerFlags
= 0;
521 fParentsKnowState
= false;
523 fResponseArray
= NULL
;
524 fNotifyClientArray
= NULL
;
525 fCurrentPowerConsumption
= kIOPMUnknown
;
526 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
528 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot()))
530 gIOPMRootNode
= this;
531 fParentsKnowState
= true;
534 fAckTimer
= thread_call_allocate(
535 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
536 fSettleTimer
= thread_call_allocate(
537 &settle_timer_expired
, (thread_call_param_t
)this);
538 fIdleTimer
= thread_call_allocate(
539 &idle_timer_expired
, (thread_call_param_t
)this);
540 fDriverCallEntry
= thread_call_allocate(
541 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
542 assert(fDriverCallEntry
);
544 // Check for powerChangeDone override.
545 if (OSMemberFunctionCast(void (*)(void),
546 getResourceService(), &IOService::powerChangeDone
) !=
547 OSMemberFunctionCast(void (*)(void),
548 this, &IOService::powerChangeDone
))
550 fPCDFunctionOverride
= true;
554 IOPMprot
* prot
= new IOPMprot
;
558 prot
->ourName
= fName
;
559 prot
->thePlatform
= gPlatform
;
564 pm_vars
= (void *) (uintptr_t) true;
571 //*********************************************************************************
574 // Free the data created by PMinit. Only called from IOService::free().
575 //*********************************************************************************
577 void IOService::PMfree ( void )
584 assert(fMachineState
== kIOPM_Finished
);
585 assert(fInsertInterestSet
== NULL
);
586 assert(fRemoveInterestSet
== NULL
);
587 assert(fNotifyChildArray
== NULL
);
588 assert(queue_empty(&pwrMgt
->RequestHead
));
589 assert(queue_empty(&fPMDriverCallQueue
));
591 if ( fSettleTimer
) {
592 thread_call_cancel(fSettleTimer
);
593 thread_call_free(fSettleTimer
);
597 thread_call_cancel(fAckTimer
);
598 thread_call_free(fAckTimer
);
602 thread_call_cancel(fIdleTimer
);
603 thread_call_free(fIdleTimer
);
606 if ( fDriverCallEntry
) {
607 thread_call_free(fDriverCallEntry
);
608 fDriverCallEntry
= NULL
;
614 if ( fActivityLock
) {
615 IOLockFree(fActivityLock
);
616 fActivityLock
= NULL
;
618 if ( fInterestedDrivers
) {
619 fInterestedDrivers
->release();
620 fInterestedDrivers
= NULL
;
622 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
623 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
624 fDriverCallParamPtr
= 0;
625 fDriverCallParamSlots
= 0;
627 if ( fResponseArray
) {
628 fResponseArray
->release();
629 fResponseArray
= NULL
;
631 if ( fNotifyClientArray
) {
632 fNotifyClientArray
->release();
633 fNotifyClientArray
= NULL
;
635 if (fPowerStates
&& fNumberOfPowerStates
) {
636 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
637 fNumberOfPowerStates
= 0;
641 fPowerClients
->release();
658 //*********************************************************************************
659 // [public] joinPMtree
661 // A policy-maker calls its nub here when initializing, to be attached into
662 // the power management hierarchy. The default function is to call the
663 // platform expert, which knows how to do it. This method is overridden
664 // by a nub subclass which may either know how to do it, or may need to
665 // take other action.
667 // This may be the only "power management" method used in a nub,
668 // meaning it may not be initialized for power management.
669 //*********************************************************************************
671 void IOService::joinPMtree ( IOService
* driver
)
673 IOPlatformExpert
* platform
;
675 platform
= getPlatform();
676 assert(platform
!= 0);
677 platform
->PMRegisterDevice(this, driver
);
681 //*********************************************************************************
682 // [deprecated] youAreRoot
684 // Power Managment is informing us that we are the root power domain.
685 //*********************************************************************************
687 IOReturn
IOService::youAreRoot ( void )
691 #endif /* !__LP64__ */
693 //*********************************************************************************
696 // Immediately stop driver callouts. Schedule an async stop request to detach
698 //*********************************************************************************
700 void IOService::PMstop ( void )
702 IOPMRequest
* request
;
709 if (fLockedFlags
.PMStop
)
711 PM_LOG2("%s: PMstop() already stopped\n", fName
);
716 // Inhibit future driver calls.
717 fLockedFlags
.PMStop
= true;
719 // Wait for all prior driver calls to finish.
720 waitForPMDriverCall();
724 // The rest of the work is performed async.
725 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
728 PM_LOG2("%s: %p PMstop\n", getName(), this);
729 submitPMRequest( request
);
733 //*********************************************************************************
734 // [private] handlePMstop
736 // Disconnect the node from all parents and children in the power plane.
737 //*********************************************************************************
739 void IOService::handlePMstop ( IOPMRequest
* request
)
743 IOPowerConnection
* connection
;
744 IOService
* theChild
;
745 IOService
* theParent
;
748 PM_LOG2("%s: %p %s start\n", getName(), this, __FUNCTION__
);
750 // remove the property
751 removeProperty(kPwrMgtKey
);
754 iter
= getParentIterator(gIOPowerPlane
);
757 while ( (next
= iter
->getNextObject()) )
759 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
761 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
764 theParent
->removePowerChild(connection
);
765 theParent
->release();
772 // detach IOConnections
773 detachAbove( gIOPowerPlane
);
775 // no more power state changes
776 fParentsKnowState
= false;
779 iter
= getChildIterator(gIOPowerPlane
);
782 while ( (next
= iter
->getNextObject()) )
784 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
786 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
789 // detach nub from child
790 connection
->detachFromChild(theChild
, gIOPowerPlane
);
793 // detach us from nub
794 detachFromChild(connection
, gIOPowerPlane
);
800 // Remove all interested drivers from the list, including the power
801 // controlling driver.
803 // Usually, the controlling driver and the policy-maker functionality
804 // are implemented by the same object, and without the deregistration,
805 // the object will be holding an extra retain on itself, and cannot
808 if ( fInterestedDrivers
)
810 IOPMinformeeList
* list
= fInterestedDrivers
;
814 while ((item
= list
->firstInList()))
816 list
->removeFromList(item
->whatObject
);
821 // Tell idleTimerExpired() to ignore idle timer.
822 fIdleTimerPeriod
= 0;
823 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
826 PM_LOG2("%s: %p %s done\n", getName(), this, __FUNCTION__
);
829 //*********************************************************************************
830 // [public] addPowerChild
832 // Power Management is informing us who our children are.
833 //*********************************************************************************
835 IOReturn
IOService::addPowerChild ( IOService
* child
)
837 IOPowerConnection
* connection
= 0;
838 IOPMRequest
* requests
[3] = {0, 0, 0};
843 return kIOReturnBadArgument
;
845 if (!initialized
|| !child
->initialized
)
846 return IOPMNotYetInitialized
;
848 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
851 // Is this child already one of our children?
853 iter
= child
->getParentIterator( gIOPowerPlane
);
856 IORegistryEntry
* entry
;
859 while ((next
= iter
->getNextObject()))
861 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
862 isChild(entry
, gIOPowerPlane
))
872 PM_LOG("%s: %s (%p) is already a child\n",
873 getName(), child
->getName(), child
);
877 // Add the child to the power plane immediately, but the
878 // joining connection is marked as not ready.
879 // We want the child to appear in the power plane before
880 // returning to the caller, but don't want the caller to
881 // block on the PM work loop.
883 connection
= new IOPowerConnection
;
887 // Create a chain of PM requests to perform the bottom-half
888 // work from the PM work loop.
890 requests
[0] = acquirePMRequest(
892 /* type */ kIOPMRequestTypeAddPowerChild1
);
894 requests
[1] = acquirePMRequest(
896 /* type */ kIOPMRequestTypeAddPowerChild2
);
898 requests
[2] = acquirePMRequest(
900 /* type */ kIOPMRequestTypeAddPowerChild3
);
902 if (!requests
[0] || !requests
[1] || !requests
[2])
905 requests
[0]->attachNextRequest( requests
[1] );
906 requests
[1]->attachNextRequest( requests
[2] );
909 connection
->start(this);
910 connection
->setAwaitingAck(false);
911 connection
->setReadyFlag(false);
913 attachToChild( connection
, gIOPowerPlane
);
914 connection
->attachToChild( child
, gIOPowerPlane
);
916 // connection needs to be released
917 requests
[0]->fArg0
= connection
;
918 requests
[1]->fArg0
= connection
;
919 requests
[2]->fArg0
= connection
;
921 submitPMRequest( requests
, 3 );
922 return kIOReturnSuccess
;
926 if (connection
) connection
->release();
927 if (requests
[0]) releasePMRequest(requests
[0]);
928 if (requests
[1]) releasePMRequest(requests
[1]);
929 if (requests
[2]) releasePMRequest(requests
[2]);
931 // Silent failure, to prevent platform drivers from adding the child
932 // to the root domain.
934 return kIOReturnSuccess
;
937 //*********************************************************************************
938 // [private] addPowerChild1
940 // Step 1/3 of adding a power child. Called on the power parent.
941 //*********************************************************************************
943 void IOService::addPowerChild1 ( IOPMRequest
* request
)
945 unsigned long tempDesire
= 0;
947 // Make us temporary usable before adding the child.
950 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
952 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
954 tempDesire
= fNumberOfPowerStates
- 1;
957 if (tempDesire
&& (IS_PM_ROOT
|| (fMaxPowerState
>= tempDesire
)))
959 adjustPowerState(tempDesire
);
963 //*********************************************************************************
964 // [private] addPowerChild2
966 // Step 2/3 of adding a power child. Called on the joining child.
967 // Execution blocked behind addPowerChild1.
968 //*********************************************************************************
970 void IOService::addPowerChild2 ( IOPMRequest
* request
)
972 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
974 IOPMPowerFlags powerFlags
;
976 unsigned long powerState
;
977 unsigned long tempDesire
;
980 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
982 if (!parent
|| !inPlane(gIOPowerPlane
))
984 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
988 // Parent will be waiting for us to complete this stage.
989 // It is safe to directly access parent's vars.
991 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
992 powerState
= parent
->fCurrentPowerState
;
995 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
999 // Set our power parent.
1001 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
1003 setParentInfo( powerFlags
, connection
, knowsState
);
1005 connection
->setReadyFlag(true);
1007 if ( fControllingDriver
&& fParentsKnowState
)
1009 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1010 // initially change into the state we are already in
1011 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1012 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
1013 adjustPowerState(tempDesire
);
1016 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
1019 //*********************************************************************************
1020 // [private] addPowerChild3
1022 // Step 3/3 of adding a power child. Called on the parent.
1023 // Execution blocked behind addPowerChild2.
1024 //*********************************************************************************
1026 void IOService::addPowerChild3 ( IOPMRequest
* request
)
1028 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
1030 IOPMrootDomain
* rootDomain
= getPMRootDomain();
1032 PM_ASSERT_IN_GATE();
1033 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
1035 if (child
&& inPlane(gIOPowerPlane
))
1037 if (child
->getProperty("IOPMStrictTreeOrder"))
1039 PM_LOG1("%s: strict PM order enforced\n", getName());
1040 fStrictTreeOrder
= true;
1044 rootDomain
->joinAggressiveness( child
);
1048 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1051 connection
->release();
1055 //*********************************************************************************
1056 // [deprecated] setPowerParent
1058 // Power Management is informing us who our parent is.
1059 // If we have a controlling driver, find out, given our newly-informed
1060 // power domain state, what state it would be in, and then tell it
1061 // to assume that state.
1062 //*********************************************************************************
1064 IOReturn
IOService::setPowerParent (
1065 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
1067 return kIOReturnUnsupported
;
1069 #endif /* !__LP64__ */
1071 //*********************************************************************************
1072 // [public] removePowerChild
1074 // Called on a parent whose child is being removed by PMstop().
1075 //*********************************************************************************
1077 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
1079 IORegistryEntry
* theChild
;
1081 PM_ASSERT_IN_GATE();
1082 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1086 // detach nub from child
1087 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1090 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1091 theChild
->release();
1093 // detach from the nub
1094 detachFromChild(theNub
, gIOPowerPlane
);
1096 // Are we awaiting an ack from this child?
1097 if ( theNub
->getAwaitingAck() )
1099 // yes, pretend we got one
1100 theNub
->setAwaitingAck(false);
1101 if (fHeadNotePendingAcks
!= 0 )
1103 // that's one fewer ack to worry about
1104 fHeadNotePendingAcks
--;
1106 // is that the last?
1107 if ( fHeadNotePendingAcks
== 0 )
1111 // Request unblocked, work queue
1112 // should re-scan all busy requests.
1113 gIOPMWorkQueue
->incrementProducerCount();
1120 // A child has gone away, re-scan children desires and clamp bits.
1121 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1123 if (!fAdjustPowerScheduled
)
1125 IOPMRequest
* request
;
1126 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1129 submitPMRequest( request
);
1130 fAdjustPowerScheduled
= true;
1137 //*********************************************************************************
1138 // [public] registerPowerDriver
1140 // A driver has called us volunteering to control power to our device.
1141 //*********************************************************************************
1143 IOReturn
IOService::registerPowerDriver (
1144 IOService
* powerDriver
,
1145 IOPMPowerState
* powerStates
,
1146 unsigned long numberOfStates
)
1148 IOPMRequest
* request
;
1149 IOPMPSEntry
* powerStatesCopy
= 0;
1152 return IOPMNotYetInitialized
;
1154 // Validate arguments.
1155 if (!powerStates
|| (numberOfStates
< 2))
1157 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1158 return kIOReturnBadArgument
;
1161 if (!powerDriver
|| !powerDriver
->initialized
)
1163 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1164 return kIOReturnBadArgument
;
1167 if (powerStates
[0].version
!= kIOPMPowerStateVersion1
)
1169 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1170 return kIOReturnBadArgument
;
1174 // Make a copy of the supplied power state array.
1175 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1176 if (!powerStatesCopy
)
1179 for (uint32_t i
= 0; i
< numberOfStates
; i
++)
1181 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1182 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1183 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1184 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1185 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1186 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1189 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1193 powerDriver
->retain();
1194 request
->fArg0
= (void *) powerDriver
;
1195 request
->fArg1
= (void *) powerStatesCopy
;
1196 request
->fArg2
= (void *) numberOfStates
;
1198 submitPMRequest( request
);
1199 return kIOReturnSuccess
;
1203 if (powerStatesCopy
)
1204 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1205 return kIOReturnNoMemory
;
1208 //*********************************************************************************
1209 // [private] handleRegisterPowerDriver
1210 //*********************************************************************************
1212 void IOService::handleRegisterPowerDriver ( IOPMRequest
* request
)
1214 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1215 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1216 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1221 PM_ASSERT_IN_GATE();
1222 assert(powerStates
);
1223 assert(powerDriver
);
1224 assert(numberOfStates
> 1);
1226 if ( !fNumberOfPowerStates
)
1228 OUR_PMLog(kPMLogControllingDriver
,
1229 (unsigned long) numberOfStates
,
1230 (unsigned long) kIOPMPowerStateVersion1
);
1232 fPowerStates
= powerStates
;
1233 fNumberOfPowerStates
= numberOfStates
;
1234 fControllingDriver
= powerDriver
;
1235 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1237 // make a mask of all the character bits we know about
1238 fOutputPowerCharacterFlags
= 0;
1239 for ( i
= 0; i
< numberOfStates
; i
++ ) {
1240 fOutputPowerCharacterFlags
|= fPowerStates
[i
].outputPowerFlags
;
1243 // Register powerDriver as interested, unless already done.
1244 // We don't want to register the default implementation since
1245 // it does nothing. One ramification of not always registering
1246 // is the one fewer retain count held.
1248 root
= getPlatform()->getProvider();
1251 ((OSMemberFunctionCast(void (*)(void),
1252 root
, &IOService::powerStateDidChangeTo
)) !=
1253 ((OSMemberFunctionCast(void (*)(void),
1254 this, &IOService::powerStateDidChangeTo
)))) ||
1255 ((OSMemberFunctionCast(void (*)(void),
1256 root
, &IOService::powerStateWillChangeTo
)) !=
1257 ((OSMemberFunctionCast(void (*)(void),
1258 this, &IOService::powerStateWillChangeTo
)))))
1260 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
)
1263 fInterestedDrivers
->appendNewInformee(powerDriver
);
1268 // Examine all existing power clients and perform limit check.
1272 iter
= OSCollectionIterator::withCollection(fPowerClients
);
1275 const OSSymbol
* client
;
1276 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
1278 uint32_t powerState
= getPowerStateForClient(client
);
1279 if (powerState
>= numberOfStates
)
1281 updatePowerClient(client
, numberOfStates
- 1);
1288 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1290 unsigned long tempDesire
;
1291 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1292 // initially change into the state we are already in
1293 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1294 adjustPowerState(tempDesire
);
1299 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1300 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1303 powerDriver
->release();
1306 //*********************************************************************************
1307 // [public] registerInterestedDriver
1309 // Add the caller to our list of interested drivers and return our current
1310 // power state. If we don't have a power-controlling driver yet, we will
1311 // call this interested driver again later when we do get a driver and find
1312 // out what the current power state of the device is.
1313 //*********************************************************************************
1315 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* driver
)
1317 IOPMRequest
* request
;
1320 if (!driver
|| !initialized
|| !fInterestedDrivers
)
1324 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1325 if (fInsertInterestSet
== NULL
)
1326 fInsertInterestSet
= OSSet::withCapacity(4);
1327 if (fInsertInterestSet
)
1329 fInsertInterestSet
->setObject(driver
);
1330 if (fRemoveInterestSet
)
1331 fRemoveInterestSet
->removeObject(driver
);
1337 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1339 submitPMRequest( request
);
1342 // This return value cannot be trusted, but return a value
1343 // for those clients that care.
1345 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1346 return kIOPMDeviceUsable
;
1349 //*********************************************************************************
1350 // [public] deRegisterInterestedDriver
1351 //*********************************************************************************
1353 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* driver
)
1355 IOPMinformeeList
* list
;
1356 IOPMinformee
* item
;
1357 IOPMRequest
* request
;
1361 return kIOReturnBadArgument
;
1362 if (!initialized
|| !fInterestedDrivers
)
1363 return IOPMNotPowerManaged
;
1366 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1367 if (fRemoveInterestSet
== NULL
)
1368 fRemoveInterestSet
= OSSet::withCapacity(4);
1369 if (fRemoveInterestSet
)
1371 fRemoveInterestSet
->setObject(driver
);
1372 if (fInsertInterestSet
)
1373 fInsertInterestSet
->removeObject(driver
);
1375 list
= fInterestedDrivers
;
1376 item
= list
->findItem(driver
);
1377 if (item
&& item
->active
)
1379 item
->active
= false;
1380 waitForPMDriverCall( driver
);
1387 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1389 submitPMRequest( request
);
1395 //*********************************************************************************
1396 // [private] handleInterestChanged
1398 // Handle interest added or removed.
1399 //*********************************************************************************
1401 void IOService::handleInterestChanged( IOPMRequest
* request
)
1404 IOPMinformee
* informee
;
1405 IOPMinformeeList
* list
= fInterestedDrivers
;
1409 if (fInsertInterestSet
)
1411 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject()))
1413 if (list
->findItem(driver
) == NULL
)
1415 informee
= list
->appendNewInformee(driver
);
1417 fInsertInterestSet
->removeObject(driver
);
1419 fInsertInterestSet
->release();
1420 fInsertInterestSet
= 0;
1423 if (fRemoveInterestSet
)
1425 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject()))
1427 informee
= list
->findItem(driver
);
1430 // Clean-up async interest acknowledgement
1431 if (fHeadNotePendingAcks
&& informee
->timer
)
1433 informee
->timer
= 0;
1434 fHeadNotePendingAcks
--;
1436 list
->removeFromList(driver
);
1438 fRemoveInterestSet
->removeObject(driver
);
1440 fRemoveInterestSet
->release();
1441 fRemoveInterestSet
= 0;
1447 //*********************************************************************************
1448 // [public] acknowledgePowerChange
1450 // After we notified one of the interested drivers or a power-domain child
1451 // of an impending change in power, it has called to say it is now
1452 // prepared for the change. If this object is the last to
1453 // acknowledge this change, we take whatever action we have been waiting
1455 // That may include acknowledging to our parent. In this case, we do it
1456 // last of all to insure that this doesn't cause the parent to call us some-
1457 // where else and alter data we are relying on here (like the very existance
1458 // of a "current change note".)
1459 //*********************************************************************************
1461 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
1463 IOPMRequest
* request
;
1466 return IOPMNotYetInitialized
;
1468 return kIOReturnBadArgument
;
1470 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1472 return kIOReturnNoMemory
;
1474 whichObject
->retain();
1475 request
->fArg0
= whichObject
;
1477 submitPMRequest( request
);
1481 //*********************************************************************************
1482 // [private] handleAcknowledgePowerChange
1483 //*********************************************************************************
1485 bool IOService::handleAcknowledgePowerChange ( IOPMRequest
* request
)
1487 IOPMinformee
* informee
;
1488 unsigned long childPower
= kIOPMUnknown
;
1489 IOService
* theChild
;
1490 IOService
* whichObject
;
1491 bool all_acked
= false;
1493 PM_ASSERT_IN_GATE();
1494 whichObject
= (IOService
*) request
->fArg0
;
1495 assert(whichObject
);
1497 // one of our interested drivers?
1498 informee
= fInterestedDrivers
->findItem( whichObject
);
1499 if ( informee
== NULL
)
1501 if ( !isChild(whichObject
, gIOPowerPlane
) )
1503 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1506 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1509 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1512 if ( fHeadNotePendingAcks
!= 0 )
1514 assert(fPowerStates
!= NULL
);
1516 // yes, make sure we're expecting acks
1517 if ( informee
!= NULL
)
1519 // it's an interested driver
1520 // make sure we're expecting this ack
1521 if ( informee
->timer
!= 0 )
1523 #if LOG_SETPOWER_TIMES
1524 if (informee
->timer
> 0)
1526 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1527 if (nsec
> LOG_SETPOWER_TIMES
)
1528 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) async took %d ms\n",
1529 informee
->whatObject
->getName(),
1530 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
1531 informee
->whatObject
,
1532 fName
, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_US(nsec
));
1534 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
1535 ? kIOPMEventTypePSWillChangeTo
1536 : kIOPMEventTypePSDidChangeTo
;
1538 PMEventDetails
*details
= PMEventDetails::eventDetails(
1542 informee
->whatObject
->getName(),
1546 getPMRootDomain()->recordAndReleasePMEventGated( details
);
1550 informee
->timer
= 0;
1551 // that's one fewer to worry about
1552 fHeadNotePendingAcks
--;
1554 // this driver has already acked
1555 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1559 // make sure we're expecting this ack
1560 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1562 // that's one fewer to worry about
1563 fHeadNotePendingAcks
--;
1564 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1565 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1568 childPower
= theChild
->currentPowerConsumption();
1569 theChild
->release();
1571 if ( childPower
== kIOPMUnknown
)
1573 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1575 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
1577 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1583 if ( fHeadNotePendingAcks
== 0 ) {
1584 // yes, stop the timer
1586 // and now we can continue
1590 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1595 whichObject
->release();
1600 //*********************************************************************************
1601 // [public] acknowledgeSetPowerState
1603 // After we instructed our controlling driver to change power states,
1604 // it has called to say it has finished doing so.
1605 // We continue to process the power state change.
1606 //*********************************************************************************
1608 IOReturn
IOService::acknowledgeSetPowerState ( void )
1610 IOPMRequest
* request
;
1613 return IOPMNotYetInitialized
;
1615 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1617 return kIOReturnNoMemory
;
1619 submitPMRequest( request
);
1620 return kIOReturnSuccess
;
1623 //*********************************************************************************
1624 // [private] adjustPowerState
1625 //*********************************************************************************
1627 void IOService::adjustPowerState ( uint32_t clamp
)
1629 PM_ASSERT_IN_GATE();
1630 computeDesiredState(clamp
);
1631 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
))
1633 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1635 // Indicate that children desires were ignored, and do not ask
1636 // apps for permission to drop power. This is used by root domain
1637 // for demand sleep.
1639 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
1640 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1643 /* flags */ changeFlags
,
1644 /* power state */ fDesiredPowerState
,
1645 /* domain flags */ 0,
1647 /* parent flags */ 0);
1651 //*********************************************************************************
1652 // [public] synchronizePowerTree
1653 //*********************************************************************************
1655 IOReturn
IOService::synchronizePowerTree (
1656 IOOptionBits options
,
1657 IOService
* notifyRoot
)
1659 IOPMRequest
* request_c
= 0;
1660 IOPMRequest
* request_s
;
1662 if (this != getPMRootDomain())
1663 return kIOReturnBadArgument
;
1665 return kIOPMNotYetInitialized
;
1671 // Cancels don't need to be synchronized.
1672 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1673 if (nr
) submitPMRequest(nr
);
1674 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1675 if (nr
) submitPMRequest(nr
);
1678 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1680 goto error_no_memory
;
1682 if (options
& kIOPMSyncCancelPowerDown
)
1683 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1686 request_c
->attachNextRequest( request_s
);
1687 submitPMRequest(request_c
);
1690 request_s
->fArg0
= (void *)(uintptr_t) options
;
1691 submitPMRequest(request_s
);
1693 return kIOReturnSuccess
;
1696 if (request_c
) releasePMRequest(request_c
);
1697 if (request_s
) releasePMRequest(request_s
);
1698 return kIOReturnNoMemory
;
1701 //*********************************************************************************
1702 // [private] handleSynchronizePowerTree
1703 //*********************************************************************************
1705 void IOService::handleSynchronizePowerTree ( IOPMRequest
* request
)
1707 PM_ASSERT_IN_GATE();
1708 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1709 (fCurrentPowerState
== fNumberOfPowerStates
- 1))
1711 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1714 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1715 (options
& kIOPMSyncNoChildNotify
),
1716 /* power state */ fCurrentPowerState
,
1717 /* domain flags */ 0,
1719 /* parent flags */ 0);
1724 //*********************************************************************************
1725 // [deprecated] powerDomainWillChangeTo
1727 // Called by the power-hierarchy parent notifying of a new power state
1728 // in the power domain.
1729 // We enqueue a parent power-change to our queue of power changes.
1730 // This may or may not cause us to change power, depending on what
1731 // kind of change is occuring in the domain.
1732 //*********************************************************************************
1734 IOReturn
IOService::powerDomainWillChangeTo (
1735 IOPMPowerFlags newPowerFlags
,
1736 IOPowerConnection
* whichParent
)
1739 return kIOReturnUnsupported
;
1741 #endif /* !__LP64__ */
1743 //*********************************************************************************
1744 // [private] handlePowerDomainWillChangeTo
1745 //*********************************************************************************
1747 void IOService::handlePowerDomainWillChangeTo ( IOPMRequest
* request
)
1749 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1750 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1751 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1752 IOPMPowerChangeFlags myChangeFlags
;
1755 IOPowerConnection
* connection
;
1756 IOPMPowerStateIndex newPowerState
;
1757 IOPMPowerFlags combinedPowerFlags
;
1758 bool savedParentsKnowState
;
1759 IOReturn result
= IOPMAckImplied
;
1761 PM_ASSERT_IN_GATE();
1762 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1764 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1766 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1770 savedParentsKnowState
= fParentsKnowState
;
1772 // Combine parents' output power flags.
1774 combinedPowerFlags
= 0;
1776 iter
= getParentIterator(gIOPowerPlane
);
1779 while ( (next
= iter
->getNextObject()) )
1781 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1783 if ( connection
== whichParent
)
1784 combinedPowerFlags
|= parentPowerFlags
;
1786 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1792 // If our initial change has yet to occur, then defer the power change
1793 // until after the power domain has completed its power transition.
1795 if ( fControllingDriver
&& !fInitialPowerChange
)
1797 newPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1798 combinedPowerFlags
);
1800 // Absorb parent's kIOPMSynchronize flag.
1801 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1802 (parentChangeFlags
& kIOPMSynchronize
);
1804 result
= startPowerChange(
1805 /* flags */ myChangeFlags
,
1806 /* power state */ newPowerState
,
1807 /* domain flags */ combinedPowerFlags
,
1808 /* connection */ whichParent
,
1809 /* parent flags */ parentPowerFlags
);
1812 // If parent is dropping power, immediately update the parent's
1813 // capability flags. Any future merging of parent(s) combined
1814 // power flags should account for this power drop.
1816 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1818 setParentInfo(parentPowerFlags
, whichParent
, true);
1821 // Parent is expecting an ACK from us. If we did not embark on a state
1822 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1823 // still required to issue an ACK to our parent.
1825 if (IOPMAckImplied
== result
)
1828 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1832 parent
->acknowledgePowerChange( whichParent
);
1838 // Drop the retain from notifyChild().
1839 if (whichParent
) whichParent
->release();
1843 //*********************************************************************************
1844 // [deprecated] powerDomainDidChangeTo
1846 // Called by the power-hierarchy parent after the power state of the power domain
1847 // has settled at a new level.
1848 // We enqueue a parent power-change to our queue of power changes.
1849 // This may or may not cause us to change power, depending on what
1850 // kind of change is occuring in the domain.
1851 //*********************************************************************************
1853 IOReturn
IOService::powerDomainDidChangeTo (
1854 IOPMPowerFlags newPowerFlags
,
1855 IOPowerConnection
* whichParent
)
1858 return kIOReturnUnsupported
;
1860 #endif /* !__LP64__ */
1862 //*********************************************************************************
1863 // [private] handlePowerDomainDidChangeTo
1864 //*********************************************************************************
1866 void IOService::handlePowerDomainDidChangeTo ( IOPMRequest
* request
)
1868 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1869 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1870 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1871 IOPMPowerChangeFlags myChangeFlags
;
1872 IOPMPowerStateIndex newPowerState
;
1873 IOPMPowerStateIndex initialDesire
;
1874 bool savedParentsKnowState
;
1875 IOReturn result
= IOPMAckImplied
;
1877 PM_ASSERT_IN_GATE();
1878 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1880 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1882 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1886 savedParentsKnowState
= fParentsKnowState
;
1888 setParentInfo(parentPowerFlags
, whichParent
, true);
1890 if ( fControllingDriver
)
1892 newPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1893 fParentsCurrentPowerFlags
);
1895 if (fInitialPowerChange
)
1897 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1898 fParentsCurrentPowerFlags
);
1899 computeDesiredState(initialDesire
);
1902 // Absorb parent's kIOPMSynchronize flag.
1903 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1904 (parentChangeFlags
& kIOPMSynchronize
);
1906 result
= startPowerChange(
1907 /* flags */ myChangeFlags
,
1908 /* power state */ newPowerState
,
1909 /* domain flags */ fParentsCurrentPowerFlags
,
1910 /* connection */ whichParent
,
1911 /* parent flags */ 0);
1914 // Parent is expecting an ACK from us. If we did not embark on a state
1915 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1916 // still required to issue an ACK to our parent.
1918 if (IOPMAckImplied
== result
)
1921 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1925 parent
->acknowledgePowerChange( whichParent
);
1930 // If the parent registers its power driver late, then this is the
1931 // first opportunity to tell our parent about our desire.
1933 if (!savedParentsKnowState
&& fParentsKnowState
)
1935 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState = true\n",
1937 requestDomainPower( fDesiredPowerState
);
1941 // Drop the retain from notifyChild().
1942 if (whichParent
) whichParent
->release();
1945 //*********************************************************************************
1946 // [private] setParentInfo
1948 // Set our connection data for one specific parent, and then combine all the parent
1950 //*********************************************************************************
1952 void IOService::setParentInfo (
1953 IOPMPowerFlags newPowerFlags
,
1954 IOPowerConnection
* whichParent
,
1959 IOPowerConnection
* conn
;
1961 PM_ASSERT_IN_GATE();
1963 // set our connection data
1964 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
1965 whichParent
->setParentKnowsState(knowsState
);
1967 // recompute our parent info
1968 fParentsCurrentPowerFlags
= 0;
1969 fParentsKnowState
= true;
1971 iter
= getParentIterator(gIOPowerPlane
);
1974 while ( (next
= iter
->getNextObject()) )
1976 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
1978 fParentsKnowState
&= conn
->parentKnowsState();
1979 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
1986 //*********************************************************************************
1987 // [private] rebuildChildClampBits
1989 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1990 // indicate that one of our children (or grandchildren or great-grandchildren ...)
1991 // doesn't support idle or system sleep in its current state. Since we don't track
1992 // the origin of each bit, every time any child changes state we have to clear
1993 // these bits and rebuild them.
1994 //*********************************************************************************
1996 void IOService::rebuildChildClampBits ( void )
2001 IOPowerConnection
* connection
;
2002 unsigned long powerState
;
2004 // A child's desires has changed. We need to rebuild the child-clamp bits in
2005 // our power state array. Start by clearing the bits in each power state.
2007 for ( i
= 0; i
< fNumberOfPowerStates
; i
++ )
2009 fPowerStates
[i
].capabilityFlags
&= ~(kIOPMChildClamp
| kIOPMChildClamp2
);
2012 if (!inPlane(gIOPowerPlane
))
2015 // Loop through the children. When we encounter the calling child, save the
2016 // computed state as this child's desire. And set the ChildClamp bits in any
2017 // of our states that some child has clamp on.
2019 iter
= getChildIterator(gIOPowerPlane
);
2022 while ( (next
= iter
->getNextObject()) )
2024 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
2026 if (connection
->getReadyFlag() == false)
2028 PM_LOG3("[%s] %s: connection not ready\n",
2029 getName(), __FUNCTION__
);
2033 powerState
= connection
->getDesiredDomainState();
2034 if (powerState
< fNumberOfPowerStates
)
2036 if ( connection
->getPreventIdleSleepFlag() )
2037 fPowerStates
[powerState
].capabilityFlags
|= kIOPMChildClamp
;
2038 if ( connection
->getPreventSystemSleepFlag() )
2039 fPowerStates
[powerState
].capabilityFlags
|= kIOPMChildClamp2
;
2047 //*********************************************************************************
2048 // [public] requestPowerDomainState
2050 // Called on a power parent when a child's power requirement changes.
2051 //*********************************************************************************
2053 IOReturn
IOService::requestPowerDomainState(
2054 IOPMPowerFlags childRequestPowerFlags
,
2055 IOPowerConnection
* childConnection
,
2056 unsigned long specification
)
2058 IOPMPowerStateIndex ps
;
2059 IOPMPowerFlags outputPowerFlags
;
2061 IOPMRequest
* subRequest
;
2062 bool preventIdle
, preventSleep
;
2063 bool adjustPower
= false;
2066 return IOPMNotYetInitialized
;
2068 if (gIOPMWorkLoop
->onThread() == false)
2070 PM_LOG("%s::requestPowerDomainState\n", getName());
2071 return kIOReturnSuccess
;
2074 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2076 if (!isChild(childConnection
, gIOPowerPlane
))
2077 return kIOReturnNotAttached
;
2079 if (!fControllingDriver
|| !fNumberOfPowerStates
)
2080 return kIOReturnNotReady
;
2082 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2085 preventIdle
= ((childRequestPowerFlags
& kIOPMPreventIdleSleep
) != 0);
2086 preventSleep
= ((childRequestPowerFlags
& kIOPMPreventSystemSleep
) != 0);
2087 childRequestPowerFlags
&= ~(kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2089 // Merge in the power flags contributed by this power parent
2090 // at its current or impending power state.
2092 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2093 if (fMachineState
!= kIOPM_Finished
)
2095 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
)
2097 // Use the lower power state when dropping power.
2098 // Must be careful since a power drop can be canceled
2099 // from the following states:
2100 // - kIOPM_OurChangeTellClientsPowerDown
2101 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2103 // The child must not wait for this parent to raise power
2104 // if the power drop was cancelled. The solution is to cancel
2105 // the power drop if possible, then schedule an adjustment to
2106 // re-evaluate the parent's power state.
2108 // Root domain is excluded to avoid idle sleep issues. And permit
2109 // root domain children to pop up when system is going to sleep.
2111 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2112 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
2114 fDoNotPowerDown
= true; // cancel power drop
2115 adjustPower
= true; // schedule an adjustment
2116 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2117 getName(), fMachineState
, child
->getName());
2121 // Beyond cancellation point, report the impending state.
2123 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2126 else if (IS_POWER_RISE
)
2128 // When raising power, must report the output power flags from
2129 // child's perspective. A child power request may arrive while
2130 // parent is transitioning upwards. If a request arrives after
2131 // setParentInfo() has already recorded the output power flags
2132 // for the next power state, then using the power supplied by
2133 // fCurrentPowerState is incorrect, and might cause the child
2134 // to wait when it should not.
2136 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2139 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2141 // Map child's requested power flags to one of our power state.
2143 for (ps
= 0; ps
< fNumberOfPowerStates
; ps
++)
2145 if ((fPowerStates
[ps
].outputPowerFlags
& childRequestPowerFlags
) ==
2146 (fOutputPowerCharacterFlags
& childRequestPowerFlags
))
2149 if (ps
>= fNumberOfPowerStates
)
2151 ps
= 0; // should never happen
2154 // Conditions that warrants a power adjustment on this parent.
2155 // Adjust power will also propagate any changes to the child's
2156 // prevent idle/sleep flags towards the root domain.
2158 if (!childConnection
->childHasRequestedPower() ||
2159 (ps
!= childConnection
->getDesiredDomainState()) ||
2160 (childConnection
->getPreventIdleSleepFlag() != preventIdle
) ||
2161 (childConnection
->getPreventSystemSleepFlag() != preventSleep
))
2164 #if ENABLE_DEBUG_LOGS
2167 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2168 getName(), child
->getName(),
2169 !childConnection
->childHasRequestedPower(),
2170 (uint32_t) childConnection
->getDesiredDomainState(),
2175 // Record the child's desires on the connection.
2176 #if SUPPORT_IDLE_CANCEL
2177 bool attemptCancel
= (preventIdle
&& !childConnection
->getPreventIdleSleepFlag());
2179 childConnection
->setChildHasRequestedPower();
2180 childConnection
->setDesiredDomainState( ps
);
2181 childConnection
->setPreventIdleSleepFlag( preventIdle
);
2182 childConnection
->setPreventSystemSleepFlag( preventSleep
);
2184 // Schedule a request to re-evaluate all children desires and
2185 // adjust power state. Submit a request if one wasn't pending,
2186 // or if the current request is part of a call tree.
2188 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2189 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest()))
2191 subRequest
= acquirePMRequest(
2192 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2195 submitPMRequest( subRequest
);
2196 fAdjustPowerScheduled
= true;
2200 #if SUPPORT_IDLE_CANCEL
2203 subRequest
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
2206 submitPMRequest( subRequest
);
2211 return kIOReturnSuccess
;
2214 //*********************************************************************************
2215 // [public] temporaryPowerClampOn
2217 // A power domain wants to clamp its power on till it has children which
2218 // will thendetermine the power domain state.
2220 // We enter the highest state until addPowerChild is called.
2221 //*********************************************************************************
2223 IOReturn
IOService::temporaryPowerClampOn ( void )
2225 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2228 //*********************************************************************************
2229 // [public] makeUsable
2231 // Some client of our device is asking that we become usable. Although
2232 // this has not come from a subclassed device object, treat it exactly
2233 // as if it had. In this way, subsequent requests for lower power from
2234 // a subclassed device object will pre-empt this request.
2236 // We treat this as a subclass object request to switch to the
2237 // highest power state.
2238 //*********************************************************************************
2240 IOReturn
IOService::makeUsable ( void )
2242 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2243 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2246 //*********************************************************************************
2247 // [public] currentCapability
2248 //*********************************************************************************
2250 IOPMPowerFlags
IOService::currentCapability ( void )
2253 return IOPMNotPowerManaged
;
2255 return fCurrentCapabilityFlags
;
2258 //*********************************************************************************
2259 // [public] changePowerStateTo
2261 // Called by our power-controlling driver to change power state. The new desired
2262 // power state is computed and compared against the current power state. If those
2263 // power states differ, then a power state change is initiated.
2264 //*********************************************************************************
2266 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
2268 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2269 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2272 //*********************************************************************************
2273 // [protected] changePowerStateToPriv
2275 // Called by our driver subclass to change power state. The new desired power
2276 // state is computed and compared against the current power state. If those
2277 // power states differ, then a power state change is initiated.
2278 //*********************************************************************************
2280 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
2282 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2283 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2286 //*********************************************************************************
2287 // [protected] changePowerStateWithOverrideTo
2289 // Called by our driver subclass to change power state. The new desired power
2290 // state is computed and compared against the current power state. If those
2291 // power states differ, then a power state change is initiated.
2292 // Override enforced - Children and Driver desires are ignored.
2293 //*********************************************************************************
2295 IOReturn
IOService::changePowerStateWithOverrideTo ( unsigned long ordinal
)
2297 IOPMRequest
* request
;
2300 return kIOPMNotYetInitialized
;
2302 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2304 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2306 return kIOReturnNoMemory
;
2308 gIOPMPowerClientDevice
->retain();
2309 request
->fArg0
= (void *) ordinal
;
2310 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2314 request
->installCompletionAction( action
, target
, param
);
2317 // Prevent needless downwards power transitions by clamping power
2318 // until the scheduled request is executed.
2320 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
))
2322 fTempClampPowerState
= max(fTempClampPowerState
, ordinal
);
2324 fOverrideMaxPowerState
= ordinal
;
2325 request
->fArg2
= (void *) (uintptr_t) true;
2328 submitPMRequest( request
);
2332 //*********************************************************************************
2333 // [private] requestPowerState
2334 //*********************************************************************************
2336 IOReturn
IOService::requestPowerState (
2337 const OSSymbol
* client
,
2340 IOPMRequest
* request
;
2343 return kIOReturnBadArgument
;
2345 return kIOPMNotYetInitialized
;
2347 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2349 return kIOReturnNoMemory
;
2352 request
->fArg0
= (void *) state
;
2353 request
->fArg1
= (void *) client
;
2357 request
->installCompletionAction( action
, target
, param
);
2360 // Prevent needless downwards power transitions by clamping power
2361 // until the scheduled request is executed.
2363 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
))
2365 fTempClampPowerState
= max(fTempClampPowerState
, state
);
2367 request
->fArg2
= (void *) (uintptr_t) true;
2370 submitPMRequest( request
);
2374 //*********************************************************************************
2375 // [private] handleRequestPowerState
2376 //*********************************************************************************
2378 void IOService::handleRequestPowerState ( IOPMRequest
* request
)
2380 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2381 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2383 PM_ASSERT_IN_GATE();
2386 assert(fTempClampCount
!= 0);
2387 if (fTempClampCount
) fTempClampCount
--;
2388 if (!fTempClampCount
) fTempClampPowerState
= 0;
2391 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
))
2392 state
= fNumberOfPowerStates
- 1;
2394 // The power suppression due to changePowerStateWithOverrideTo() expires
2395 // upon the next "device" power request - changePowerStateToPriv().
2397 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2398 (client
== gIOPMPowerClientDevice
))
2399 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2402 (client
!= gIOPMPowerClientDevice
) &&
2403 (client
!= gIOPMPowerClientDriver
) &&
2404 (client
!= gIOPMPowerClientChildProxy
))
2405 removePowerClient(client
);
2407 updatePowerClient(client
, state
);
2413 //*********************************************************************************
2414 // [private] Helper functions to update/remove power clients.
2415 //*********************************************************************************
2417 void IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2420 fPowerClients
= OSDictionary::withCapacity(4);
2421 if (fPowerClients
&& client
)
2423 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2425 num
->setValue(powerState
);
2428 num
= OSNumber::withNumber(powerState
, 32);
2431 fPowerClients
->setObject(client
, num
);
2438 void IOService::removePowerClient( const OSSymbol
* client
)
2440 if (fPowerClients
&& client
)
2441 fPowerClients
->removeObject(client
);
2444 uint32_t IOService::getPowerStateForClient( const OSSymbol
* client
)
2446 uint32_t powerState
= 0;
2448 if (fPowerClients
&& client
)
2450 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2451 if (num
) powerState
= num
->unsigned32BitValue();
2456 //*********************************************************************************
2457 // [protected] powerOverrideOnPriv
2458 //*********************************************************************************
2460 IOReturn
IOService::powerOverrideOnPriv ( void )
2462 IOPMRequest
* request
;
2465 return IOPMNotYetInitialized
;
2467 if (gIOPMWorkLoop
->inGate())
2469 fDeviceOverrideEnabled
= true;
2473 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2475 return kIOReturnNoMemory
;
2477 submitPMRequest( request
);
2481 //*********************************************************************************
2482 // [protected] powerOverrideOffPriv
2483 //*********************************************************************************
2485 IOReturn
IOService::powerOverrideOffPriv ( void )
2487 IOPMRequest
* request
;
2490 return IOPMNotYetInitialized
;
2492 if (gIOPMWorkLoop
->inGate())
2494 fDeviceOverrideEnabled
= false;
2498 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2500 return kIOReturnNoMemory
;
2502 submitPMRequest( request
);
2506 //*********************************************************************************
2507 // [private] handlePowerOverrideChanged
2508 //*********************************************************************************
2510 void IOService::handlePowerOverrideChanged ( IOPMRequest
* request
)
2512 PM_ASSERT_IN_GATE();
2513 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
)
2515 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2516 fDeviceOverrideEnabled
= true;
2520 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2521 fDeviceOverrideEnabled
= false;
2527 //*********************************************************************************
2528 // [private] computeDesiredState
2529 //*********************************************************************************
2531 void IOService::computeDesiredState ( unsigned long localClamp
)
2535 IOPowerConnection
* connection
;
2536 uint32_t desiredState
= 0;
2537 uint32_t newPowerState
= 0;
2538 bool hasChildren
= false;
2540 // Desired power state is always 0 without a controlling driver.
2542 if (!fNumberOfPowerStates
)
2544 fDesiredPowerState
= 0;
2545 //PM_LOG("%s::%s no controlling driver\n", getName(), __FUNCTION__);
2549 // Examine the children's desired power state.
2551 iter
= getChildIterator(gIOPowerPlane
);
2554 while ((next
= iter
->getNextObject()))
2556 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
2558 if (connection
->getReadyFlag() == false)
2560 PM_LOG3("[%s] %s: connection not ready\n",
2561 getName(), __FUNCTION__
);
2564 if (connection
->childHasRequestedPower())
2566 if (connection
->getDesiredDomainState() > desiredState
)
2567 desiredState
= connection
->getDesiredDomainState();
2573 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2575 removePowerClient(gIOPMPowerClientChildren
);
2577 // Iterate through all power clients to determine the min power state.
2579 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2582 const OSSymbol
* client
;
2583 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
2585 // Ignore child and driver when override is in effect.
2586 if ((fDeviceOverrideEnabled
||
2587 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2588 ((client
== gIOPMPowerClientChildren
) ||
2589 (client
== gIOPMPowerClientDriver
)))
2592 // Ignore child proxy when children are present.
2593 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
))
2596 desiredState
= getPowerStateForClient(client
);
2597 assert(desiredState
< fNumberOfPowerStates
);
2599 desiredState
, client
->getCStringNoCopy());
2601 newPowerState
= max(newPowerState
, desiredState
);
2603 if (client
== gIOPMPowerClientDevice
)
2604 fDeviceDesire
= desiredState
;
2609 // Factor in the temporary power desires.
2611 newPowerState
= max(newPowerState
, localClamp
);
2612 newPowerState
= max(newPowerState
, fTempClampPowerState
);
2614 // Limit check against max power override.
2616 newPowerState
= min(newPowerState
, fOverrideMaxPowerState
);
2618 // Limit check against number of power states.
2620 if (newPowerState
>= fNumberOfPowerStates
)
2621 newPowerState
= fNumberOfPowerStates
- 1;
2623 fDesiredPowerState
= newPowerState
;
2625 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2626 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2627 (uint32_t) fCurrentPowerState
, newPowerState
);
2629 // Restart idle timer if stopped and device desire has increased.
2631 if (fDeviceDesire
&& fIdleTimerStopped
)
2633 fIdleTimerStopped
= false;
2634 fActivityTickleCount
= 0;
2635 clock_get_uptime(&fIdleTimerStartTime
);
2636 start_PM_idle_timer();
2639 // Invalidate cached tickle power state when desires change, and not
2640 // due to a tickle request. This invalidation must occur before the
2641 // power state change to minimize races. We want to err on the side
2642 // of servicing more activity tickles rather than dropping one when
2643 // the device is in a low power state.
2645 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2646 (fActivityTicklePowerState
!= -1))
2648 IOLockLock(fActivityLock
);
2649 fActivityTicklePowerState
= -1;
2650 IOLockUnlock(fActivityLock
);
2654 //*********************************************************************************
2655 // [public] currentPowerConsumption
2657 //*********************************************************************************
2659 unsigned long IOService::currentPowerConsumption ( void )
2662 return kIOPMUnknown
;
2664 return fCurrentPowerConsumption
;
2667 //*********************************************************************************
2668 // [deprecated] getPMworkloop
2669 //*********************************************************************************
2671 IOWorkLoop
* IOService::getPMworkloop ( void )
2673 return gIOPMWorkLoop
;
2678 //*********************************************************************************
2679 // Power Parent/Children Applier
2680 //*********************************************************************************
2683 applyToPowerChildren(
2684 IOService
* service
,
2685 IOServiceApplierFunction applier
,
2687 IOOptionBits options
)
2689 PM_ASSERT_IN_GATE();
2691 IORegistryEntry
* entry
;
2692 IORegistryIterator
* iter
;
2693 IOPowerConnection
* connection
;
2696 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2699 while ((entry
= iter
->getNextObject()))
2701 // Get child of IOPowerConnection objects
2702 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2704 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2707 (*applier
)(child
, context
);
2718 IOService
* service
,
2719 IOServiceApplierFunction applier
,
2721 IOOptionBits options
)
2723 PM_ASSERT_IN_GATE();
2725 IORegistryEntry
* entry
;
2726 IORegistryIterator
* iter
;
2727 IOPowerConnection
* connection
;
2730 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2731 options
| kIORegistryIterateParents
);
2734 while ((entry
= iter
->getNextObject()))
2736 // Get child of IOPowerConnection objects
2737 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2739 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2742 (*applier
)(parent
, context
);
2751 #endif /* NOT_YET */
2754 // MARK: Activity Tickle & Idle Timer
2756 //*********************************************************************************
2757 // [public] activityTickle
2759 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2760 // flag to be set, and the device state checked. If the device has been
2761 // powered down, it is powered up again.
2762 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2763 // should be intercepted by a subclass.
2764 //*********************************************************************************
2766 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
2768 IOPMRequest
* request
;
2769 bool noPowerChange
= true;
2771 if ( initialized
&& stateNumber
&& (type
== kIOPMSuperclassPolicy1
) )
2773 IOLockLock(fActivityLock
);
2775 // Record device activity for the idle timer handler.
2777 fDeviceWasActive
= true;
2778 fActivityTickleCount
++;
2779 clock_get_uptime(&fDeviceActiveTimestamp
);
2781 PM_ACTION_0(actionActivityTickle
);
2783 // Record the last tickle power state.
2784 // This helps to filter out redundant tickles as
2785 // this function may be called from the data path.
2787 if (fActivityTicklePowerState
< (long)stateNumber
)
2789 fActivityTicklePowerState
= stateNumber
;
2790 noPowerChange
= false;
2792 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2795 request
->fArg0
= (void *) stateNumber
; // power state
2796 request
->fArg1
= (void *) (uintptr_t) true; // power rise
2797 submitPMRequest(request
);
2801 IOLockUnlock(fActivityLock
);
2804 // Returns false if the activityTickle might cause a transition to a
2805 // higher powered state, true otherwise.
2807 return noPowerChange
;
2810 //*********************************************************************************
2811 // [private] handleActivityTickle
2812 //*********************************************************************************
2814 void IOService::handleActivityTickle ( IOPMRequest
* request
)
2816 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2817 bool adjustPower
= false;
2819 PM_ASSERT_IN_GATE();
2822 // Power rise from activity tickle.
2823 if ((ticklePowerState
> fDeviceDesire
) &&
2824 (ticklePowerState
< fNumberOfPowerStates
))
2826 fIdleTimerMinPowerState
= ticklePowerState
;
2830 else if (fDeviceDesire
> fIdleTimerMinPowerState
)
2832 // Power drop due to idle timer expiration.
2833 // Do not allow idle timer to reduce power below tickle power.
2834 ticklePowerState
= fDeviceDesire
- 1;
2840 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2845 //******************************************************************************
2846 // [public] setIdleTimerPeriod
2848 // A subclass policy-maker is using our standard idleness detection service.
2849 // Start the idle timer. Period is in seconds.
2850 //******************************************************************************
2852 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
2855 return IOPMNotYetInitialized
;
2857 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
2859 IOPMRequest
* request
=
2860 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
2862 return kIOReturnNoMemory
;
2864 request
->fArg0
= (void *) period
;
2865 submitPMRequest( request
);
2867 return kIOReturnSuccess
;
2870 IOReturn
IOService::setIgnoreIdleTimer( bool ignore
)
2873 return IOPMNotYetInitialized
;
2875 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
2877 IOPMRequest
* request
=
2878 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
2880 return kIOReturnNoMemory
;
2882 request
->fArg0
= (void *) ignore
;
2883 submitPMRequest( request
);
2885 return kIOReturnSuccess
;
2888 //******************************************************************************
2889 // [public] nextIdleTimeout
2891 // Returns how many "seconds from now" the device should idle into its
2892 // next lowest power state.
2893 //******************************************************************************
2895 SInt32
IOService::nextIdleTimeout(
2896 AbsoluteTime currentTime
,
2897 AbsoluteTime lastActivity
,
2898 unsigned int powerState
)
2905 // Calculate time difference using funky macro from clock.h.
2906 delta
= currentTime
;
2907 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
2909 // Figure it in seconds.
2910 absolutetime_to_nanoseconds(delta
, &delta_ns
);
2911 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
2913 // Be paranoid about delta somehow exceeding timer period.
2914 if (delta_secs
< (int) fIdleTimerPeriod
)
2915 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
2917 delay_secs
= (int) fIdleTimerPeriod
;
2919 return (SInt32
)delay_secs
;
2922 //*********************************************************************************
2923 // [public] start_PM_idle_timer
2924 //*********************************************************************************
2926 void IOService::start_PM_idle_timer ( void )
2928 static const int maxTimeout
= 100000;
2929 static const int minTimeout
= 1;
2930 AbsoluteTime uptime
, deadline
;
2934 if (!initialized
|| !fIdleTimerPeriod
)
2937 IOLockLock(fActivityLock
);
2939 clock_get_uptime(&uptime
);
2941 // Subclasses may modify idle sleep algorithm
2942 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
2944 // Check for out-of range responses
2945 if (idle_in
> maxTimeout
)
2947 // use standard implementation
2948 idle_in
= IOService::nextIdleTimeout(uptime
,
2949 fDeviceActiveTimestamp
,
2950 fCurrentPowerState
);
2951 } else if (idle_in
< minTimeout
) {
2952 idle_in
= fIdleTimerPeriod
;
2955 IOLockUnlock(fActivityLock
);
2958 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
2959 ADD_ABSOLUTETIME(&deadline
, &uptime
);
2960 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
2961 if (pending
) release();
2964 //*********************************************************************************
2965 // idle_timer_expired
2966 //*********************************************************************************
2969 idle_timer_expired (
2970 thread_call_param_t arg0
, thread_call_param_t arg1
)
2972 IOService
* me
= (IOService
*) arg0
;
2975 gIOPMWorkLoop
->runAction(
2976 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
2977 &IOService::idleTimerExpired
),
2983 //*********************************************************************************
2984 // [private] idleTimerExpired
2986 // The idle timer has expired. If there has been activity since the last
2987 // expiration, just restart the timer and return. If there has not been
2988 // activity, switch to the next lower power state and restart the timer.
2989 //*********************************************************************************
2991 void IOService::idleTimerExpired( void )
2993 IOPMRequest
* request
;
2994 bool restartTimer
= true;
2996 if ( !initialized
|| !fIdleTimerPeriod
|| fLockedFlags
.PMStop
)
2999 IOLockLock(fActivityLock
);
3001 // Check for device activity (tickles) over last timer period.
3003 if (fDeviceWasActive
)
3005 // Device was active - do not drop power, restart timer.
3006 fDeviceWasActive
= false;
3008 else if (!fIdleTimerIgnored
)
3010 // No device activity - drop power state by one level.
3011 // Decrement the cached tickle power state when possible.
3012 // This value may be (-1) before activityTickle() is called,
3013 // but the power drop request must be issued regardless.
3015 if (fActivityTicklePowerState
> 0)
3017 fActivityTicklePowerState
--;
3020 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3023 request
->fArg0
= (void *) 0; // power state (irrelevant)
3024 request
->fArg1
= (void *) (uintptr_t) false; // power drop
3025 submitPMRequest( request
);
3027 // Do not restart timer until after the tickle request has been
3030 restartTimer
= false;
3034 IOLockUnlock(fActivityLock
);
3037 start_PM_idle_timer();
3041 //*********************************************************************************
3042 // [deprecated] PM_idle_timer_expiration
3043 //*********************************************************************************
3045 void IOService::PM_idle_timer_expiration ( void )
3049 //*********************************************************************************
3050 // [deprecated] command_received
3051 //*********************************************************************************
3053 void IOService::command_received ( void *statePtr
, void *, void * , void * )
3056 #endif /* !__LP64__ */
3058 //*********************************************************************************
3059 // [public] setAggressiveness
3061 // Pass on the input parameters to all power domain children. All those which are
3062 // power domains will pass it on to their children, etc.
3063 //*********************************************************************************
3065 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
3067 return kIOReturnSuccess
;
3070 //*********************************************************************************
3071 // [public] getAggressiveness
3073 // Called by the user client.
3074 //*********************************************************************************
3076 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
3078 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3081 return kIOReturnNotReady
;
3083 return rootDomain
->getAggressiveness( type
, currentLevel
);
3086 //*********************************************************************************
3087 // [public] getPowerState
3089 //*********************************************************************************
3091 UInt32
IOService::getPowerState ( void )
3096 return fCurrentPowerState
;
3100 //*********************************************************************************
3101 // [deprecated] systemWake
3103 // Pass this to all power domain children. All those which are
3104 // power domains will pass it on to their children, etc.
3105 //*********************************************************************************
3107 IOReturn
IOService::systemWake ( void )
3111 IOPowerConnection
* connection
;
3112 IOService
* theChild
;
3114 iter
= getChildIterator(gIOPowerPlane
);
3117 while ( (next
= iter
->getNextObject()) )
3119 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
3121 if (connection
->getReadyFlag() == false)
3123 PM_LOG3("[%s] %s: connection not ready\n",
3124 getName(), __FUNCTION__
);
3128 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3131 theChild
->systemWake();
3132 theChild
->release();
3139 if ( fControllingDriver
!= NULL
)
3141 if ( fControllingDriver
->didYouWakeSystem() )
3150 //*********************************************************************************
3151 // [deprecated] temperatureCriticalForZone
3152 //*********************************************************************************
3154 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
3156 IOService
* theParent
;
3159 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3161 if ( inPlane(gIOPowerPlane
) && !IS_PM_ROOT
)
3163 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3166 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3170 theParent
->temperatureCriticalForZone(whichZone
);
3171 theParent
->release();
3177 #endif /* !__LP64__ */
3180 // MARK: Power Change (Common)
3182 //*********************************************************************************
3183 // [private] startPowerChange
3185 // All power state changes starts here.
3186 //*********************************************************************************
3188 IOReturn
IOService::startPowerChange(
3189 IOPMPowerChangeFlags changeFlags
,
3190 IOPMPowerStateIndex powerState
,
3191 IOPMPowerFlags domainFlags
,
3192 IOPowerConnection
* parentConnection
,
3193 IOPMPowerFlags parentFlags
)
3195 PM_ASSERT_IN_GATE();
3196 assert( fMachineState
== kIOPM_Finished
);
3197 assert( powerState
< fNumberOfPowerStates
);
3199 if (powerState
>= fNumberOfPowerStates
)
3200 return IOPMAckImplied
;
3202 fIsPreChange
= true;
3203 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3205 // Forks to either Driver or Parent initiated power change paths.
3207 fHeadNoteChangeFlags
= changeFlags
;
3208 fHeadNotePowerState
= powerState
;
3209 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
3210 fHeadNoteParentConnection
= NULL
;
3212 if (changeFlags
& kIOPMSelfInitiated
)
3214 if (changeFlags
& kIOPMSynchronize
)
3222 assert(changeFlags
& kIOPMParentInitiated
);
3223 fHeadNoteDomainFlags
= domainFlags
;
3224 fHeadNoteParentFlags
= parentFlags
;
3225 fHeadNoteParentConnection
= parentConnection
;
3226 return ParentChangeStart();
3230 //*********************************************************************************
3231 // [private] notifyInterestedDrivers
3232 //*********************************************************************************
3234 bool IOService::notifyInterestedDrivers ( void )
3236 IOPMinformee
* informee
;
3237 IOPMinformeeList
* list
= fInterestedDrivers
;
3238 DriverCallParam
* param
;
3241 PM_ASSERT_IN_GATE();
3242 assert( fDriverCallParamCount
== 0 );
3243 assert( fHeadNotePendingAcks
== 0 );
3245 fHeadNotePendingAcks
= 0;
3247 count
= list
->numberOfItems();
3249 goto done
; // no interested drivers
3251 // Allocate an array of interested drivers and their return values
3252 // for the callout thread. Everything else is still "owned" by the
3253 // PM work loop, which can run to process acknowledgePowerChange()
3256 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3257 if (count
> fDriverCallParamSlots
)
3259 if (fDriverCallParamSlots
)
3261 assert(fDriverCallParamPtr
);
3262 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3263 fDriverCallParamPtr
= 0;
3264 fDriverCallParamSlots
= 0;
3267 param
= IONew(DriverCallParam
, count
);
3269 goto done
; // no memory
3271 fDriverCallParamPtr
= (void *) param
;
3272 fDriverCallParamSlots
= count
;
3275 informee
= list
->firstInList();
3277 for (IOItemCount i
= 0; i
< count
; i
++)
3279 informee
->timer
= -1;
3280 param
[i
].Target
= informee
;
3282 informee
= list
->nextInList( informee
);
3285 fDriverCallParamCount
= count
;
3286 fHeadNotePendingAcks
= count
;
3288 // Block state machine and wait for callout completion.
3289 assert(!fDriverCallBusy
);
3290 fDriverCallBusy
= true;
3291 thread_call_enter( fDriverCallEntry
);
3295 // Return false if there are no interested drivers or could not schedule
3296 // callout thread due to error.
3300 //*********************************************************************************
3301 // [private] notifyInterestedDriversDone
3302 //*********************************************************************************
3304 void IOService::notifyInterestedDriversDone ( void )
3306 IOPMinformee
* informee
;
3308 DriverCallParam
* param
;
3311 PM_ASSERT_IN_GATE();
3312 assert( fDriverCallBusy
== false );
3313 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3315 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3316 count
= fDriverCallParamCount
;
3320 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3322 informee
= (IOPMinformee
*) param
->Target
;
3323 result
= param
->Result
;
3325 if ((result
== IOPMAckImplied
) || (result
< 0))
3327 // Interested driver return IOPMAckImplied.
3328 // If informee timer is zero, it must have de-registered
3329 // interest during the thread callout. That also drops
3330 // the pending ack count.
3332 if (fHeadNotePendingAcks
&& informee
->timer
)
3333 fHeadNotePendingAcks
--;
3335 informee
->timer
= 0;
3337 else if (informee
->timer
)
3339 assert(informee
->timer
== -1);
3341 // Driver has not acked, and has returned a positive result.
3342 // Enforce a minimum permissible timeout value.
3343 // Make the min value large enough so timeout is less likely
3344 // to occur if a driver misinterpreted that the return value
3345 // should be in microsecond units. And make it large enough
3346 // to be noticeable if a driver neglects to ack.
3348 if (result
< kMinAckTimeoutTicks
)
3349 result
= kMinAckTimeoutTicks
;
3351 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3353 // else, child has already acked or driver has removed interest,
3354 // and head_note_pendingAcks decremented.
3355 // informee may have been removed from the interested drivers list,
3356 // thus the informee must be retained across the callout.
3358 informee
->release();
3361 fDriverCallParamCount
= 0;
3363 if ( fHeadNotePendingAcks
)
3365 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3370 MS_POP(); // pushed by notifyAll()
3372 // If interest acks are outstanding, wait for fHeadNotePendingAcks to become
3373 // zero before notifying children. This enforces the children after interest
3374 // ordering even for async interest clients.
3376 if (!fHeadNotePendingAcks
)
3382 MS_PUSH(fMachineState
);
3383 fMachineState
= kIOPM_NotifyChildrenStart
;
3384 PM_LOG2("%s: %u outstanding async interest\n",
3385 getName(), fHeadNotePendingAcks
);
3389 //*********************************************************************************
3390 // [private] notifyChildren
3391 //*********************************************************************************
3393 void IOService::notifyChildren ( void )
3397 IOPowerConnection
* connection
;
3398 OSArray
* children
= 0;
3399 IOPMrootDomain
* rootDomain
;
3400 bool delayNotify
= false;
3402 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3403 (IS_POWER_DROP
== fIsPreChange
) &&
3404 ((rootDomain
= getPMRootDomain()) == this))
3406 rootDomain
->tracePoint( IS_POWER_DROP
?
3407 kIOPMTracePointSleepPowerPlaneDrivers
:
3408 kIOPMTracePointWakePowerPlaneDrivers
);
3411 if (fStrictTreeOrder
)
3412 children
= OSArray::withCapacity(8);
3414 // Sum child power consumption in notifyChild()
3415 fHeadNotePowerArrayEntry
->staticPower
= 0;
3417 iter
= getChildIterator(gIOPowerPlane
);
3420 while ((next
= iter
->getNextObject()))
3422 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3424 if (connection
->getReadyFlag() == false)
3426 PM_LOG3("[%s] %s: connection not ready\n",
3427 getName(), __FUNCTION__
);
3431 // Mechanism to postpone the did-change notification to
3432 // certain power children to order those children last.
3433 // Cannot be used together with strict tree ordering.
3435 if (!fIsPreChange
&&
3436 (connection
->delayChildNotification
) &&
3437 getPMRootDomain()->shouldDelayChildNotification(this))
3441 children
= OSArray::withCapacity(8);
3447 children
->setObject( connection
);
3452 if (!delayNotify
&& children
)
3453 children
->setObject( connection
);
3455 notifyChild( connection
);
3461 if (children
&& (children
->getCount() == 0))
3463 children
->release();
3468 assert(fNotifyChildArray
== 0);
3469 fNotifyChildArray
= children
;
3470 MS_PUSH(fMachineState
);
3474 // Wait for exiting child notifications to complete,
3475 // before notifying the children in the array.
3476 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3477 PM_LOG2("%s: %d children in delayed array\n",
3478 getName(), children
->getCount());
3482 // Notify children in the array one at a time.
3483 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3488 //*********************************************************************************
3489 // [private] notifyChildrenOrdered
3490 //*********************************************************************************
3492 void IOService::notifyChildrenOrdered ( void )
3494 PM_ASSERT_IN_GATE();
3495 assert(fNotifyChildArray
);
3496 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3498 // Notify one child, wait for it to ack, then repeat for next child.
3499 // This is a workaround for some drivers with multiple instances at
3500 // the same branch in the power tree, but the driver is slow to power
3501 // up unless the tree ordering is observed. Problem observed only on
3502 // system wake, not on system sleep.
3504 // We have the ability to power off in reverse child index order.
3505 // That works nicely on some machines, but not on all HW configs.
3507 if (fNotifyChildArray
->getCount())
3509 IOPowerConnection
* connection
;
3510 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3511 fNotifyChildArray
->removeObject(0);
3512 notifyChild( connection
);
3516 fNotifyChildArray
->release();
3517 fNotifyChildArray
= 0;
3519 MS_POP(); // pushed by notifyChildren()
3523 //*********************************************************************************
3524 // [private] notifyChildrenDelayed
3525 //*********************************************************************************
3527 void IOService::notifyChildrenDelayed ( void )
3529 IOPowerConnection
* connection
;
3531 PM_ASSERT_IN_GATE();
3532 assert(fNotifyChildArray
);
3533 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3535 // Wait after all non-delayed children and interested drivers have ack'ed,
3536 // then notify all delayed children. When explicitly cancelled, interest
3537 // acks (and ack timer) may still be outstanding.
3539 for (int i
= 0; ; i
++)
3541 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3545 notifyChild( connection
);
3548 PM_LOG2("%s: notified delayed children\n", getName());
3549 fNotifyChildArray
->release();
3550 fNotifyChildArray
= 0;
3552 MS_POP(); // pushed by notifyChildren()
3555 //*********************************************************************************
3556 // [private] notifyAll
3557 //*********************************************************************************
3559 IOReturn
IOService::notifyAll ( uint32_t nextMS
)
3561 // Save the next machine_state to be restored by notifyInterestedDriversDone()
3563 PM_ASSERT_IN_GATE();
3565 fMachineState
= kIOPM_DriverThreadCallDone
;
3566 fDriverCallReason
= fIsPreChange
?
3567 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3569 if (!notifyInterestedDrivers())
3570 notifyInterestedDriversDone();
3572 return IOPMWillAckLater
;
3575 //*********************************************************************************
3576 // [private, static] pmDriverCallout
3578 // Thread call context
3579 //*********************************************************************************
3581 IOReturn
IOService::actionDriverCalloutDone (
3583 void * arg0
, void * arg1
,
3584 void * arg2
, void * arg3
)
3586 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3588 assert( fDriverCallBusy
);
3589 fDriverCallBusy
= false;
3591 assert(gIOPMWorkQueue
);
3592 gIOPMWorkQueue
->signalWorkAvailable();
3594 return kIOReturnSuccess
;
3597 void IOService::pmDriverCallout ( IOService
* from
)
3600 switch (from
->fDriverCallReason
)
3602 case kDriverCallSetPowerState
:
3603 from
->driverSetPowerState();
3606 case kDriverCallInformPreChange
:
3607 case kDriverCallInformPostChange
:
3608 from
->driverInformPowerChange();
3612 panic("IOService::pmDriverCallout bad machine state %x",
3613 from
->fDriverCallReason
);
3616 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3618 /* arg0 */ (void *) from
->pwrMgt
);
3621 //*********************************************************************************
3622 // [private] driverSetPowerState
3624 // Thread call context
3625 //*********************************************************************************
3627 void IOService::driverSetPowerState ( void )
3629 IOPMPowerStateIndex powerState
;
3630 DriverCallParam
* param
;
3631 IOPMDriverCallEntry callEntry
;
3634 uint32_t oldPowerState
= getPowerState();
3636 assert( fDriverCallBusy
);
3637 assert( fDriverCallParamPtr
);
3638 assert( fDriverCallParamCount
== 1 );
3640 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3641 powerState
= fHeadNotePowerState
;
3643 if (assertPMDriverCall(&callEntry
))
3645 OUR_PMLog( kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3646 clock_get_uptime(&fDriverCallStartTime
);
3647 result
= fControllingDriver
->setPowerState( powerState
, this );
3648 clock_get_uptime(&end
);
3649 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3651 deassertPMDriverCall(&callEntry
);
3655 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
3656 fName
, this, fCurrentPowerState
, powerState
, result
);
3659 #if LOG_SETPOWER_TIMES
3660 if ((result
== IOPMAckImplied
) || (result
< 0))
3664 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
3665 absolutetime_to_nanoseconds(end
, &nsec
);
3666 if (nsec
> LOG_SETPOWER_TIMES
)
3667 PM_LOG("%s::setPowerState(%p, %lu -> %lu) took %d ms\n",
3668 fName
, this, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3670 PMEventDetails
*details
= PMEventDetails::eventDetails(
3671 kIOPMEventTypeSetPowerStateImmediate
, // type
3673 (uintptr_t)this, // owner unique
3674 NULL
, // interest name
3675 (uint8_t)oldPowerState
, // old
3676 (uint8_t)powerState
, // new
3678 NS_TO_US(nsec
)); // usec completion time
3680 getPMRootDomain()->recordAndReleasePMEventGated( details
);
3685 result
= kIOPMAckImplied
;
3687 param
->Result
= result
;
3690 //*********************************************************************************
3691 // [private] driverInformPowerChange
3693 // Thread call context
3694 //*********************************************************************************
3696 void IOService::driverInformPowerChange ( void )
3698 IOPMinformee
* informee
;
3700 DriverCallParam
* param
;
3701 IOPMDriverCallEntry callEntry
;
3702 IOPMPowerFlags powerFlags
;
3703 IOPMPowerStateIndex powerState
;
3708 assert( fDriverCallBusy
);
3709 assert( fDriverCallParamPtr
);
3710 assert( fDriverCallParamCount
);
3712 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3713 count
= fDriverCallParamCount
;
3715 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
3716 powerState
= fHeadNotePowerState
;
3718 for (IOItemCount i
= 0; i
< count
; i
++)
3720 informee
= (IOPMinformee
*) param
->Target
;
3721 driver
= informee
->whatObject
;
3723 if (assertPMDriverCall(&callEntry
, 0, informee
))
3725 if (fDriverCallReason
== kDriverCallInformPreChange
)
3727 OUR_PMLog(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
3728 clock_get_uptime(&informee
->startTime
);
3729 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
3730 clock_get_uptime(&end
);
3731 OUR_PMLog((UInt32
)-kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
3735 OUR_PMLog(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
3736 clock_get_uptime(&informee
->startTime
);
3737 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
3738 clock_get_uptime(&end
);
3739 OUR_PMLog((UInt32
)-kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
3742 deassertPMDriverCall(&callEntry
);
3744 #if LOG_SETPOWER_TIMES
3745 if ((result
== IOPMAckImplied
) || (result
< 0))
3749 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
3750 absolutetime_to_nanoseconds(end
, &nsec
);
3751 if (nsec
> LOG_SETPOWER_TIMES
)
3752 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) took %d ms\n",
3754 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
3755 driver
, fName
, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3757 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
3758 ? kIOPMEventTypePSWillChangeTo
3759 : kIOPMEventTypePSDidChangeTo
;
3761 PMEventDetails
*details
= PMEventDetails::eventDetails(
3764 (uintptr_t)this, // owner unique
3765 driver
->getName(), // interest name
3766 (uint8_t)fCurrentPowerState
, // old
3767 (uint8_t)fHeadNotePowerState
, // new
3769 NS_TO_US(nsec
)); // usec completion time
3771 getPMRootDomain()->recordAndReleasePMEventGated( details
);
3776 result
= kIOPMAckImplied
;
3778 param
->Result
= result
;
3783 //*********************************************************************************
3784 // [private] notifyChild
3786 // Notify a power domain child of an upcoming power change.
3787 // If the object acknowledges the current change, we return TRUE.
3788 //*********************************************************************************
3790 bool IOService::notifyChild ( IOPowerConnection
* theNub
)
3792 IOReturn ret
= IOPMAckImplied
;
3793 unsigned long childPower
;
3794 IOService
* theChild
;
3795 IOPMRequest
* childRequest
;
3796 IOPMPowerChangeFlags requestArg2
;
3799 PM_ASSERT_IN_GATE();
3800 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
3807 // Unless the child handles the notification immediately and returns
3808 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
3809 fHeadNotePendingAcks
++;
3810 theNub
->setAwaitingAck(true);
3812 requestArg2
= fHeadNoteChangeFlags
;
3813 if (fHeadNotePowerState
< fCurrentPowerState
)
3814 requestArg2
|= kIOPMDomainPowerDrop
;
3816 requestType
= fIsPreChange
?
3817 kIOPMRequestTypePowerDomainWillChange
:
3818 kIOPMRequestTypePowerDomainDidChange
;
3820 childRequest
= acquirePMRequest( theChild
, requestType
);
3824 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
3825 childRequest
->fArg1
= (void *) theNub
;
3826 childRequest
->fArg2
= (void *) requestArg2
;
3827 theChild
->submitPMRequest( childRequest
);
3828 ret
= IOPMWillAckLater
;
3832 ret
= IOPMAckImplied
;
3833 fHeadNotePendingAcks
--;
3834 theNub
->setAwaitingAck(false);
3835 childPower
= theChild
->currentPowerConsumption();
3836 if ( childPower
== kIOPMUnknown
)
3838 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
3840 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
3841 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
3845 theChild
->release();
3846 return (IOPMAckImplied
== ret
);
3849 //*********************************************************************************
3850 // [private] notifyControllingDriver
3851 //*********************************************************************************
3853 bool IOService::notifyControllingDriver ( void )
3855 DriverCallParam
* param
;
3857 PM_ASSERT_IN_GATE();
3858 assert( fDriverCallParamCount
== 0 );
3859 assert( fControllingDriver
);
3861 if (fInitialSetPowerState
)
3863 // Driver specified flag to skip the inital setPowerState()
3864 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)
3868 fInitialSetPowerState
= false;
3871 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3874 param
= IONew(DriverCallParam
, 1);
3876 return false; // no memory
3878 fDriverCallParamPtr
= (void *) param
;
3879 fDriverCallParamSlots
= 1;
3882 param
->Target
= fControllingDriver
;
3883 fDriverCallParamCount
= 1;
3886 // Block state machine and wait for callout completion.
3887 assert(!fDriverCallBusy
);
3888 fDriverCallBusy
= true;
3889 thread_call_enter( fDriverCallEntry
);
3894 //*********************************************************************************
3895 // [private] notifyControllingDriverDone
3896 //*********************************************************************************
3898 void IOService::notifyControllingDriverDone( void )
3900 DriverCallParam
* param
;
3903 PM_ASSERT_IN_GATE();
3904 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3906 assert( fDriverCallBusy
== false );
3907 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3909 if (param
&& fDriverCallParamCount
)
3911 assert(fDriverCallParamCount
== 1);
3913 // the return value from setPowerState()
3914 result
= param
->Result
;
3916 if ((result
== IOPMAckImplied
) || (result
< 0))
3920 else if (fDriverTimer
)
3922 assert(fDriverTimer
== -1);
3924 // Driver has not acked, and has returned a positive result.
3925 // Enforce a minimum permissible timeout value.
3926 // Make the min value large enough so timeout is less likely
3927 // to occur if a driver misinterpreted that the return value
3928 // should be in microsecond units. And make it large enough
3929 // to be noticeable if a driver neglects to ack.
3931 if (result
< kMinAckTimeoutTicks
)
3932 result
= kMinAckTimeoutTicks
;
3934 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3936 // else, child has already acked and driver_timer reset to 0.
3938 fDriverCallParamCount
= 0;
3942 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3947 MS_POP(); // pushed by OurChangeSetPowerState()
3948 fIsPreChange
= false;
3951 //*********************************************************************************
3952 // [private] all_done
3954 // A power change is done.
3955 //*********************************************************************************
3957 void IOService::all_done ( void )
3959 IOPMPowerStateIndex prevPowerState
;
3960 const IOPMPSEntry
* powerStatePtr
;
3961 IOPMDriverCallEntry callEntry
;
3962 uint32_t prevMachineState
= fMachineState
;
3963 bool callAction
= false;
3965 fMachineState
= kIOPM_Finished
;
3967 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
3968 ((prevMachineState
== kIOPM_Finished
) ||
3969 (prevMachineState
== kIOPM_SyncFinish
)))
3971 // Sync operation and no power change occurred.
3972 // Do not inform driver and clients about this request completion,
3973 // except for the originator (root domain).
3975 PM_ACTION_2(actionPowerChangeDone
,
3976 fHeadNotePowerState
, fHeadNoteChangeFlags
);
3978 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
3980 powerChangeDone(fCurrentPowerState
);
3987 if ( fHeadNoteChangeFlags
& kIOPMSelfInitiated
)
3989 // could our driver switch to the new state?
3990 if ( !( fHeadNoteChangeFlags
& kIOPMNotDone
) )
3992 // we changed, tell our parent
3993 requestDomainPower(fHeadNotePowerState
);
3995 // yes, did power raise?
3996 if ( fCurrentPowerState
< fHeadNotePowerState
)
3998 // yes, inform clients and apps
3999 tellChangeUp (fHeadNotePowerState
);
4001 prevPowerState
= fCurrentPowerState
;
4003 fCurrentPowerState
= fHeadNotePowerState
;
4005 fPMVars
->myCurrentState
= fCurrentPowerState
;
4007 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, 0);
4008 PM_ACTION_2(actionPowerChangeDone
,
4009 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4012 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4013 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4014 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4015 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4017 // inform subclass policy-maker
4018 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4019 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4021 powerChangeDone(prevPowerState
);
4022 deassertPMDriverCall(&callEntry
);
4025 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
4027 // changePowerStateWithOverrideTo() was cancelled
4028 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4032 // parent's power change
4033 if ( fHeadNoteChangeFlags
& kIOPMParentInitiated
)
4035 if (((fHeadNoteChangeFlags
& kIOPMDomainWillChange
) &&
4036 (fCurrentPowerState
>= fHeadNotePowerState
)) ||
4037 ((fHeadNoteChangeFlags
& kIOPMDomainDidChange
) &&
4038 (fCurrentPowerState
< fHeadNotePowerState
)))
4040 if ((fHeadNoteChangeFlags
& kIOPMPowerSuppressed
) &&
4041 (fHeadNotePowerState
!= fCurrentPowerState
) &&
4042 (fHeadNotePowerState
== fDesiredPowerState
))
4044 // Power changed, and desired power state restored.
4045 // Clear any prior power desire while in suppressed state.
4046 requestDomainPower(fHeadNotePowerState
);
4050 if ( fCurrentPowerState
< fHeadNotePowerState
)
4052 // yes, inform clients and apps
4053 tellChangeUp (fHeadNotePowerState
);
4056 prevPowerState
= fCurrentPowerState
;
4057 fCurrentPowerState
= fHeadNotePowerState
;
4059 fPMVars
->myCurrentState
= fCurrentPowerState
;
4061 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fHeadNoteDomainFlags
);
4063 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, 0);
4064 PM_ACTION_2(actionPowerChangeDone
,
4065 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4068 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4069 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4070 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4071 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4073 // inform subclass policy-maker
4074 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4075 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4077 powerChangeDone(prevPowerState
);
4078 deassertPMDriverCall(&callEntry
);
4083 // When power rises enough to satisfy the tickle's desire for more power,
4084 // the condition preventing idle-timer from dropping power is removed.
4086 if (fCurrentPowerState
>= fIdleTimerMinPowerState
)
4088 fIdleTimerMinPowerState
= 0;
4093 PM_ACTION_2(actionPowerChangeDone
,
4094 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4099 // MARK: Power Change Initiated by Driver
4101 //*********************************************************************************
4102 // [private] OurChangeStart
4104 // Begin the processing of a power change initiated by us.
4105 //*********************************************************************************
4107 void IOService::OurChangeStart ( void )
4109 PM_ASSERT_IN_GATE();
4110 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4112 // fMaxPowerState is our maximum possible power state based on the current
4113 // power state of our parents. If we are trying to raise power beyond the
4114 // maximum, send an async request for more power to all parents.
4116 if (!IS_PM_ROOT
&& (fMaxPowerState
< fHeadNotePowerState
))
4118 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4119 requestDomainPower(fHeadNotePowerState
);
4124 // Redundant power changes skips to the end of the state machine.
4126 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
4131 fInitialPowerChange
= false;
4133 // Change started, but may not complete...
4134 // Can be canceled (power drop) or deferred (power rise).
4136 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4138 // Two separate paths, depending if power is being raised or lowered.
4139 // Lowering power is subject to approval by clients of this service.
4143 fDoNotPowerDown
= false;
4145 // Ask for persmission to drop power state
4146 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4147 fOutOfBandParameter
= kNotifyApps
;
4148 askChangeDown(fHeadNotePowerState
);
4152 // This service is raising power and parents are able to support the
4153 // new power state. However a parent may have already committed to
4154 // drop power, which might force this object to temporarily drop power.
4155 // This results in "oscillations" before the state machines converge
4156 // to a steady state.
4158 // To prevent this, a child must make a power reservation against all
4159 // parents before raising power. If the reservation fails, indicating
4160 // that the child will be unable to sustain the higher power state,
4161 // then the child will signal the parent to adjust power, and the child
4162 // will defer its power change.
4166 // Reserve parent power necessary to achieve fHeadNotePowerState.
4167 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4168 if (ret
!= kIOReturnSuccess
)
4170 // Reservation failed, defer power rise.
4171 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4176 OurChangeTellCapabilityWillChange();
4180 //*********************************************************************************
4182 struct IOPMRequestDomainPowerContext
{
4183 IOService
* child
; // the requesting child
4184 IOPMPowerFlags requestPowerFlags
; // power flags requested by child
4188 requestDomainPowerApplier(
4189 IORegistryEntry
* entry
,
4192 IOPowerConnection
* connection
;
4194 IOPMRequestDomainPowerContext
* context
;
4196 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0)
4198 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4203 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4205 if (connection
->parentKnowsState() && connection
->getReadyFlag())
4207 parent
->requestPowerDomainState(
4208 context
->requestPowerFlags
,
4216 //*********************************************************************************
4217 // [private] requestDomainPower
4218 //*********************************************************************************
4220 IOReturn
IOService::requestDomainPower(
4221 IOPMPowerStateIndex ourPowerState
,
4222 IOOptionBits options
)
4224 const IOPMPSEntry
* powerStateEntry
;
4225 IOPMPowerFlags requestPowerFlags
;
4226 IOPMPowerStateIndex maxPowerState
;
4227 IOPMRequestDomainPowerContext context
;
4229 PM_ASSERT_IN_GATE();
4230 assert(ourPowerState
< fNumberOfPowerStates
);
4231 if (ourPowerState
>= fNumberOfPowerStates
)
4232 return kIOReturnBadArgument
;
4234 return kIOReturnSuccess
;
4236 // Fetch the input power flags for the requested power state.
4237 // Parent request is stated in terms of required power flags.
4239 powerStateEntry
= &fPowerStates
[ourPowerState
];
4240 requestPowerFlags
= powerStateEntry
->inputPowerFlags
;
4242 if (powerStateEntry
->capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
))
4243 requestPowerFlags
|= kIOPMPreventIdleSleep
;
4244 if (powerStateEntry
->capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
))
4245 requestPowerFlags
|= kIOPMPreventSystemSleep
;
4247 // Disregard the "previous request" for power reservation.
4249 if (((options
& kReserveDomainPower
) == 0) &&
4250 (fPreviousRequestPowerFlags
== requestPowerFlags
))
4252 // skip if domain already knows our requirements
4255 fPreviousRequestPowerFlags
= requestPowerFlags
;
4257 context
.child
= this;
4258 context
.requestPowerFlags
= requestPowerFlags
;
4259 fHeadNoteDomainTargetFlags
= 0;
4260 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4262 if (options
& kReserveDomainPower
)
4264 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4265 fHeadNoteDomainTargetFlags
);
4267 if (maxPowerState
< fHeadNotePowerState
)
4269 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4271 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4272 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4273 return kIOReturnNoPower
;
4278 return kIOReturnSuccess
;
4281 //*********************************************************************************
4282 // [private] OurSyncStart
4283 //*********************************************************************************
4285 void IOService::OurSyncStart ( void )
4287 PM_ASSERT_IN_GATE();
4289 if (fInitialPowerChange
)
4292 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4294 if (fHeadNoteChangeFlags
& kIOPMNotDone
)
4300 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
)
4302 fDoNotPowerDown
= false;
4304 // Ask for permission to drop power state
4305 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4306 fOutOfBandParameter
= kNotifyApps
;
4307 askChangeDown(fHeadNotePowerState
);
4311 // Only inform capability app and clients.
4312 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4316 //*********************************************************************************
4317 // [private] OurChangeTellClientsPowerDown
4319 // All applications and kernel clients have acknowledged our permission to drop
4320 // power. Here we notify them that we will lower the power and wait for acks.
4321 //*********************************************************************************
4323 void IOService::OurChangeTellClientsPowerDown ( void )
4325 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4326 tellChangeDown1(fHeadNotePowerState
);
4329 //*********************************************************************************
4330 // [private] OurChangeTellPriorityClientsPowerDown
4332 // All applications and kernel clients have acknowledged our intention to drop
4333 // power. Here we notify "priority" clients that we are lowering power.
4334 //*********************************************************************************
4336 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
4338 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4339 tellChangeDown2(fHeadNotePowerState
);
4342 //*********************************************************************************
4343 // [private] OurChangeTellCapabilityWillChange
4345 // Extra stage for root domain to notify apps and drivers about the
4346 // system capability change when raising power state.
4347 //*********************************************************************************
4349 void IOService::OurChangeTellCapabilityWillChange ( void )
4351 if (!IS_ROOT_DOMAIN
)
4352 return OurChangeNotifyInterestedDriversWillChange();
4354 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4357 //*********************************************************************************
4358 // [private] OurChangeNotifyInterestedDriversWillChange
4360 // All applications and kernel clients have acknowledged our power state change.
4361 // Here we notify interested drivers pre-change.
4362 //*********************************************************************************
4364 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
4366 IOPMrootDomain
* rootDomain
;
4367 if ((rootDomain
= getPMRootDomain()) == this)
4371 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4373 PMEventDetails
*details
= PMEventDetails::eventDetails(
4374 kIOPMEventTypeAppNotificationsFinished
,
4378 rootDomain
->recordAndReleasePMEventGated( details
);
4381 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4384 notifyAll( kIOPM_OurChangeSetPowerState
);
4387 //*********************************************************************************
4388 // [private] OurChangeSetPowerState
4390 // Instruct our controlling driver to program the hardware for the power state
4391 // change. Wait for async completions.
4392 //*********************************************************************************
4394 void IOService::OurChangeSetPowerState ( void )
4396 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4397 fMachineState
= kIOPM_DriverThreadCallDone
;
4398 fDriverCallReason
= kDriverCallSetPowerState
;
4400 if (notifyControllingDriver() == false)
4401 notifyControllingDriverDone();
4404 //*********************************************************************************
4405 // [private] OurChangeWaitForPowerSettle
4407 // Our controlling driver has completed the power state change we initiated.
4408 // Wait for the driver specified settle time to expire.
4409 //*********************************************************************************
4411 void IOService::OurChangeWaitForPowerSettle ( void )
4413 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4417 //*********************************************************************************
4418 // [private] OurChangeNotifyInterestedDriversDidChange
4420 // Power has settled on a power change we initiated. Here we notify
4421 // all our interested drivers post-change.
4422 //*********************************************************************************
4424 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
4426 IOPMrootDomain
* rootDomain
;
4427 if ((rootDomain
= getPMRootDomain()) == this)
4429 rootDomain
->tracePoint( IS_POWER_DROP
?
4430 kIOPMTracePointSleepDidChangeInterests
:
4431 kIOPMTracePointWakeDidChangeInterests
);
4434 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4437 //*********************************************************************************
4438 // [private] OurChangeTellCapabilityDidChange
4440 // For root domain to notify capability power-change.
4441 //*********************************************************************************
4443 void IOService::OurChangeTellCapabilityDidChange ( void )
4445 if (!IS_ROOT_DOMAIN
)
4446 return OurChangeFinish();
4448 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4449 kIOPMTracePointSleepCapabilityClients
:
4450 kIOPMTracePointWakeCapabilityClients
);
4452 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4455 //*********************************************************************************
4456 // [private] OurChangeFinish
4458 // Done with this self-induced power state change.
4459 //*********************************************************************************
4461 void IOService::OurChangeFinish ( void )
4467 // MARK: Power Change Initiated by Parent
4469 //*********************************************************************************
4470 // [private] ParentChangeStart
4472 // Here we begin the processing of a power change initiated by our parent.
4473 //*********************************************************************************
4475 IOReturn
IOService::ParentChangeStart ( void )
4477 PM_ASSERT_IN_GATE();
4478 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4480 // Power domain is lowering power
4481 if ( fHeadNotePowerState
< fCurrentPowerState
)
4483 // TODO: redundant? See handlePowerDomainWillChangeTo()
4484 setParentInfo( fHeadNoteParentFlags
, fHeadNoteParentConnection
, true );
4486 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4488 // Tell apps and kernel clients
4489 fInitialPowerChange
= false;
4490 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4491 tellChangeDown1(fHeadNotePowerState
);
4492 return IOPMWillAckLater
;
4495 // Power domain is raising power
4496 if ( fHeadNotePowerState
> fCurrentPowerState
)
4498 if ( fDesiredPowerState
> fCurrentPowerState
)
4500 if ( fDesiredPowerState
< fHeadNotePowerState
)
4502 // We power up, but not all the way
4503 fHeadNotePowerState
= fDesiredPowerState
;
4504 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4505 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4508 // We don't need to change
4509 fHeadNotePowerState
= fCurrentPowerState
;
4510 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4511 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4515 if ( fHeadNoteChangeFlags
& kIOPMDomainDidChange
)
4517 if ( fHeadNotePowerState
> fCurrentPowerState
)
4519 PM_ACTION_2(actionPowerChangeStart
,
4520 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4522 // Parent did change up - start our change up
4523 fInitialPowerChange
= false;
4524 ParentChangeTellCapabilityWillChange();
4525 return IOPMWillAckLater
;
4527 else if (fHeadNoteChangeFlags
& kIOPMSynchronize
)
4529 // We do not need to change power state, but notify
4530 // children to propagate tree synchronization.
4531 fMachineState
= kIOPM_SyncNotifyDidChange
;
4532 fDriverCallReason
= kDriverCallInformPreChange
;
4534 return IOPMWillAckLater
;
4539 return IOPMAckImplied
;
4542 //*********************************************************************************
4543 // [private] ParentChangeTellPriorityClientsPowerDown
4545 // All applications and kernel clients have acknowledged our intention to drop
4546 // power. Here we notify "priority" clients that we are lowering power.
4547 //*********************************************************************************
4549 void IOService::ParentChangeTellPriorityClientsPowerDown ( void )
4551 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
4552 tellChangeDown2(fHeadNotePowerState
);
4555 //*********************************************************************************
4556 // [private] ParentChangeTellCapabilityWillChange
4558 // All (legacy) applications and kernel clients have acknowledged, extra stage for
4559 // root domain to notify apps and drivers about the system capability change.
4560 //*********************************************************************************
4562 void IOService::ParentChangeTellCapabilityWillChange ( void )
4564 if (!IS_ROOT_DOMAIN
)
4565 return ParentChangeNotifyInterestedDriversWillChange();
4567 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
4570 //*********************************************************************************
4571 // [private] ParentChangeNotifyInterestedDriversWillChange
4573 // All applications and kernel clients have acknowledged our power state change.
4574 // Here we notify interested drivers pre-change.
4575 //*********************************************************************************
4577 void IOService::ParentChangeNotifyInterestedDriversWillChange ( void )
4579 notifyAll( kIOPM_ParentChangeSetPowerState
);
4582 //*********************************************************************************
4583 // [private] ParentChangeSetPowerState
4585 // Instruct our controlling driver to program the hardware for the power state
4586 // change. Wait for async completions.
4587 //*********************************************************************************
4589 void IOService::ParentChangeSetPowerState ( void )
4591 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
4592 fMachineState
= kIOPM_DriverThreadCallDone
;
4593 fDriverCallReason
= kDriverCallSetPowerState
;
4595 if (notifyControllingDriver() == false)
4596 notifyControllingDriverDone();
4599 //*********************************************************************************
4600 // [private] ParentChangeWaitForPowerSettle
4602 // Our controlling driver has completed the power state change initiated by our
4603 // parent. Wait for the driver specified settle time to expire.
4604 //*********************************************************************************
4606 void IOService::ParentChangeWaitForPowerSettle ( void )
4608 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
4612 //*********************************************************************************
4613 // [private] ParentChangeNotifyInterestedDriversDidChange
4615 // Power has settled on a power change initiated by our parent. Here we notify
4616 // all our interested drivers post-change.
4617 //*********************************************************************************
4619 void IOService::ParentChangeNotifyInterestedDriversDidChange ( void )
4621 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
4624 //*********************************************************************************
4625 // [private] ParentChangeTellCapabilityDidChange
4627 // For root domain to notify capability power-change.
4628 //*********************************************************************************
4630 void IOService::ParentChangeTellCapabilityDidChange ( void )
4632 if (!IS_ROOT_DOMAIN
)
4633 return ParentChangeAcknowledgePowerChange();
4635 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
4638 //*********************************************************************************
4639 // [private] ParentAcknowledgePowerChange
4641 // Acknowledge our power parent that our power change is done.
4642 //*********************************************************************************
4644 void IOService::ParentChangeAcknowledgePowerChange ( void )
4646 IORegistryEntry
* nub
;
4649 nub
= fHeadNoteParentConnection
;
4652 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
4655 parent
->acknowledgePowerChange((IOService
*)nub
);
4662 // MARK: Ack and Settle timers
4664 //*********************************************************************************
4665 // [private] settleTimerExpired
4667 // Power has settled after our last change. Notify interested parties that
4668 // there is a new power state.
4669 //*********************************************************************************
4671 void IOService::settleTimerExpired( void )
4674 gIOPMWorkQueue
->signalWorkAvailable();
4677 //*********************************************************************************
4678 // settle_timer_expired
4680 // Holds a retain while the settle timer callout is in flight.
4681 //*********************************************************************************
4684 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
4686 IOService
* me
= (IOService
*) arg0
;
4688 if (gIOPMWorkLoop
&& gIOPMWorkQueue
)
4690 gIOPMWorkLoop
->runAction(
4691 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
4697 //*********************************************************************************
4698 // [private] startSettleTimer
4700 // Calculate a power-settling delay in microseconds and start a timer.
4701 //*********************************************************************************
4703 void IOService::startSettleTimer( void )
4705 AbsoluteTime deadline
;
4706 IOPMPowerStateIndex i
;
4707 uint32_t settleTime
= 0;
4710 PM_ASSERT_IN_GATE();
4712 i
= fCurrentPowerState
;
4715 if ( fHeadNotePowerState
< fCurrentPowerState
)
4717 while ( i
> fHeadNotePowerState
)
4719 settleTime
+= (uint32_t) fPowerStates
[i
].settleDownTime
;
4725 if ( fHeadNotePowerState
> fCurrentPowerState
)
4727 while ( i
< fHeadNotePowerState
)
4729 settleTime
+= (uint32_t) fPowerStates
[i
+1].settleUpTime
;
4737 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
4738 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
4739 if (pending
) release();
4743 //*********************************************************************************
4744 // [private] ackTimerTick
4746 // The acknowledgement timeout periodic timer has ticked.
4747 // If we are awaiting acks for a power change notification,
4748 // we decrement the timer word of each interested driver which hasn't acked.
4749 // If a timer word becomes zero, we pretend the driver aknowledged.
4750 // If we are waiting for the controlling driver to change the power
4751 // state of the hardware, we decrement its timer word, and if it becomes
4752 // zero, we pretend the driver acknowledged.
4754 // Returns true if the timer tick made it possible to advance to the next
4755 // machine state, false otherwise.
4756 //*********************************************************************************
4759 void IOService::ack_timer_ticked ( void )
4763 #endif /* !__LP64__ */
4765 bool IOService::ackTimerTick( void )
4767 IOPMinformee
* nextObject
;
4770 PM_ASSERT_IN_GATE();
4771 switch (fMachineState
) {
4772 case kIOPM_OurChangeWaitForPowerSettle
:
4773 case kIOPM_ParentChangeWaitForPowerSettle
:
4774 // are we waiting for controlling driver to acknowledge?
4775 if ( fDriverTimer
> 0 )
4777 // yes, decrement timer tick
4779 if ( fDriverTimer
== 0 )
4781 // controlling driver is tardy
4782 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
4783 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
4784 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
4785 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
4786 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
4788 #if LOG_SETPOWER_TIMES
4789 PMEventDetails
*details
= PMEventDetails::eventDetails(
4790 kIOPMEventTypeSetPowerStateDelayed
, // type
4792 (uintptr_t)this, // owner unique
4793 NULL
, // interest name
4794 (uint8_t)getPowerState(), // old
4796 kIOReturnTimeout
, // result
4797 NS_TO_US(nsec
)); // usec completion time
4799 getPMRootDomain()->recordAndReleasePMEventGated( details
);
4802 if (gIOKitDebug
& kIOLogDebugPower
)
4804 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
4805 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
4809 // Unblock state machine and pretend driver has acked.
4813 // still waiting, set timer again
4819 case kIOPM_NotifyChildrenStart
:
4820 // are we waiting for interested parties to acknowledge?
4821 if ( fHeadNotePendingAcks
!= 0 )
4823 // yes, go through the list of interested drivers
4824 nextObject
= fInterestedDrivers
->firstInList();
4825 // and check each one
4826 while ( nextObject
!= NULL
)
4828 if ( nextObject
->timer
> 0 )
4830 nextObject
->timer
--;
4831 // this one should have acked by now
4832 if ( nextObject
->timer
== 0 )
4834 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
4835 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
4836 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
4837 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
4838 nextObject
->whatObject
->getName(),
4839 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
4840 nextObject
->whatObject
, fName
, fCurrentPowerState
, fHeadNotePowerState
,
4843 #if LOG_SETPOWER_TIMES
4844 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
4845 ? kIOPMEventTypePSWillChangeTo
4846 : kIOPMEventTypePSDidChangeTo
;
4848 PMEventDetails
*details
= PMEventDetails::eventDetails(
4851 (uintptr_t)this, // owner unique
4852 nextObject
->whatObject
->getName(), // interest name
4853 (uint8_t)fCurrentPowerState
, // old
4854 (uint8_t)fHeadNotePowerState
, // new
4855 kIOReturnTimeout
, // result
4856 NS_TO_US(nsec
)); // usec completion time
4858 getPMRootDomain()->recordAndReleasePMEventGated( details
);
4861 // Pretend driver has acked.
4862 fHeadNotePendingAcks
--;
4865 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
4868 // is that the last?
4869 if ( fHeadNotePendingAcks
== 0 )
4871 // yes, we can continue
4874 // no, set timer again
4880 // TODO: aggreggate this
4881 case kIOPM_OurChangeTellClientsPowerDown
:
4882 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
4883 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
4884 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
4885 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
4886 case kIOPM_SyncTellClientsPowerDown
:
4887 case kIOPM_SyncTellPriorityClientsPowerDown
:
4888 case kIOPM_SyncNotifyWillChange
:
4889 case kIOPM_TellCapabilityChangeDone
:
4890 // apps didn't respond in time
4891 cleanClientResponses(true);
4892 OUR_PMLog(kPMLogClientTardy
, 0, 1);
4893 // tardy equates to approval
4898 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
4899 getName(), fMachineState
);
4905 //*********************************************************************************
4906 // [private] start_ack_timer
4907 //*********************************************************************************
4909 void IOService::start_ack_timer ( void )
4911 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
4914 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
4916 AbsoluteTime deadline
;
4919 clock_interval_to_deadline(interval
, scale
, &deadline
);
4922 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
4923 if (pending
) release();
4926 //*********************************************************************************
4927 // [private] stop_ack_timer
4928 //*********************************************************************************
4930 void IOService::stop_ack_timer ( void )
4934 pending
= thread_call_cancel(fAckTimer
);
4935 if (pending
) release();
4938 //*********************************************************************************
4939 // [static] actionAckTimerExpired
4941 // Inside PM work loop's gate.
4942 //*********************************************************************************
4945 IOService::actionAckTimerExpired (
4947 void * arg0
, void * arg1
,
4948 void * arg2
, void * arg3
)
4950 IOService
* me
= (IOService
*) target
;
4953 // done will be true if the timer tick unblocks the machine state,
4954 // otherwise no need to signal the work loop.
4956 done
= me
->ackTimerTick();
4957 if (done
&& gIOPMWorkQueue
)
4958 gIOPMWorkQueue
->signalWorkAvailable();
4960 return kIOReturnSuccess
;
4963 //*********************************************************************************
4964 // ack_timer_expired
4966 // Thread call function. Holds a retain while the callout is in flight.
4967 //*********************************************************************************
4970 IOService::ack_timer_expired ( thread_call_param_t arg0
, thread_call_param_t arg1
)
4972 IOService
* me
= (IOService
*) arg0
;
4976 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
4982 // MARK: Client Messaging
4984 //*********************************************************************************
4985 // [private] tellSystemCapabilityChange
4986 //*********************************************************************************
4988 void IOService::tellSystemCapabilityChange( uint32_t nextMS
)
4991 fMachineState
= kIOPM_TellCapabilityChangeDone
;
4992 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
4996 // Notify app first on pre-change.
4997 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5001 // Notify kernel clients first on post-change.
5002 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5005 tellClientsWithResponse( fOutOfBandMessage
);
5008 //*********************************************************************************
5009 // [public] askChangeDown
5011 // Ask registered applications and kernel clients if we can change to a lower
5014 // Subclass can override this to send a different message type. Parameter is
5015 // the destination state number.
5017 // Return true if we don't have to wait for acknowledgements
5018 //*********************************************************************************
5020 bool IOService::askChangeDown ( unsigned long stateNum
)
5022 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5025 //*********************************************************************************
5026 // [private] tellChangeDown1
5028 // Notify registered applications and kernel clients that we are definitely
5031 // Return true if we don't have to wait for acknowledgements
5032 //*********************************************************************************
5034 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
5036 fOutOfBandParameter
= kNotifyApps
;
5037 return tellChangeDown(stateNum
);
5040 //*********************************************************************************
5041 // [private] tellChangeDown2
5043 // Notify priority clients that we are definitely dropping power.
5045 // Return true if we don't have to wait for acknowledgements
5046 //*********************************************************************************
5048 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
5050 fOutOfBandParameter
= kNotifyPriority
;
5051 return tellChangeDown(stateNum
);
5054 //*********************************************************************************
5055 // [public] tellChangeDown
5057 // Notify registered applications and kernel clients that we are definitely
5060 // Subclass can override this to send a different message type. Parameter is
5061 // the destination state number.
5063 // Return true if we don't have to wait for acknowledgements
5064 //*********************************************************************************
5066 bool IOService::tellChangeDown ( unsigned long stateNum
)
5068 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5071 //*********************************************************************************
5072 // cleanClientResponses
5074 //*********************************************************************************
5076 static void logAppTimeouts ( OSObject
* object
, void * arg
)
5078 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5080 unsigned int clientIndex
;
5082 if (OSDynamicCast(_IOServiceInterestNotifier
, object
))
5084 // Discover the 'counter' value or index assigned to this client
5085 // when it was notified, by searching for the array index of the
5086 // client in an array holding the cached interested clients.
5088 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5090 if ((clientIndex
!= (unsigned int) -1) &&
5091 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5092 (flag
!= kOSBooleanTrue
))
5094 OSString
* clientID
= 0;
5095 context
->us
->messageClient(context
->messageType
, object
, &clientID
);
5096 PM_ERROR(context
->errorLog
, clientID
? clientID
->getCStringNoCopy() : "");
5098 // TODO: record message type if possible
5099 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5100 gIOPMStatsApplicationResponseTimedOut
,
5101 clientID
? clientID
->getCStringNoCopy() : "",
5105 clientID
->release();
5110 void IOService::cleanClientResponses ( bool logErrors
)
5112 if (logErrors
&& fResponseArray
)
5114 switch ( fOutOfBandParameter
) {
5116 case kNotifyCapabilityChangeApps
:
5117 if (fNotifyClientArray
)
5119 IOPMInterestContext context
;
5121 context
.responseArray
= fResponseArray
;
5122 context
.notifyClients
= fNotifyClientArray
;
5123 context
.serialNumber
= fSerialNumber
;
5124 context
.messageType
= kIOMessageCopyClientID
;
5125 context
.notifyType
= kNotifyApps
;
5126 context
.isPreChange
= fIsPreChange
;
5127 context
.enableTracing
= false;
5129 context
.maxTimeRequested
= 0;
5130 context
.stateNumber
= fHeadNotePowerState
;
5131 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5132 context
.changeFlags
= fHeadNoteChangeFlags
;
5133 context
.errorLog
= "PM notification timeout (%s)\n";
5135 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5140 // kNotifyPriority, kNotifyCapabilityChangePriority
5141 // TODO: identify the priority client that has not acked
5142 PM_ERROR("PM priority notification timeout\n");
5143 if (gIOKitDebug
& kIOLogDebugPower
)
5145 panic("PM priority notification timeout");
5153 fResponseArray
->release();
5154 fResponseArray
= NULL
;
5156 if (fNotifyClientArray
)
5158 fNotifyClientArray
->release();
5159 fNotifyClientArray
= NULL
;
5163 //*********************************************************************************
5164 // [protected] tellClientsWithResponse
5166 // Notify registered applications and kernel clients that we are definitely
5169 // Return true if we don't have to wait for acknowledgements
5170 //*********************************************************************************
5172 bool IOService::tellClientsWithResponse ( int messageType
)
5174 IOPMInterestContext context
;
5175 bool isRootDomain
= IS_ROOT_DOMAIN
;
5177 PM_ASSERT_IN_GATE();
5178 assert( fResponseArray
== NULL
);
5179 assert( fNotifyClientArray
== NULL
);
5181 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5182 getIOMessageString(messageType
), fOutOfBandParameter
);
5184 fResponseArray
= OSArray::withCapacity( 1 );
5185 if (!fResponseArray
)
5188 fResponseArray
->setCapacityIncrement(8);
5189 if (++fSerialNumber
== 0)
5192 context
.responseArray
= fResponseArray
;
5193 context
.notifyClients
= 0;
5194 context
.serialNumber
= fSerialNumber
;
5195 context
.messageType
= messageType
;
5196 context
.notifyType
= fOutOfBandParameter
;
5197 context
.isPreChange
= fIsPreChange
;
5198 context
.enableTracing
= false;
5200 context
.maxTimeRequested
= 0;
5201 context
.stateNumber
= fHeadNotePowerState
;
5202 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5203 context
.changeFlags
= fHeadNoteChangeFlags
;
5204 context
.messageFilter
= (isRootDomain
) ?
5205 OSMemberFunctionCast(
5208 &IOPMrootDomain::systemMessageFilter
) : 0;
5210 switch ( fOutOfBandParameter
) {
5212 applyToInterested( gIOAppPowerStateInterest
,
5213 pmTellAppWithResponse
, (void *) &context
);
5216 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5217 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
))
5219 // Notify capability app for tellChangeDown1()
5220 // but not for askChangeDown().
5221 context
.notifyType
= kNotifyCapabilityChangeApps
;
5222 context
.messageType
= kIOMessageSystemCapabilityChange
;
5223 applyToInterested( gIOAppPowerStateInterest
,
5224 pmTellCapabilityAppWithResponse
, (void *) &context
);
5225 context
.notifyType
= fOutOfBandParameter
;
5226 context
.messageType
= messageType
;
5228 context
.maxTimeRequested
= k30seconds
;
5230 applyToInterested( gIOGeneralInterest
,
5231 pmTellClientWithResponse
, (void *) &context
);
5233 fNotifyClientArray
= context
.notifyClients
;
5236 case kNotifyPriority
:
5237 context
.enableTracing
= isRootDomain
;
5238 applyToInterested( gIOPriorityPowerStateInterest
,
5239 pmTellClientWithResponse
, (void *) &context
);
5243 // Notify capability clients for tellChangeDown2().
5244 context
.notifyType
= kNotifyCapabilityChangePriority
;
5245 context
.messageType
= kIOMessageSystemCapabilityChange
;
5246 applyToInterested( gIOPriorityPowerStateInterest
,
5247 pmTellCapabilityClientWithResponse
, (void *) &context
);
5251 case kNotifyCapabilityChangeApps
:
5252 applyToInterested( gIOAppPowerStateInterest
,
5253 pmTellCapabilityAppWithResponse
, (void *) &context
);
5254 fNotifyClientArray
= context
.notifyClients
;
5255 context
.maxTimeRequested
= k30seconds
;
5258 case kNotifyCapabilityChangePriority
:
5259 applyToInterested( gIOPriorityPowerStateInterest
,
5260 pmTellCapabilityClientWithResponse
, (void *) &context
);
5264 // do we have to wait for somebody?
5265 if ( !checkForDone() )
5267 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5268 if (context
.enableTracing
)
5269 getPMRootDomain()->traceDetail( context
.maxTimeRequested
/ 1000 );
5270 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5275 // everybody responded
5278 fResponseArray
->release();
5279 fResponseArray
= NULL
;
5281 if (fNotifyClientArray
)
5283 fNotifyClientArray
->release();
5284 fNotifyClientArray
= NULL
;
5290 //*********************************************************************************
5291 // [static private] pmTellAppWithResponse
5293 // We send a message to an application, and we expect a response, so we compute a
5294 // cookie we can identify the response with.
5295 //*********************************************************************************
5297 void IOService::pmTellAppWithResponse ( OSObject
* object
, void * arg
)
5299 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5300 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5301 uint32_t msgIndex
, msgRef
, msgType
;
5302 #if LOG_APP_RESPONSE_TIMES
5306 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5309 if (context
->messageFilter
&&
5310 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5312 if (kIOLogDebugPower
& gIOKitDebug
)
5314 // Log client pid/name and client array index.
5315 OSString
* clientID
= 0;
5316 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
5317 PM_LOG("%s DROP App %s, %s\n",
5318 context
->us
->getName(),
5319 getIOMessageString(context
->messageType
),
5320 clientID
? clientID
->getCStringNoCopy() : "");
5321 if (clientID
) clientID
->release();
5326 // Create client array (for tracking purposes) only if the service
5327 // has app clients. Usually only root domain does.
5328 if (0 == context
->notifyClients
)
5329 context
->notifyClients
= OSArray::withCapacity( 32 );
5331 msgType
= context
->messageType
;
5332 msgIndex
= context
->responseArray
->getCount();
5333 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5335 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
5336 if (kIOLogDebugPower
& gIOKitDebug
)
5338 // Log client pid/name and client array index.
5339 OSString
* clientID
= 0;
5340 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
5341 PM_LOG("%s MESG App(%u) %s, %s\n",
5342 context
->us
->getName(),
5343 msgIndex
, getIOMessageString(msgType
),
5344 clientID
? clientID
->getCStringNoCopy() : "");
5345 if (clientID
) clientID
->release();
5348 #if LOG_APP_RESPONSE_TIMES
5350 clock_get_uptime(&now
);
5351 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
5354 context
->responseArray
->setObject(msgIndex
, num
);
5359 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
5361 if (context
->notifyClients
)
5362 context
->notifyClients
->setObject(msgIndex
, object
);
5364 context
->us
->messageClient(msgType
, object
, (void *) msgRef
);
5367 //*********************************************************************************
5368 // [static private] pmTellClientWithResponse
5370 // We send a message to an in-kernel client, and we expect a response,
5371 // so we compute a cookie we can identify the response with.
5372 //*********************************************************************************
5374 void IOService::pmTellClientWithResponse ( OSObject
* object
, void * arg
)
5376 IOPowerStateChangeNotification notify
;
5377 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5378 OSObject
* replied
= kOSBooleanTrue
;
5379 _IOServiceInterestNotifier
* notifier
;
5380 uint32_t msgIndex
, msgRef
, msgType
;
5383 if (context
->messageFilter
&&
5384 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5386 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5387 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5389 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5390 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5391 context
->us
->getName(),
5392 getIOMessageString(context
->messageType
),
5393 object
, n
->handler
);
5398 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5399 msgType
= context
->messageType
;
5400 msgIndex
= context
->responseArray
->getCount();
5401 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5403 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5404 if (gIOKitDebug
& kIOLogPower
) {
5405 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
5406 if (OSDynamicCast(IOService
, object
)) {
5407 const char *who
= ((IOService
*) object
)->getName();
5408 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
5410 else if (notifier
) {
5411 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
5414 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
5416 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5417 context
->us
->getName(),
5418 getIOMessageString(msgType
),
5419 object
, notifier
->handler
);
5422 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
5423 notify
.returnValue
= 0;
5424 notify
.stateNumber
= context
->stateNumber
;
5425 notify
.stateFlags
= context
->stateFlags
;
5427 if (context
->enableTracing
&& (notifier
!= 0))
5429 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
5430 ((msgType
& 0xfff) << 12) |
5431 (((uintptr_t) notifier
->handler
) & 0xfff);
5432 getPMRootDomain()->traceDetail( detail
);
5435 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
5436 if ( kIOReturnSuccess
== retCode
)
5438 if ( 0 == notify
.returnValue
)
5440 // client doesn't want time to respond
5441 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
5445 replied
= kOSBooleanFalse
;
5446 if ( notify
.returnValue
> context
->maxTimeRequested
)
5448 if (notify
.returnValue
> kPriorityClientMaxWait
)
5450 context
->maxTimeRequested
= kPriorityClientMaxWait
;
5451 PM_ERROR("%s: client %p returned %llu for %s\n",
5452 context
->us
->getName(),
5453 notifier
? (void *) notifier
->handler
: object
,
5454 (uint64_t) notify
.returnValue
,
5455 getIOMessageString(msgType
));
5458 context
->maxTimeRequested
= notify
.returnValue
;
5464 // not a client of ours
5465 // so we won't be waiting for response
5466 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
5469 context
->responseArray
->setObject(msgIndex
, replied
);
5472 //*********************************************************************************
5473 // [static private] pmTellCapabilityAppWithResponse
5474 //*********************************************************************************
5476 void IOService::pmTellCapabilityAppWithResponse ( OSObject
* object
, void * arg
)
5478 IOPMSystemCapabilityChangeParameters msgArg
;
5479 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5480 OSObject
* replied
= kOSBooleanTrue
;
5481 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5482 uint32_t msgIndex
, msgRef
, msgType
;
5483 #if LOG_APP_RESPONSE_TIMES
5487 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5490 memset(&msgArg
, 0, sizeof(msgArg
));
5491 if (context
->messageFilter
&&
5492 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
))
5497 // Create client array (for tracking purposes) only if the service
5498 // has app clients. Usually only root domain does.
5499 if (0 == context
->notifyClients
)
5500 context
->notifyClients
= OSArray::withCapacity( 32 );
5502 msgType
= context
->messageType
;
5503 msgIndex
= context
->responseArray
->getCount();
5504 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5506 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
5507 if (kIOLogDebugPower
& gIOKitDebug
)
5509 // Log client pid/name and client array index.
5510 OSString
* clientID
= 0;
5511 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
5512 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
5513 context
->us
->getName(),
5514 msgIndex
, getIOMessageString(msgType
),
5515 (replied
!= kOSBooleanTrue
),
5516 clientID
? clientID
->getCStringNoCopy() : "");
5517 if (clientID
) clientID
->release();
5520 msgArg
.notifyRef
= msgRef
;
5521 msgArg
.maxWaitForReply
= 0;
5523 if (replied
== kOSBooleanTrue
)
5525 msgArg
.notifyRef
= 0;
5526 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
5527 if (context
->notifyClients
)
5528 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
5532 #if LOG_APP_RESPONSE_TIMES
5534 clock_get_uptime(&now
);
5535 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
5538 context
->responseArray
->setObject(msgIndex
, num
);
5543 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
5545 if (context
->notifyClients
)
5546 context
->notifyClients
->setObject(msgIndex
, object
);
5549 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
5552 //*********************************************************************************
5553 // [static private] pmTellCapabilityClientWithResponse
5554 //*********************************************************************************
5556 void IOService::pmTellCapabilityClientWithResponse(
5557 OSObject
* object
, void * arg
)
5559 IOPMSystemCapabilityChangeParameters msgArg
;
5560 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5561 OSObject
* replied
= kOSBooleanTrue
;
5562 _IOServiceInterestNotifier
* notifier
;
5563 uint32_t msgIndex
, msgRef
, msgType
;
5566 memset(&msgArg
, 0, sizeof(msgArg
));
5567 if (context
->messageFilter
&&
5568 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, 0))
5570 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5571 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5573 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5574 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5575 context
->us
->getName(),
5576 getIOMessageString(context
->messageType
),
5577 object
, n
->handler
);
5582 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5583 msgType
= context
->messageType
;
5584 msgIndex
= context
->responseArray
->getCount();
5585 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5587 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5588 if (gIOKitDebug
& kIOLogPower
) {
5589 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
5590 if (OSDynamicCast(IOService
, object
)) {
5591 const char *who
= ((IOService
*) object
)->getName();
5592 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
5594 else if (notifier
) {
5595 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
5598 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
5600 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5601 context
->us
->getName(),
5602 getIOMessageString(msgType
),
5603 object
, notifier
->handler
);
5606 msgArg
.notifyRef
= msgRef
;
5607 msgArg
.maxWaitForReply
= 0;
5609 if (context
->enableTracing
&& (notifier
!= 0))
5611 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
5612 ((msgType
& 0xfff) << 12) |
5613 (((uintptr_t) notifier
->handler
) & 0xfff);
5614 getPMRootDomain()->traceDetail( detail
);
5617 retCode
= context
->us
->messageClient(
5618 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
5620 if ( kIOReturnSuccess
== retCode
)
5622 if ( 0 == msgArg
.maxWaitForReply
)
5624 // client doesn't want time to respond
5625 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
5629 replied
= kOSBooleanFalse
;
5630 if ( msgArg
.maxWaitForReply
> context
->maxTimeRequested
)
5632 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
)
5634 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
5635 PM_ERROR("%s: client %p returned %u for %s\n",
5636 context
->us
->getName(),
5637 notifier
? (void *) notifier
->handler
: object
,
5638 msgArg
.maxWaitForReply
,
5639 getIOMessageString(msgType
));
5642 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
5648 // not a client of ours
5649 // so we won't be waiting for response
5650 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
5653 context
->responseArray
->setObject(msgIndex
, replied
);
5656 //*********************************************************************************
5657 // [public] tellNoChangeDown
5659 // Notify registered applications and kernel clients that we are not
5662 // Subclass can override this to send a different message type. Parameter is
5663 // the aborted destination state number.
5664 //*********************************************************************************
5666 void IOService::tellNoChangeDown ( unsigned long )
5668 return tellClients( kIOMessageDeviceWillNotPowerOff
);
5671 //*********************************************************************************
5672 // [public] tellChangeUp
5674 // Notify registered applications and kernel clients that we are raising power.
5676 // Subclass can override this to send a different message type. Parameter is
5677 // the aborted destination state number.
5678 //*********************************************************************************
5680 void IOService::tellChangeUp ( unsigned long )
5682 return tellClients( kIOMessageDeviceHasPoweredOn
);
5685 //*********************************************************************************
5686 // [protected] tellClients
5688 // Notify registered applications and kernel clients of something.
5689 //*********************************************************************************
5691 void IOService::tellClients ( int messageType
)
5693 IOPMInterestContext context
;
5695 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
5697 memset(&context
, 0, sizeof(context
));
5698 context
.messageType
= messageType
;
5699 context
.isPreChange
= fIsPreChange
;
5701 context
.stateNumber
= fHeadNotePowerState
;
5702 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5703 context
.changeFlags
= fHeadNoteChangeFlags
;
5704 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
5705 OSMemberFunctionCast(
5708 &IOPMrootDomain::systemMessageFilter
) : 0;
5710 context
.notifyType
= kNotifyPriority
;
5711 applyToInterested( gIOPriorityPowerStateInterest
,
5712 tellKernelClientApplier
, (void *) &context
);
5714 context
.notifyType
= kNotifyApps
;
5715 applyToInterested( gIOAppPowerStateInterest
,
5716 tellAppClientApplier
, (void *) &context
);
5718 applyToInterested( gIOGeneralInterest
,
5719 tellKernelClientApplier
, (void *) &context
);
5722 //*********************************************************************************
5723 // [private] tellKernelClientApplier
5725 // Message a kernel client.
5726 //*********************************************************************************
5728 static void tellKernelClientApplier ( OSObject
* object
, void * arg
)
5730 IOPowerStateChangeNotification notify
;
5731 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5733 if (context
->messageFilter
&&
5734 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5736 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5737 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5739 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5740 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5741 context
->us
->getName(),
5742 IOService::getIOMessageString(context
->messageType
),
5743 object
, n
->handler
);
5748 notify
.powerRef
= (void *) 0;
5749 notify
.returnValue
= 0;
5750 notify
.stateNumber
= context
->stateNumber
;
5751 notify
.stateFlags
= context
->stateFlags
;
5753 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
5755 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5756 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5758 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5759 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5760 context
->us
->getName(),
5761 IOService::getIOMessageString(context
->messageType
),
5762 object
, n
->handler
);
5766 //*********************************************************************************
5767 // [private] tellAppClientApplier
5769 // Message a registered application.
5770 //*********************************************************************************
5772 static void tellAppClientApplier ( OSObject
* object
, void * arg
)
5774 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5776 if (context
->messageFilter
&&
5777 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5779 if (kIOLogDebugPower
& gIOKitDebug
)
5781 // Log client pid/name and client array index.
5782 OSString
* clientID
= 0;
5783 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
5784 PM_LOG("%s DROP App %s, %s\n",
5785 context
->us
->getName(),
5786 IOService::getIOMessageString(context
->messageType
),
5787 clientID
? clientID
->getCStringNoCopy() : "");
5788 if (clientID
) clientID
->release();
5793 if (kIOLogDebugPower
& gIOKitDebug
)
5795 // Log client pid/name and client array index.
5796 OSString
* clientID
= 0;
5797 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
5798 PM_LOG("%s MESG App %s, %s\n",
5799 context
->us
->getName(),
5800 IOService::getIOMessageString(context
->messageType
),
5801 clientID
? clientID
->getCStringNoCopy() : "");
5802 if (clientID
) clientID
->release();
5805 context
->us
->messageClient(context
->messageType
, object
, 0);
5808 //*********************************************************************************
5809 // [private] checkForDone
5810 //*********************************************************************************
5812 bool IOService::checkForDone ( void )
5817 if ( fResponseArray
== NULL
)
5822 for ( i
= 0; ; i
++ )
5824 theFlag
= fResponseArray
->getObject(i
);
5825 if ( theFlag
== NULL
)
5829 if ( kOSBooleanTrue
!= theFlag
)
5837 //*********************************************************************************
5838 // [public] responseValid
5839 //*********************************************************************************
5841 bool IOService::responseValid ( uint32_t refcon
, int pid
)
5843 UInt16 serialComponent
;
5844 UInt16 ordinalComponent
;
5847 serialComponent
= (refcon
>> 16) & 0xFFFF;
5848 ordinalComponent
= (refcon
& 0xFFFF);
5850 if ( serialComponent
!= fSerialNumber
)
5855 if ( fResponseArray
== NULL
)
5860 theFlag
= fResponseArray
->getObject(ordinalComponent
);
5868 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
5870 #if LOG_APP_RESPONSE_TIMES
5874 OSString
*name
= IOCopyLogNameForPID(pid
);
5876 clock_get_uptime(&now
);
5877 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
5878 SUB_ABSOLUTETIME(&now
, &start
);
5879 absolutetime_to_nanoseconds(now
, &nsec
);
5881 PMEventDetails
*details
= PMEventDetails::eventDetails(
5882 kIOPMEventTypeAppResponse
, // type
5883 name
? name
->getCStringNoCopy() : "", // who
5884 (uintptr_t)pid
, // owner unique
5885 NULL
, // interest name
5889 NS_TO_US(nsec
)); // usec completion time
5891 getPMRootDomain()->recordAndReleasePMEventGated( details
);
5893 if (kIOLogDebugPower
& gIOKitDebug
)
5895 PM_LOG("Ack(%u) %u ms\n",
5896 (uint32_t) ordinalComponent
,
5901 if (nsec
> LOG_APP_RESPONSE_TIMES
)
5903 PM_LOG("PM response took %d ms (%s)\n", NS_TO_MS(nsec
),
5904 name
? name
->getCStringNoCopy() : "");
5906 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
5908 // TODO: populate the messageType argument
5909 getPMRootDomain()->pmStatsRecordApplicationResponse(
5910 gIOPMStatsApplicationResponseSlow
,
5911 name
? name
->getCStringNoCopy() : "", 0,
5912 NS_TO_MS(nsec
), pid
);
5919 theFlag
= kOSBooleanFalse
;
5922 if ( kOSBooleanFalse
== theFlag
)
5924 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
5930 //*********************************************************************************
5931 // [public] allowPowerChange
5933 // Our power state is about to lower, and we have notified applications
5934 // and kernel clients, and one of them has acknowledged. If this is the last to do
5935 // so, and all acknowledgements are positive, we continue with the power change.
5936 //*********************************************************************************
5938 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
5940 IOPMRequest
* request
;
5945 return kIOReturnSuccess
;
5948 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
5950 return kIOReturnNoMemory
;
5952 request
->fArg0
= (void *) refcon
;
5953 request
->fArg1
= (void *) proc_selfpid();
5954 request
->fArg2
= (void *) 0;
5955 submitPMRequest( request
);
5957 return kIOReturnSuccess
;
5961 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
5963 // [deprecated] public
5964 return kIOReturnUnsupported
;
5966 #endif /* !__LP64__ */
5968 //*********************************************************************************
5969 // [public] cancelPowerChange
5971 // Our power state is about to lower, and we have notified applications
5972 // and kernel clients, and one of them has vetoed the change. If this is the last
5973 // client to respond, we abandon the power change.
5974 //*********************************************************************************
5976 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
5978 IOPMRequest
* request
;
5984 return kIOReturnSuccess
;
5987 name
= IOCopyLogNameForPID(proc_selfpid());
5988 PM_ERROR("PM notification cancel (%s)\n", name
? name
->getCStringNoCopy() : "");
5990 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
5995 return kIOReturnNoMemory
;
5998 request
->fArg0
= (void *) refcon
;
5999 request
->fArg1
= (void *) proc_selfpid();
6000 request
->fArg2
= (void *) name
;
6001 submitPMRequest( request
);
6003 return kIOReturnSuccess
;
6007 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
6009 // [deprecated] public
6010 return kIOReturnUnsupported
;
6013 //*********************************************************************************
6014 // PM_Clamp_Timer_Expired
6016 // called when clamp timer expires...set power state to 0.
6017 //*********************************************************************************
6019 void IOService::PM_Clamp_Timer_Expired ( void )
6023 //*********************************************************************************
6026 // Set to highest available power state for a minimum of duration milliseconds
6027 //*********************************************************************************
6029 void IOService::clampPowerOn ( unsigned long duration
)
6032 #endif /* !__LP64__ */
6035 // MARK: Driver Overrides
6037 //*********************************************************************************
6038 // [public] setPowerState
6040 // Does nothing here. This should be implemented in a subclass driver.
6041 //*********************************************************************************
6043 IOReturn
IOService::setPowerState (
6044 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
6049 //*********************************************************************************
6050 // [public] maxCapabilityForDomainState
6052 // Finds the highest power state in the array whose input power
6053 // requirement is equal to the input parameter. Where a more intelligent
6054 // decision is possible, override this in the subclassed driver.
6055 //*********************************************************************************
6057 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
6061 if (fNumberOfPowerStates
== 0 )
6065 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
6067 if ( (domainState
& fPowerStates
[i
].inputPowerFlags
) ==
6068 fPowerStates
[i
].inputPowerFlags
)
6076 //*********************************************************************************
6077 // [public] initialPowerStateForDomainState
6079 // Finds the highest power state in the array whose input power
6080 // requirement is equal to the input parameter. Where a more intelligent
6081 // decision is possible, override this in the subclassed driver.
6082 //*********************************************************************************
6084 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
6088 if (fNumberOfPowerStates
== 0 )
6092 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
6094 if ( (domainState
& fPowerStates
[i
].inputPowerFlags
) ==
6095 fPowerStates
[i
].inputPowerFlags
)
6103 //*********************************************************************************
6104 // [public] powerStateForDomainState
6106 // Finds the highest power state in the array whose input power
6107 // requirement is equal to the input parameter. Where a more intelligent
6108 // decision is possible, override this in the subclassed driver.
6109 //*********************************************************************************
6111 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
6115 if (fNumberOfPowerStates
== 0 )
6119 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
6121 if ( (domainState
& fPowerStates
[i
].inputPowerFlags
) ==
6122 fPowerStates
[i
].inputPowerFlags
)
6131 //*********************************************************************************
6132 // [deprecated] didYouWakeSystem
6134 // Does nothing here. This should be implemented in a subclass driver.
6135 //*********************************************************************************
6137 bool IOService::didYouWakeSystem ( void )
6141 #endif /* !__LP64__ */
6143 //*********************************************************************************
6144 // [public] powerStateWillChangeTo
6146 // Does nothing here. This should be implemented in a subclass driver.
6147 //*********************************************************************************
6149 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
6151 return kIOPMAckImplied
;
6154 //*********************************************************************************
6155 // [public] powerStateDidChangeTo
6157 // Does nothing here. This should be implemented in a subclass driver.
6158 //*********************************************************************************
6160 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
6162 return kIOPMAckImplied
;
6165 //*********************************************************************************
6166 // [protected] powerChangeDone
6168 // Called from PM work loop thread.
6169 // Does nothing here. This should be implemented in a subclass policy-maker.
6170 //*********************************************************************************
6172 void IOService::powerChangeDone ( unsigned long )
6177 //*********************************************************************************
6178 // [deprecated] newTemperature
6180 // Does nothing here. This should be implemented in a subclass driver.
6181 //*********************************************************************************
6183 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
6187 #endif /* !__LP64__ */
6189 //*********************************************************************************
6190 // [public] systemWillShutdown
6192 // System shutdown and restart notification.
6193 //*********************************************************************************
6195 void IOService::systemWillShutdown( IOOptionBits specifier
)
6197 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
6199 rootDomain
->acknowledgeSystemWillShutdown( this );
6203 // MARK: PM State Machine
6205 //*********************************************************************************
6206 // [private static] acquirePMRequest
6207 //*********************************************************************************
6210 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
6211 IOPMRequest
* active
)
6213 IOPMRequest
* request
;
6217 request
= IOPMRequest::create();
6220 request
->init( target
, requestType
);
6223 IOPMRequest
* root
= active
->getRootRequest();
6224 if (root
) request
->attachRootRequest(root
);
6229 PM_ERROR("%s: No memory for PM request type 0x%x\n",
6230 target
->getName(), (uint32_t) requestType
);
6235 //*********************************************************************************
6236 // [private static] releasePMRequest
6237 //*********************************************************************************
6239 void IOService::releasePMRequest( IOPMRequest
* request
)
6248 //*********************************************************************************
6249 // [private] submitPMRequest
6250 //*********************************************************************************
6252 void IOService::submitPMRequest( IOPMRequest
* request
)
6255 assert( gIOPMReplyQueue
);
6256 assert( gIOPMRequestQueue
);
6258 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6259 (long)request
->getType(), request
,
6260 request
->getTarget(), request
->getTarget()->getName(),
6261 request
->fArg0
, request
->fArg1
, request
->fArg2
);
6263 if (request
->isReplyType())
6264 gIOPMReplyQueue
->queuePMRequest( request
);
6266 gIOPMRequestQueue
->queuePMRequest( request
);
6269 void IOService::submitPMRequest( IOPMRequest
** requests
, IOItemCount count
)
6272 assert( count
> 0 );
6273 assert( gIOPMRequestQueue
);
6275 for (IOItemCount i
= 0; i
< count
; i
++)
6277 IOPMRequest
* req
= requests
[i
];
6278 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6279 (long)req
->getType(), req
,
6280 req
->getTarget(), req
->getTarget()->getName(),
6281 req
->fArg0
, req
->fArg1
, req
->fArg2
);
6284 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
6287 //*********************************************************************************
6288 // [private] servicePMRequestQueue
6290 // Called from IOPMRequestQueue::checkForWork().
6291 //*********************************************************************************
6293 bool IOService::servicePMRequestQueue(
6294 IOPMRequest
* request
,
6295 IOPMRequestQueue
* queue
)
6301 // Work queue will immediately execute the queue'd request if possible.
6302 // If execution blocks, the work queue will wait for a producer signal.
6303 // Only need to signal more when completing attached requests.
6305 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
6309 // Calling PM without PMinit() is not allowed, fail the request.
6311 PM_LOG("%s: PM not initialized\n", getName());
6312 fAdjustPowerScheduled
= false;
6313 more
= gIOPMFreeQueue
->queuePMRequest(request
);
6314 if (more
) gIOPMWorkQueue
->incrementProducerCount();
6318 //*********************************************************************************
6319 // [private] servicePMFreeQueue
6321 // Called from IOPMCompletionQueue::checkForWork().
6322 //*********************************************************************************
6324 bool IOService::servicePMFreeQueue(
6325 IOPMRequest
* request
,
6326 IOPMCompletionQueue
* queue
)
6328 bool more
= request
->getNextRequest();
6329 IOPMRequest
* root
= request
->getRootRequest();
6331 if (root
&& (root
!= request
))
6334 gIOPMWorkQueue
->incrementProducerCount();
6336 releasePMRequest( request
);
6340 //*********************************************************************************
6341 // [private] retirePMRequest
6343 // Called by IOPMWorkQueue to retire a completed request.
6344 //*********************************************************************************
6346 bool IOService::retirePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
6348 assert(request
&& queue
);
6350 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
6351 request
->getType(), request
, this, getName(),
6352 fMachineState
, gIOPMBusyCount
);
6354 // Catch requests created by idleTimerExpired().
6356 if ((request
->getType() == kIOPMRequestTypeActivityTickle
) &&
6357 (request
->fArg1
== (void *) (uintptr_t) false))
6359 // Idle timer power drop request completed.
6360 // Restart the idle timer if deviceDesire can go lower, otherwise set
6361 // a flag so we know to restart idle timer when deviceDesire goes up.
6363 if (fDeviceDesire
> 0)
6365 fActivityTickleCount
= 0;
6366 clock_get_uptime(&fIdleTimerStartTime
);
6367 start_PM_idle_timer();
6370 fIdleTimerStopped
= true;
6373 // If the request is linked, then Work queue has already incremented its
6376 return (gIOPMFreeQueue
->queuePMRequest( request
));
6379 //*********************************************************************************
6380 // [private] isPMBlocked
6382 // Check if machine state transition is blocked.
6383 //*********************************************************************************
6385 bool IOService::isPMBlocked ( IOPMRequest
* request
, int count
)
6390 if (kIOPM_Finished
== fMachineState
)
6393 if (kIOPM_DriverThreadCallDone
== fMachineState
)
6395 // 5 = kDriverCallInformPreChange
6396 // 6 = kDriverCallInformPostChange
6397 // 7 = kDriverCallSetPowerState
6398 if (fDriverCallBusy
)
6399 reason
= 5 + fDriverCallReason
;
6403 // Waiting on driver's setPowerState() timeout.
6409 // Child or interested driver acks pending.
6410 if (fHeadNotePendingAcks
)
6415 // Waiting on apps or priority power interest clients.
6421 // Waiting on settle timer expiration.
6428 fWaitReason
= reason
;
6434 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
6435 request
->getType(), request
, this, getName(),
6436 fMachineState
, reason
);
6445 //*********************************************************************************
6446 // [private] servicePMRequest
6448 // Service a request from our work queue.
6449 //*********************************************************************************
6451 bool IOService::servicePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
6456 assert(request
&& queue
);
6458 while (isPMBlocked(request
, loop
++) == false)
6460 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
6461 request
->getType(), request
, this, getName(), fMachineState
);
6463 gIOPMRequest
= request
;
6466 // Every PM machine states must be handled in one of the cases below.
6468 switch ( fMachineState
)
6470 case kIOPM_Finished
:
6471 executePMRequest( request
);
6474 case kIOPM_OurChangeTellClientsPowerDown
:
6475 // Root domain might self cancel due to assertions.
6478 bool cancel
= (bool) fDoNotPowerDown
;
6479 getPMRootDomain()->askChangeDownDone(
6480 &fHeadNoteChangeFlags
, &cancel
);
6481 fDoNotPowerDown
= cancel
;
6484 // askChangeDown() done, was it vetoed?
6485 if (!fDoNotPowerDown
)
6487 if (IS_ROOT_DOMAIN
) {
6488 PMEventDetails
*details
= PMEventDetails::eventDetails(
6489 kIOPMEventTypeAppNotificationsFinished
,
6494 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6497 // no, we can continue
6498 OurChangeTellClientsPowerDown();
6502 if (IS_ROOT_DOMAIN
) {
6503 PMEventDetails
*details
= PMEventDetails::eventDetails(
6504 kIOPMEventTypeSleepDone
,
6506 1, /* reason: 1 == Ask clients succeeded */
6507 kIOReturnAborted
); /* result */
6509 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6512 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
6513 PM_ERROR("%s: idle cancel\n", fName
);
6514 // yes, rescind the warning
6515 tellNoChangeDown(fHeadNotePowerState
);
6516 // mark the change note un-actioned
6517 fHeadNoteChangeFlags
|= kIOPMNotDone
;
6523 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
6524 // tellChangeDown(kNotifyApps) done, was it cancelled?
6525 if (fDoNotPowerDown
)
6527 if (IS_ROOT_DOMAIN
) {
6528 PMEventDetails
*details
= PMEventDetails::eventDetails(
6529 kIOPMEventTypeSleepDone
,
6531 2, /* reason: 2 == Client cancelled wake */
6532 kIOReturnAborted
); /* result */
6534 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6536 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
6537 PM_ERROR("%s: idle revert\n", fName
);
6538 // no, tell clients we're back in the old state
6539 tellChangeUp(fCurrentPowerState
);
6540 // mark the change note un-actioned
6541 fHeadNoteChangeFlags
|= kIOPMNotDone
;
6547 if (IS_ROOT_DOMAIN
) {
6548 PMEventDetails
*details
= PMEventDetails::eventDetails(
6549 kIOPMEventTypeAppNotificationsFinished
,
6551 2, /* reason: 2 == TellPriorityClientsDone */
6552 kIOReturnSuccess
); /* result */
6554 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6556 // yes, we can continue
6557 OurChangeTellPriorityClientsPowerDown();
6561 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
6562 OurChangeNotifyInterestedDriversWillChange();
6565 case kIOPM_OurChangeSetPowerState
:
6566 OurChangeSetPowerState();
6569 case kIOPM_OurChangeWaitForPowerSettle
:
6570 OurChangeWaitForPowerSettle();
6573 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
6574 OurChangeNotifyInterestedDriversDidChange();
6577 case kIOPM_OurChangeTellCapabilityDidChange
:
6578 OurChangeTellCapabilityDidChange();
6581 case kIOPM_OurChangeFinish
:
6585 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
6586 ParentChangeTellPriorityClientsPowerDown();
6589 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
6590 ParentChangeNotifyInterestedDriversWillChange();
6593 case kIOPM_ParentChangeSetPowerState
:
6594 ParentChangeSetPowerState();
6597 case kIOPM_ParentChangeWaitForPowerSettle
:
6598 ParentChangeWaitForPowerSettle();
6601 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
6602 ParentChangeNotifyInterestedDriversDidChange();
6605 case kIOPM_ParentChangeTellCapabilityDidChange
:
6606 ParentChangeTellCapabilityDidChange();
6609 case kIOPM_ParentChangeAcknowledgePowerChange
:
6610 ParentChangeAcknowledgePowerChange();
6613 case kIOPM_DriverThreadCallDone
:
6614 if (fDriverCallReason
== kDriverCallSetPowerState
)
6615 notifyControllingDriverDone();
6617 notifyInterestedDriversDone();
6620 case kIOPM_NotifyChildrenOrdered
:
6621 notifyChildrenOrdered();
6624 case kIOPM_NotifyChildrenDelayed
:
6625 notifyChildrenDelayed();
6628 case kIOPM_NotifyChildrenStart
:
6629 PM_LOG2("%s: kIOPM_NotifyChildrenStart done\n", getName());
6630 MS_POP(); // from notifyInterestedDriversDone()
6634 case kIOPM_SyncTellClientsPowerDown
:
6635 // Root domain might self cancel due to assertions.
6638 bool cancel
= (bool) fDoNotPowerDown
;
6639 getPMRootDomain()->askChangeDownDone(
6640 &fHeadNoteChangeFlags
, &cancel
);
6641 fDoNotPowerDown
= cancel
;
6643 if (!fDoNotPowerDown
)
6645 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
6646 fOutOfBandParameter
= kNotifyApps
;
6647 tellChangeDown(fHeadNotePowerState
);
6651 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
6652 PM_ERROR("%s: idle cancel\n", fName
);
6653 tellNoChangeDown(fHeadNotePowerState
);
6654 fHeadNoteChangeFlags
|= kIOPMNotDone
;
6659 case kIOPM_SyncTellPriorityClientsPowerDown
:
6660 if (!fDoNotPowerDown
)
6662 fMachineState
= kIOPM_SyncNotifyWillChange
;
6663 fOutOfBandParameter
= kNotifyPriority
;
6664 tellChangeDown(fHeadNotePowerState
);
6668 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
6669 PM_ERROR("%s: idle revert\n", fName
);
6670 tellChangeUp(fCurrentPowerState
);
6671 fHeadNoteChangeFlags
|= kIOPMNotDone
;
6676 case kIOPM_SyncNotifyWillChange
:
6677 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
)
6679 fMachineState
= kIOPM_SyncFinish
;
6682 fMachineState
= kIOPM_SyncNotifyDidChange
;
6683 fDriverCallReason
= kDriverCallInformPreChange
;
6687 case kIOPM_SyncNotifyDidChange
:
6688 fIsPreChange
= false;
6690 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
6691 fMachineState
= kIOPM_SyncFinish
;
6693 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
6695 fDriverCallReason
= kDriverCallInformPostChange
;
6699 case kIOPM_SyncTellCapabilityDidChange
:
6700 tellSystemCapabilityChange( kIOPM_SyncFinish
);
6703 case kIOPM_SyncFinish
:
6704 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
6705 ParentChangeAcknowledgePowerChange();
6710 case kIOPM_TellCapabilityChangeDone
:
6713 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
)
6715 MS_POP(); // tellSystemCapabilityChange()
6718 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
6722 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
)
6724 MS_POP(); // tellSystemCapabilityChange()
6727 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
6729 tellClientsWithResponse( fOutOfBandMessage
);
6733 panic("servicePMWorkQueue: unknown machine state %x",
6739 if (fMachineState
== kIOPM_Finished
)
6749 //*********************************************************************************
6750 // [private] executePMRequest
6751 //*********************************************************************************
6753 void IOService::executePMRequest( IOPMRequest
* request
)
6755 assert( kIOPM_Finished
== fMachineState
);
6757 switch (request
->getType())
6759 case kIOPMRequestTypePMStop
:
6760 handlePMstop( request
);
6763 case kIOPMRequestTypeAddPowerChild1
:
6764 addPowerChild1( request
);
6767 case kIOPMRequestTypeAddPowerChild2
:
6768 addPowerChild2( request
);
6771 case kIOPMRequestTypeAddPowerChild3
:
6772 addPowerChild3( request
);
6775 case kIOPMRequestTypeRegisterPowerDriver
:
6776 handleRegisterPowerDriver( request
);
6779 case kIOPMRequestTypeAdjustPowerState
:
6780 fAdjustPowerScheduled
= false;
6781 rebuildChildClampBits();
6785 case kIOPMRequestTypePowerDomainWillChange
:
6786 handlePowerDomainWillChangeTo( request
);
6789 case kIOPMRequestTypePowerDomainDidChange
:
6791 handlePowerDomainDidChangeTo( request
);
6794 case kIOPMRequestTypeRequestPowerState
:
6795 case kIOPMRequestTypeRequestPowerStateOverride
:
6796 handleRequestPowerState( request
);
6799 case kIOPMRequestTypePowerOverrideOnPriv
:
6800 case kIOPMRequestTypePowerOverrideOffPriv
:
6801 handlePowerOverrideChanged( request
);
6804 case kIOPMRequestTypeActivityTickle
:
6805 handleActivityTickle( request
);
6808 case kIOPMRequestTypeSynchronizePowerTree
:
6809 handleSynchronizePowerTree( request
);
6812 case kIOPMRequestTypeSetIdleTimerPeriod
:
6814 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
6816 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
6818 fActivityTickleCount
= 0;
6819 clock_get_uptime(&fIdleTimerStartTime
);
6820 start_PM_idle_timer();
6825 case kIOPMRequestTypeIgnoreIdleTimer
:
6826 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
6830 panic("executePMRequest: unknown request type %x", request
->getType());
6834 //*********************************************************************************
6835 // [private] servicePMReplyQueue
6836 //*********************************************************************************
6838 bool IOService::servicePMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
6842 assert( request
&& queue
);
6843 assert( request
->isReplyType() );
6845 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
6846 request
->getType(), request
, this, getName(), fMachineState
);
6848 switch ( request
->getType() )
6850 case kIOPMRequestTypeAllowPowerChange
:
6851 case kIOPMRequestTypeCancelPowerChange
:
6852 // Check if we are expecting this response.
6853 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
6854 (int)(uintptr_t) request
->fArg1
))
6856 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
6858 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
6859 // flag is set. Only root domain will set this flag.
6861 if ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0)
6863 fDoNotPowerDown
= true;
6865 OSString
* name
= (OSString
*) request
->fArg2
;
6866 getPMRootDomain()->pmStatsRecordApplicationResponse(
6867 gIOPMStatsApplicationResponseCancel
,
6868 name
? name
->getCStringNoCopy() : "", 0,
6869 0, (int)(uintptr_t) request
->fArg1
);
6876 cleanClientResponses(false);
6880 // OSString containing app name in Arg2 must be released.
6881 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
6883 OSObject
* obj
= (OSObject
*) request
->fArg2
;
6884 if (obj
) obj
->release();
6888 case kIOPMRequestTypeAckPowerChange
:
6889 more
= handleAcknowledgePowerChange( request
);
6892 case kIOPMRequestTypeAckSetPowerState
:
6893 if (fDriverTimer
== -1)
6895 // driver acked while setPowerState() call is in-flight.
6896 // take this ack, return value from setPowerState() is irrelevant.
6897 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
6898 (uintptr_t) this, fDriverTimer
);
6901 else if (fDriverTimer
> 0)
6903 // expected ack, stop the timer
6906 #if LOG_SETPOWER_TIMES
6907 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
6908 if (nsec
> LOG_SETPOWER_TIMES
)
6909 PM_LOG("%s::setPowerState(%p, %lu -> %lu) async took %d ms\n",
6910 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
6912 PMEventDetails
*details
= PMEventDetails::eventDetails(
6913 kIOPMEventTypeSetPowerStateDelayed
, // type
6915 (uintptr_t)this, // owner unique
6916 NULL
, // interest name
6917 (uint8_t)getPowerState(), // old
6918 (uint8_t)fHeadNotePowerState
, // new
6920 NS_TO_US(nsec
)); // usec completion time
6922 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6924 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
6931 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
6935 case kIOPMRequestTypeInterestChanged
:
6936 handleInterestChanged( request
);
6940 case kIOPMRequestTypeIdleCancel
:
6941 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
6942 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
6943 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
6944 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
6946 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
6947 PM_LOG2("%s: cancel from machine state %d\n",
6948 getName(), fMachineState
);
6949 fDoNotPowerDown
= true;
6950 // Stop waiting for app replys.
6951 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
6952 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
6953 cleanClientResponses(false);
6958 case kIOPMRequestTypeChildNotifyDelayCancel
:
6959 if (fMachineState
== kIOPM_NotifyChildrenDelayed
)
6961 PM_LOG2("%s: delay notify cancelled\n", getName());
6962 notifyChildrenDelayed();
6967 panic("servicePMReplyQueue: unknown reply type %x",
6968 request
->getType());
6971 more
|= gIOPMFreeQueue
->queuePMRequest(request
);
6973 gIOPMWorkQueue
->incrementProducerCount();
6978 //*********************************************************************************
6979 // [private] assertPMDriverCall / deassertPMDriverCall
6980 //*********************************************************************************
6982 bool IOService::assertPMDriverCall(
6983 IOPMDriverCallEntry
* entry
,
6984 IOOptionBits options
,
6985 IOPMinformee
* inform
)
6987 IOService
* target
= 0;
6995 if (fLockedFlags
.PMStop
)
7000 if (((options
& kIOPMADC_NoInactiveCheck
) == 0) && isInactive())
7007 if (!inform
->active
)
7011 target
= inform
->whatObject
;
7012 if (target
->isInactive())
7018 entry
->thread
= current_thread();
7019 entry
->target
= target
;
7020 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7029 void IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
7031 bool wakeup
= false;
7035 assert( !queue_empty(&fPMDriverCallQueue
) );
7036 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7037 if (fLockedFlags
.PMDriverCallWait
)
7045 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
7048 void IOService::waitForPMDriverCall( IOService
* target
)
7050 const IOPMDriverCallEntry
* entry
;
7051 thread_t thread
= current_thread();
7052 AbsoluteTime deadline
;
7059 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
7061 // Target of interested driver call
7062 if (target
&& (target
!= entry
->target
))
7065 if (entry
->thread
== thread
)
7069 PM_LOG("%s: %s(%s) on PM thread\n",
7070 fName
, __FUNCTION__
, target
? target
->getName() : "");
7071 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
7072 fName
, __FUNCTION__
, target
? target
->getName() : "");
7084 fLockedFlags
.PMDriverCallWait
= true;
7085 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
7086 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
7087 fLockedFlags
.PMDriverCallWait
= false;
7088 if (THREAD_TIMED_OUT
== waitResult
)
7090 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
7097 //*********************************************************************************
7098 // [private] Debug helpers
7099 //*********************************************************************************
7101 const char * IOService::getIOMessageString( uint32_t msg
)
7103 #define MSG_ENTRY(x) {x, #x}
7105 static const IONamedValue msgNames
[] = {
7106 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
7107 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
7108 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
7109 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
7110 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
7111 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
7112 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
7113 MSG_ENTRY( kIOMessageCanSystemSleep
),
7114 MSG_ENTRY( kIOMessageSystemWillSleep
),
7115 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
7116 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
7117 MSG_ENTRY( kIOMessageSystemWillRestart
),
7118 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
7119 MSG_ENTRY( kIOMessageSystemCapabilityChange
)
7122 return IOFindNameForValue(msg
, msgNames
);
7126 // MARK: IOPMRequest
7128 //*********************************************************************************
7129 // IOPMRequest Class
7131 // Requests from PM clients, and also used for inter-object messaging within PM.
7132 //*********************************************************************************
7134 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
7136 IOPMRequest
* IOPMRequest::create( void )
7138 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
7139 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
7147 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
7149 if (!IOCommand::init())
7154 fCompletionStatus
= kIOReturnSuccess
;
7162 void IOPMRequest::reset( void )
7164 assert( fWorkWaitCount
== 0 );
7165 assert( fFreeWaitCount
== 0 );
7167 detachNextRequest();
7168 detachRootRequest();
7170 fType
= kIOPMRequestTypeInvalid
;
7172 if (fCompletionAction
)
7174 fCompletionAction(fCompletionTarget
, fCompletionParam
, fCompletionStatus
);
7184 bool IOPMRequest::attachNextRequest( IOPMRequest
* next
)
7190 // Postpone the execution of the next request after
7192 fRequestNext
= next
;
7193 fRequestNext
->fWorkWaitCount
++;
7194 #if LOG_REQUEST_ATTACH
7195 kprintf("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7196 this, (uint32_t) fType
, fRequestNext
,
7197 (uint32_t) fRequestNext
->fType
,
7198 (uint32_t) fRequestNext
->fWorkWaitCount
,
7199 fTarget
->getName());
7206 bool IOPMRequest::detachNextRequest( void )
7212 assert(fRequestNext
->fWorkWaitCount
);
7213 if (fRequestNext
->fWorkWaitCount
)
7214 fRequestNext
->fWorkWaitCount
--;
7215 #if LOG_REQUEST_ATTACH
7216 kprintf("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7217 this, (uint32_t) fType
, fRequestNext
,
7218 (uint32_t) fRequestNext
->fType
,
7219 (uint32_t) fRequestNext
->fWorkWaitCount
,
7220 fTarget
->getName());
7228 bool IOPMRequest::attachRootRequest( IOPMRequest
* root
)
7234 // Delay the completion of the root request after
7236 fRequestRoot
= root
;
7237 fRequestRoot
->fFreeWaitCount
++;
7238 #if LOG_REQUEST_ATTACH
7239 kprintf("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7240 this, (uint32_t) fType
, fRequestRoot
,
7241 (uint32_t) fRequestRoot
->fType
,
7242 (uint32_t) fRequestRoot
->fFreeWaitCount
,
7243 fTarget
->getName());
7250 bool IOPMRequest::detachRootRequest( void )
7256 assert(fRequestRoot
->fFreeWaitCount
);
7257 if (fRequestRoot
->fFreeWaitCount
)
7258 fRequestRoot
->fFreeWaitCount
--;
7259 #if LOG_REQUEST_ATTACH
7260 kprintf("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7261 this, (uint32_t) fType
, fRequestRoot
,
7262 (uint32_t) fRequestRoot
->fType
,
7263 (uint32_t) fRequestRoot
->fFreeWaitCount
,
7264 fTarget
->getName());
7273 // MARK: IOPMRequestQueue
7275 //*********************************************************************************
7276 // IOPMRequestQueue Class
7278 // Global queues. Queues are created once and never released.
7279 //*********************************************************************************
7281 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
7283 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
7285 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
7286 if (me
&& !me
->init(inOwner
, inAction
))
7294 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
7296 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
7299 queue_init(&fQueue
);
7300 fLock
= IOLockAlloc();
7301 return (fLock
!= 0);
7304 void IOPMRequestQueue::free( void )
7311 return IOEventSource::free();
7314 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
7318 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
7319 IOLockUnlock(fLock
);
7320 if (workLoop
) signalWorkAvailable();
7324 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
7328 assert(requests
&& count
);
7334 queue_enter(&fQueue
, next
, IOPMRequest
*, fCommandChain
);
7336 IOLockUnlock(fLock
);
7337 if (workLoop
) signalWorkAvailable();
7340 bool IOPMRequestQueue::checkForWork( void )
7342 Action dqAction
= (Action
) action
;
7343 IOPMRequest
* request
;
7347 IOLockLock( fLock
);
7349 while (!queue_empty(&fQueue
))
7351 queue_remove_first( &fQueue
, request
, IOPMRequest
*, fCommandChain
);
7352 IOLockUnlock( fLock
);
7353 target
= request
->getTarget();
7355 more
|= (*dqAction
)( target
, request
, this );
7356 IOLockLock( fLock
);
7359 IOLockUnlock( fLock
);
7364 // MARK: IOPMWorkQueue
7366 //*********************************************************************************
7367 // IOPMWorkQueue Class
7369 // Queue of IOServicePM objects with busy IOPMRequest(s).
7370 //*********************************************************************************
7372 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
7375 IOPMWorkQueue::create( IOService
* inOwner
, Action work
, Action retire
)
7377 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
7378 if (me
&& !me
->init(inOwner
, work
, retire
))
7386 bool IOPMWorkQueue::init( IOService
* inOwner
, Action work
, Action retire
)
7388 if (!work
|| !retire
||
7389 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
7392 queue_init(&fWorkQueue
);
7395 fRetireAction
= retire
;
7396 fConsumerCount
= fProducerCount
= 0;
7401 bool IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
7408 assert( onThread() );
7409 assert( queue_next(&request
->fCommandChain
) ==
7410 queue_prev(&request
->fCommandChain
) );
7414 // Add new request to the tail of the per-service request queue.
7415 // Then immediately check the request queue to minimize latency
7416 // if the queue was empty.
7418 empty
= queue_empty(&pwrMgt
->RequestHead
);
7419 queue_enter(&pwrMgt
->RequestHead
, request
, IOPMRequest
*, fCommandChain
);
7422 more
= checkRequestQueue(&pwrMgt
->RequestHead
, &empty
);
7425 // New Request is blocked, add IOServicePM to work queue.
7426 assert( queue_next(&pwrMgt
->WorkChain
) ==
7427 queue_prev(&pwrMgt
->WorkChain
) );
7429 queue_enter(&fWorkQueue
, pwrMgt
, IOServicePM
*, WorkChain
);
7431 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
7432 fQueueLength
, pwrMgt
->Name
, pwrMgt
);
7439 bool IOPMWorkQueue::checkRequestQueue( queue_head_t
* queue
, bool * empty
)
7441 IOPMRequest
* request
;
7446 assert(!queue_empty(queue
));
7448 request
= (IOPMRequest
*) queue_first(queue
);
7449 if (request
->isWorkBlocked())
7450 break; // cannot start, blocked on attached request
7452 target
= request
->getTarget();
7453 done
= (*fWorkAction
)( target
, request
, this );
7455 break; // work started, blocked on PM state machine
7457 assert(gIOPMBusyCount
> 0);
7461 queue_remove_first(queue
, request
, IOPMRequest
*, fCommandChain
);
7462 more
|= (*fRetireAction
)( target
, request
, this );
7463 done
= queue_empty(queue
);
7470 // Retired request blocks another request, since the
7471 // blocked request may reside in the work queue, we
7472 // must bump the producer count to avoid work stall.
7479 bool IOPMWorkQueue::checkForWork( void )
7481 IOServicePM
* entry
;
7486 #if WORK_QUEUE_STATS
7487 fStatCheckForWork
++;
7490 // Each producer signal triggers a full iteration over
7491 // all IOServicePM entries in the work queue.
7493 while (fConsumerCount
!= fProducerCount
)
7495 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
7496 fProducerCount
, fConsumerCount
);
7498 fConsumerCount
= fProducerCount
;
7500 #if WORK_QUEUE_STATS
7501 if (queue_empty(&fWorkQueue
))
7507 uint32_t cachedWorkCount
= gIOPMWorkCount
;
7510 entry
= (IOServicePM
*) queue_first(&fWorkQueue
);
7511 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
))
7513 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
7515 // Get next entry, points to head if current entry is last.
7516 next
= (IOServicePM
*) queue_next(&entry
->WorkChain
);
7518 // if request queue is empty, remove IOServicePM from queue.
7521 assert(fQueueLength
);
7522 if (fQueueLength
) fQueueLength
--;
7523 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
7524 fQueueLength
, entry
->Name
, entry
);
7525 queue_remove(&fWorkQueue
, entry
, IOServicePM
*, WorkChain
);
7530 #if WORK_QUEUE_STATS
7531 if (cachedWorkCount
== gIOPMWorkCount
)
7539 void IOPMWorkQueue::signalWorkAvailable( void )
7542 IOEventSource::signalWorkAvailable();
7545 void IOPMWorkQueue::incrementProducerCount( void )
7551 // MARK: IOPMCompletionQueue
7553 //*********************************************************************************
7554 // IOPMCompletionQueue Class
7555 //*********************************************************************************
7557 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
7559 IOPMCompletionQueue
*
7560 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
7562 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
7563 if (me
&& !me
->init(inOwner
, inAction
))
7571 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
7573 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
7576 queue_init(&fQueue
);
7580 bool IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
7585 // unblock dependent request
7586 more
= request
->detachNextRequest();
7587 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
7591 bool IOPMCompletionQueue::checkForWork( void )
7593 Action dqAction
= (Action
) action
;
7594 IOPMRequest
* request
;
7599 request
= (IOPMRequest
*) queue_first(&fQueue
);
7600 while (!queue_end(&fQueue
, (queue_entry_t
) request
))
7602 next
= (IOPMRequest
*) queue_next(&request
->fCommandChain
);
7603 if (!request
->isFreeBlocked())
7605 queue_remove(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
7606 target
= request
->getTarget();
7608 more
|= (*dqAction
)( target
, request
, this );
7617 // MARK: IOServicePM
7619 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
7621 //*********************************************************************************
7624 // Serialize IOServicePM for debugging.
7625 //*********************************************************************************
7628 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
7630 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
7633 dict
->setObject(key
, num
);
7638 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
)
7640 OSDictionary
* dict
;
7644 if (IdleTimerPeriod
)
7647 #if WORK_QUEUE_STATS
7648 if (gIOPMRootNode
== ControllingDriver
)
7653 dict
= OSDictionary::withDictionary(
7654 PowerClients
, PowerClients
->getCount() + dictSize
);
7656 dict
= OSDictionary::withCapacity(dictSize
);
7660 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
7661 if (NumberOfPowerStates
)
7662 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
-1);
7663 if (DesiredPowerState
!= CurrentPowerState
)
7664 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
7665 if (kIOPM_Finished
!= MachineState
)
7666 setPMProperty(dict
, "MachineState", MachineState
);
7667 if (DeviceOverrideEnabled
)
7668 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
7670 if (IdleTimerPeriod
)
7676 clock_get_uptime(&now
);
7678 // The idle timer period in milliseconds.
7679 setPMProperty(dict
, "IdleTimerPeriod", IdleTimerPeriod
* 1000ULL);
7681 // The number of activity tickles recorded since device idle
7682 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
7684 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
7686 // The number of milliseconds since the last activity tickle.
7688 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
7689 absolutetime_to_nanoseconds(delta
, &nsecs
);
7690 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
7693 if (AbsoluteTime_to_scalar(&IdleTimerStartTime
))
7695 // The number of milliseconds since the last device idle.
7697 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
7698 absolutetime_to_nanoseconds(delta
, &nsecs
);
7699 setPMProperty(dict
, "TimeSinceDeviceIdle", NS_TO_MS(nsecs
));
7703 #if WORK_QUEUE_STATS
7704 if (gIOPMRootNode
== Owner
)
7706 setPMProperty(dict
, "WQ-CheckForWork",
7707 gIOPMWorkQueue
->fStatCheckForWork
);
7708 setPMProperty(dict
, "WQ-ScanEntries",
7709 gIOPMWorkQueue
->fStatScanEntries
);
7710 setPMProperty(dict
, "WQ-QueueEmpty",
7711 gIOPMWorkQueue
->fStatQueueEmpty
);
7712 setPMProperty(dict
, "WQ-NoWorkDone",
7713 gIOPMWorkQueue
->fStatNoWorkDone
);
7717 ok
= dict
->serialize(s
);
7721 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
7724 bool IOServicePM::serialize( OSSerialize
* s
) const
7726 IOReturn ret
= kIOReturnNotReady
;
7730 ret
= gIOPMWorkLoop
->runAction(
7731 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
7732 (OSObject
*) this, (void *) s
);
7735 return (kIOReturnSuccess
== ret
);
7738 PMEventDetails
* PMEventDetails::eventDetails(uint32_t type
,
7739 const char *ownerName
,
7740 uintptr_t ownerUnique
,
7741 const char *interestName
,
7745 uint32_t elapsedTimeUS
) {
7747 PMEventDetails
*myself
;
7748 myself
= new PMEventDetails
;
7751 myself
->eventType
= type
;
7752 myself
->ownerName
= ownerName
;
7753 myself
->ownerUnique
= ownerUnique
;
7754 myself
->interestName
= interestName
;
7755 myself
->oldState
= oldState
;
7756 myself
->newState
= newState
;
7757 myself
->result
= result
;
7758 myself
->elapsedTimeUS
= elapsedTimeUS
;
7760 myself
->eventClassifier
= kIOPMEventClassDriverEvent
;
7767 PMEventDetails
* PMEventDetails::eventDetails(uint32_t type
,
7772 PMEventDetails
*myself
;
7773 myself
= new PMEventDetails
;
7776 myself
->eventType
= type
;
7777 myself
->uuid
= uuid
;
7778 myself
->reason
= reason
;
7779 myself
->result
= result
;
7781 myself
->eventClassifier
= kIOPMEventClassSystemEvent
;