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 <sys/proc_internal.h>
51 #include <libkern/OSDebug.h>
53 // Required for notification instrumentation
54 #include "IOServicePrivate.h"
55 #include "IOServicePMPrivate.h"
56 #include "IOKitKernelInternal.h"
58 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
59 static void idle_timer_expired(thread_call_param_t
, thread_call_param_t
);
60 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
61 static void tellAppClientApplier(OSObject
* object
, void * arg
);
63 static uint64_t computeTimeDeltaNS( const AbsoluteTime
* start
)
68 clock_get_uptime(&now
);
69 SUB_ABSOLUTETIME(&now
, start
);
70 absolutetime_to_nanoseconds(now
, &nsec
);
75 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
78 // Container class for recording system power events
79 OSDefineMetaClassAndStructors( PMEventDetails
, OSObject
);
81 //******************************************************************************
83 //******************************************************************************
85 static bool gIOPMInitialized
= false;
86 static uint32_t gIOPMBusyCount
= 0;
87 static uint32_t gIOPMWorkCount
= 0;
88 static IOWorkLoop
* gIOPMWorkLoop
= 0;
89 static IOPMRequestQueue
* gIOPMRequestQueue
= 0;
90 static IOPMRequestQueue
* gIOPMReplyQueue
= 0;
91 static IOPMWorkQueue
* gIOPMWorkQueue
= 0;
92 static IOPMCompletionQueue
* gIOPMFreeQueue
= 0;
93 static IOPMRequest
* gIOPMRequest
= 0;
94 static IOService
* gIOPMRootNode
= 0;
95 static IOPlatformExpert
* gPlatform
= 0;
97 static const OSSymbol
* gIOPMPowerClientDevice
= 0;
98 static const OSSymbol
* gIOPMPowerClientDriver
= 0;
99 static const OSSymbol
* gIOPMPowerClientChildProxy
= 0;
100 static const OSSymbol
* gIOPMPowerClientChildren
= 0;
102 static const OSSymbol
* gIOPMPowerClientAdvisoryTickle
= 0;
103 static bool gIOPMAdvisoryTickleEnabled
= true;
105 static uint32_t getPMRequestType( void )
107 uint32_t type
= kIOPMRequestTypeInvalid
;
109 type
= gIOPMRequest
->getType();
113 //******************************************************************************
115 //******************************************************************************
117 #define PM_ERROR(x...) do { kprintf(x); IOLog(x); } while (false)
118 #define PM_LOG(x...) do { kprintf(x); } while (false)
120 #define PM_LOG1(x...) do { \
121 if (kIOLogDebugPower & gIOKitDebug) \
122 kprintf(x); } while (false)
124 #define PM_LOG2(x...) do { \
125 if (kIOLogDebugPower & gIOKitDebug) \
126 kprintf(x); } while (false)
129 #define PM_LOG3(x...) do { kprintf(x); } while (false)
131 #define PM_LOG3(x...)
134 #define RD_LOG(x...) do { \
135 if ((kIOLogPMRootDomain & gIOKitDebug) && \
136 (getPMRootDomain() == this)) \
137 kprintf("PMRD: " x); } while (false)
139 #define PM_ASSERT_IN_GATE(x) \
141 assert(gIOPMWorkLoop->inGate()); \
144 #define PM_LOCK() IOLockLock(fPMLock)
145 #define PM_UNLOCK() IOLockUnlock(fPMLock)
146 #define PM_LOCK_SLEEP(event, dl) IOLockSleepDeadline(fPMLock, event, dl, THREAD_UNINT)
147 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
149 #define ns_per_us 1000
150 #define k30Seconds (30*1000000)
151 #define kMinAckTimeoutTicks (10*1000000)
152 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
153 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
154 #define kPwrMgtKey "IOPowerManagement"
156 #define OUR_PMLog(t, a, b) \
157 do { gPlatform->PMLog( fName, t, a, b); } while(0)
159 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
160 #define NS_TO_US(nsec) ((int)((nsec) / 1000ULL))
163 #define SUPPORT_IDLE_CANCEL 1
166 #define kIOPMPowerStateMax 0xFFFFFFFF
167 #define kInvalidTicklePowerState (-1)
169 #define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL)
171 #define IS_PM_ROOT (this == gIOPMRootNode)
172 #define IS_ROOT_DOMAIN (getPMRootDomain() == this)
173 #define IS_POWER_DROP (fHeadNotePowerState < fCurrentPowerState)
174 #define IS_POWER_RISE (fHeadNotePowerState > fCurrentPowerState)
176 // log setPowerStates longer than (ns):
177 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
178 // log app responses longer than (ns):
179 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
180 // use message tracer to log messages longer than (ns):
181 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
184 kReserveDomainPower
= 1
188 do { assert(kIOPM_BadMachineState == fSavedMachineState); \
189 assert(kIOPM_BadMachineState != n); \
190 fSavedMachineState = n; } while (false)
193 do { assert(kIOPM_BadMachineState != fSavedMachineState); \
194 fMachineState = fSavedMachineState; \
195 fSavedMachineState = kIOPM_BadMachineState; } while (false)
197 #define PM_ACTION_0(a) \
198 do { if (fPMActions.a) { \
199 (fPMActions.a)(fPMActions.target, this, &fPMActions); } \
202 #define PM_ACTION_2(a, x, y) \
203 do { if (fPMActions.a) { \
204 (fPMActions.a)(fPMActions.target, this, &fPMActions, x, y); } \
207 static OSNumber
* copyClientIDForNotification(
209 IOPMInterestContext
*context
);
211 static void logClientIDForNotification(
213 IOPMInterestContext
*context
,
214 const char *logString
);
216 //*********************************************************************************
219 // Check kgmacros after modifying machine states.
220 //*********************************************************************************
225 kIOPM_OurChangeTellClientsPowerDown
= 1,
226 kIOPM_OurChangeTellPriorityClientsPowerDown
= 2,
227 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 3,
228 kIOPM_OurChangeSetPowerState
= 4,
229 kIOPM_OurChangeWaitForPowerSettle
= 5,
230 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 6,
231 kIOPM_OurChangeTellCapabilityDidChange
= 7,
232 kIOPM_OurChangeFinish
= 8,
234 kIOPM_ParentChangeTellPriorityClientsPowerDown
= 10,
235 kIOPM_ParentChangeNotifyInterestedDriversWillChange
= 11,
236 kIOPM_ParentChangeSetPowerState
= 12,
237 kIOPM_ParentChangeWaitForPowerSettle
= 13,
238 kIOPM_ParentChangeNotifyInterestedDriversDidChange
= 14,
239 kIOPM_ParentChangeTellCapabilityDidChange
= 15,
240 kIOPM_ParentChangeAcknowledgePowerChange
= 16,
242 kIOPM_NotifyChildrenStart
= 17,
243 kIOPM_NotifyChildrenOrdered
= 18,
244 kIOPM_NotifyChildrenDelayed
= 19,
245 kIOPM_SyncTellClientsPowerDown
= 20,
246 kIOPM_SyncTellPriorityClientsPowerDown
= 21,
247 kIOPM_SyncNotifyWillChange
= 22,
248 kIOPM_SyncNotifyDidChange
= 23,
249 kIOPM_SyncTellCapabilityDidChange
= 24,
250 kIOPM_SyncFinish
= 25,
251 kIOPM_TellCapabilityChangeDone
= 26,
252 kIOPM_DriverThreadCallDone
= 27,
254 kIOPM_BadMachineState
= 0xFFFFFFFF
259 Power Management defines a few roles that drivers can play in their own,
260 and other drivers', power management. We briefly define those here.
262 Many drivers implement their policy maker and power controller within the same
263 IOService object, but that is not required.
266 * Virtual IOService PM methods a "policy maker" may implement
267 * maxCapabilityForDomainState()
268 * initialPowerStateForDomainState()
269 * powerStateForDomainState()
271 * Virtual IOService PM methods a "policy maker" may CALL
274 == Power Controller ==
275 * Virtual IOService PM methods a "power controller" may implement
278 * Virtual IOService PM methods a "power controller" may CALL
280 * registerPowerDriver()
282 =======================
283 There are two different kinds of power state changes.
284 * One is initiated by a subclassed device object which has either decided
285 to change power state, or its controlling driver has suggested it, or
286 some other driver wants to use the idle device and has asked it to become
288 * The second kind of power state change is initiated by the power domain
290 The two are handled through different code paths.
292 We maintain a queue of "change notifications," or change notes.
293 * Usually the queue is empty.
294 * When it isn't, usually there is one change note in it
295 * It's possible to have more than one power state change pending at one
296 time, so a queue is implemented.
298 * The subclass device decides it's idle and initiates a change to a lower
299 power state. This causes interested parties to be notified, but they
300 don't all acknowledge right away. This causes the change note to sit
301 in the queue until all the acks are received. During this time, the
302 device decides it isn't idle anymore and wants to raise power back up
303 again. This change can't be started, however, because the previous one
304 isn't complete yet, so the second one waits in the queue. During this
305 time, the parent decides to lower or raise the power state of the entire
306 power domain and notifies the device, and that notification goes into
307 the queue, too, and can't be actioned until the others are.
310 This is how a power change initiated by the subclass device is handled:
311 -> First, all interested parties are notified of the change via their
312 powerStateWillChangeTo method. If they all don't acknowledge via return
313 code, then we have to wait. If they do, or when they finally all
314 acknowledge via our acknowledgePowerChange method, then we can continue.
315 -> We call the controlling driver, instructing it to change to the new state
316 -> Then we wait for power to settle. If there is no settling-time, or after
318 -> we notify interested parties again, this time via their
319 powerStateDidChangeTo methods.
320 -> When they have all acked, we're done.
321 If we lowered power and don't need the power domain to be in its current power
322 state, we suggest to the parent that it lower the power domain state.
324 == PowerDomainDownInitiated ==
325 How a change to a lower power domain state initiated by the parent is handled:
326 -> First, we figure out what power state we will be in when the new domain
328 -> Then all interested parties are notified that we are moving to that new
330 -> When they have acknowledged, we call the controlling driver to assume
331 that state and we wait for power to settle.
332 -> Then we acknowledge our preparedness to our parent. When all its
333 interested parties have acknowledged,
334 -> it lowers power and then notifies its interested parties again.
335 -> When we get this call, we notify our interested parties that the power
336 state has changed, and when they have all acknowledged, we're done.
338 == PowerDomainUpInitiated ==
339 How a change to a higher power domain state initiated by the parent is handled:
340 -> We figure out what power state we will be in when the new domain state is
342 -> If it is different from our current state we acknowledge the parent.
343 -> When all the parent's interested parties have acknowledged, it raises
344 power in the domain and waits for power to settle.
345 -> Then it notifies everyone that the new state has been reached.
346 -> When we get this call, we call the controlling driver, instructing it to
347 assume the new state, and wait for power to settle.
348 -> Then we notify our interested parties. When they all acknowledge we are
351 In either of the two power domain state cases above, it is possible that we
352 will not be changing state even though the domain is.
354 * A change to a lower domain state may not affect us because we are already
355 in a low enough state,
356 * We will not take advantage of a change to a higher domain state, because
357 we have no need of the higher power. In such cases, there is nothing to
358 do but acknowledge the parent. So when the parent calls our
359 powerDomainWillChange method, and we decide that we will not be changing
360 state, we merely acknowledge the parent, via return code, and wait.
361 When the parent subsequently calls powerStateDidChange, we acknowledge again
362 via return code, and the change is complete.
364 == 4 Paths Through State Machine ==
365 Power state changes are processed in a state machine, and since there are four
366 varieties of power state changes, there are four major paths through the state
369 == 5. No Need To change ==
370 The fourth is nearly trivial. In this path, the parent is changing the domain
371 state, but we are not changing the device state. The change starts when the
372 parent calls powerDomainWillChange. All we do is acknowledge the parent. When
373 the parent calls powerStateDidChange, we acknowledge the parent again, and
376 == 1. OurChange Down == XXX gvdl
377 The first is fairly simple. It starts:
378 * when a power domain child calls requestPowerDomainState and we decide to
379 change power states to accomodate the child,
380 * or if our power-controlling driver calls changePowerStateTo,
381 * or if some other driver which is using our device calls makeUsable,
382 * or if a subclassed object calls changePowerStateToPriv.
383 These are all power changes initiated by us, not forced upon us by the parent.
385 -> We start by notifying interested parties.
386 -> If they all acknowledge via return code, we can go on to state
388 -> Otherwise, we start the ack timer and wait for the stragglers to
389 acknowlege by calling acknowledgePowerChange.
390 -> We move on to state "msSetPowerState" when all the
391 stragglers have acknowledged, or when the ack timer expires on
392 all those which didn't acknowledge.
393 In "msSetPowerState" we call the power-controlling driver to change the
394 power state of the hardware.
395 -> If it returns saying it has done so, we go on to state
396 "msWaitForPowerSettle".
397 -> Otherwise, we have to wait for it, so we set the ack timer and wait.
398 -> When it calls acknowledgeSetPowerState, or when the ack timer
400 In "msWaitForPowerSettle", we look in the power state array to see if
401 there is any settle time required when changing from our current state to the
403 -> If not, we go right away to "msNotifyInterestedDriversDidChange".
404 -> Otherwise, we set the settle timer and wait. When it expires, we move on.
405 In "msNotifyInterestedDriversDidChange" state, we notify all our
406 interested parties via their powerStateDidChange methods that we have finished
407 changing power state.
408 -> If they all acknowledge via return code, we move on to "msFinish".
409 -> Otherwise we set the ack timer and wait. When they have all
410 acknowledged, or when the ack timer has expired for those that didn't,
411 we move on to "msFinish".
412 In "msFinish" we remove the used change note from the head of the queue
413 and start the next one if one exists.
415 == 2. Parent Change Down ==
416 Start at Stage 2 of OurChange Down XXX gvdl
419 Start at Stage 4 of OurChange Down XXX gvdl
421 Note all parent requested changes need to acknowledge the power has changed to the parent when done.
424 //*********************************************************************************
427 // Initialize power management.
428 //*********************************************************************************
430 void IOService::PMinit ( void )
434 if ( !gIOPMInitialized
)
436 gPlatform
= getPlatform();
437 gIOPMWorkLoop
= IOWorkLoop::workLoop();
440 gIOPMRequestQueue
= IOPMRequestQueue::create(
441 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
442 this, &IOService::servicePMRequestQueue
));
444 gIOPMReplyQueue
= IOPMRequestQueue::create(
445 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
446 this, &IOService::servicePMReplyQueue
));
448 gIOPMWorkQueue
= IOPMWorkQueue::create(
450 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
451 &IOService::servicePMRequest
),
452 OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
453 &IOService::retirePMRequest
));
455 gIOPMFreeQueue
= IOPMCompletionQueue::create(
456 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
457 this, &IOService::servicePMFreeQueue
));
459 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
462 gIOPMRequestQueue
->release();
463 gIOPMRequestQueue
= 0;
466 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
469 gIOPMReplyQueue
->release();
473 if (gIOPMWorkLoop
->addEventSource(gIOPMWorkQueue
) !=
476 gIOPMWorkQueue
->release();
480 if (gIOPMWorkLoop
->addEventSource(gIOPMFreeQueue
) !=
483 gIOPMFreeQueue
->release();
487 gIOPMPowerClientDevice
=
488 OSSymbol::withCStringNoCopy( "DevicePowerState" );
490 gIOPMPowerClientDriver
=
491 OSSymbol::withCStringNoCopy( "DriverPowerState" );
493 gIOPMPowerClientChildProxy
=
494 OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
496 gIOPMPowerClientChildren
=
497 OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
499 gIOPMPowerClientAdvisoryTickle
=
500 OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" );
503 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMFreeQueue
)
504 gIOPMInitialized
= true;
506 if (!gIOPMInitialized
)
509 pwrMgt
= new IOServicePM
;
511 setProperty(kPwrMgtKey
, pwrMgt
);
513 queue_init(&pwrMgt
->WorkChain
);
514 queue_init(&pwrMgt
->RequestHead
);
515 queue_init(&pwrMgt
->PMDriverCallQueue
);
518 fPMLock
= IOLockAlloc();
519 fInterestedDrivers
= new IOPMinformeeList
;
520 fInterestedDrivers
->initialize();
521 fDesiredPowerState
= 0;
523 fInitialPowerChange
= true;
524 fInitialSetPowerState
= true;
525 fPreviousRequestPowerFlags
= 0;
526 fDeviceOverrideEnabled
= false;
527 fMachineState
= kIOPM_Finished
;
528 fSavedMachineState
= kIOPM_BadMachineState
;
529 fIdleTimerMinPowerState
= 0;
530 fActivityLock
= IOLockAlloc();
531 fStrictTreeOrder
= false;
532 fActivityTicklePowerState
= kInvalidTicklePowerState
;
533 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
534 fControllingDriver
= NULL
;
536 fNumberOfPowerStates
= 0;
537 fCurrentPowerState
= 0;
538 fParentsCurrentPowerFlags
= 0;
541 fParentsKnowState
= false;
543 fResponseArray
= NULL
;
544 fNotifyClientArray
= NULL
;
545 fCurrentPowerConsumption
= kIOPMUnknown
;
546 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
548 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot()))
550 gIOPMRootNode
= this;
551 fParentsKnowState
= true;
554 fAckTimer
= thread_call_allocate(
555 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
556 fSettleTimer
= thread_call_allocate(
557 &settle_timer_expired
, (thread_call_param_t
)this);
558 fIdleTimer
= thread_call_allocate(
559 &idle_timer_expired
, (thread_call_param_t
)this);
560 fDriverCallEntry
= thread_call_allocate(
561 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
562 assert(fDriverCallEntry
);
564 // Check for powerChangeDone override.
565 if (OSMemberFunctionCast(void (*)(void),
566 getResourceService(), &IOService::powerChangeDone
) !=
567 OSMemberFunctionCast(void (*)(void),
568 this, &IOService::powerChangeDone
))
570 fPCDFunctionOverride
= true;
574 IOPMprot
* prot
= new IOPMprot
;
578 prot
->ourName
= fName
;
579 prot
->thePlatform
= gPlatform
;
584 pm_vars
= (void *) (uintptr_t) true;
591 //*********************************************************************************
594 // Free the data created by PMinit. Only called from IOService::free().
595 //*********************************************************************************
597 void IOService::PMfree ( void )
604 assert(fMachineState
== kIOPM_Finished
);
605 assert(fInsertInterestSet
== NULL
);
606 assert(fRemoveInterestSet
== NULL
);
607 assert(fNotifyChildArray
== NULL
);
608 assert(queue_empty(&pwrMgt
->RequestHead
));
609 assert(queue_empty(&fPMDriverCallQueue
));
611 if ( fSettleTimer
) {
612 thread_call_cancel(fSettleTimer
);
613 thread_call_free(fSettleTimer
);
617 thread_call_cancel(fAckTimer
);
618 thread_call_free(fAckTimer
);
622 thread_call_cancel(fIdleTimer
);
623 thread_call_free(fIdleTimer
);
626 if ( fDriverCallEntry
) {
627 thread_call_free(fDriverCallEntry
);
628 fDriverCallEntry
= NULL
;
634 if ( fActivityLock
) {
635 IOLockFree(fActivityLock
);
636 fActivityLock
= NULL
;
638 if ( fInterestedDrivers
) {
639 fInterestedDrivers
->release();
640 fInterestedDrivers
= NULL
;
642 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
643 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
644 fDriverCallParamPtr
= 0;
645 fDriverCallParamSlots
= 0;
647 if ( fResponseArray
) {
648 fResponseArray
->release();
649 fResponseArray
= NULL
;
651 if ( fNotifyClientArray
) {
652 fNotifyClientArray
->release();
653 fNotifyClientArray
= NULL
;
655 if (fPowerStates
&& fNumberOfPowerStates
) {
656 IODelete(fPowerStates
, IOPMPSEntry
, fNumberOfPowerStates
);
657 fNumberOfPowerStates
= 0;
661 fPowerClients
->release();
678 //*********************************************************************************
679 // [public] joinPMtree
681 // A policy-maker calls its nub here when initializing, to be attached into
682 // the power management hierarchy. The default function is to call the
683 // platform expert, which knows how to do it. This method is overridden
684 // by a nub subclass which may either know how to do it, or may need to
685 // take other action.
687 // This may be the only "power management" method used in a nub,
688 // meaning it may not be initialized for power management.
689 //*********************************************************************************
691 void IOService::joinPMtree ( IOService
* driver
)
693 IOPlatformExpert
* platform
;
695 platform
= getPlatform();
696 assert(platform
!= 0);
697 platform
->PMRegisterDevice(this, driver
);
701 //*********************************************************************************
702 // [deprecated] youAreRoot
704 // Power Managment is informing us that we are the root power domain.
705 //*********************************************************************************
707 IOReturn
IOService::youAreRoot ( void )
711 #endif /* !__LP64__ */
713 //*********************************************************************************
716 // Immediately stop driver callouts. Schedule an async stop request to detach
718 //*********************************************************************************
720 void IOService::PMstop ( void )
722 IOPMRequest
* request
;
729 if (fLockedFlags
.PMStop
)
731 PM_LOG2("%s: PMstop() already stopped\n", fName
);
736 // Inhibit future driver calls.
737 fLockedFlags
.PMStop
= true;
739 // Wait for all prior driver calls to finish.
740 waitForPMDriverCall();
744 // The rest of the work is performed async.
745 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
748 PM_LOG2("%s: %p PMstop\n", getName(), this);
749 submitPMRequest( request
);
753 //*********************************************************************************
754 // [private] handlePMstop
756 // Disconnect the node from all parents and children in the power plane.
757 //*********************************************************************************
759 void IOService::handlePMstop ( IOPMRequest
* request
)
763 IOPowerConnection
* connection
;
764 IOService
* theChild
;
765 IOService
* theParent
;
768 PM_LOG2("%s: %p %s start\n", getName(), this, __FUNCTION__
);
770 // remove driver from prevent system sleep lists
771 getPMRootDomain()->updatePreventIdleSleepList(this, false);
772 getPMRootDomain()->updatePreventSystemSleepList(this, false);
774 // remove the property
775 removeProperty(kPwrMgtKey
);
778 iter
= getParentIterator(gIOPowerPlane
);
781 while ( (next
= iter
->getNextObject()) )
783 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
785 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
788 theParent
->removePowerChild(connection
);
789 theParent
->release();
796 // detach IOConnections
797 detachAbove( gIOPowerPlane
);
799 // no more power state changes
800 fParentsKnowState
= false;
803 iter
= getChildIterator(gIOPowerPlane
);
806 while ( (next
= iter
->getNextObject()) )
808 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
810 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
813 // detach nub from child
814 connection
->detachFromChild(theChild
, gIOPowerPlane
);
817 // detach us from nub
818 detachFromChild(connection
, gIOPowerPlane
);
824 // Remove all interested drivers from the list, including the power
825 // controlling driver.
827 // Usually, the controlling driver and the policy-maker functionality
828 // are implemented by the same object, and without the deregistration,
829 // the object will be holding an extra retain on itself, and cannot
832 if ( fInterestedDrivers
)
834 IOPMinformeeList
* list
= fInterestedDrivers
;
838 while ((item
= list
->firstInList()))
840 list
->removeFromList(item
->whatObject
);
845 // Tell idleTimerExpired() to ignore idle timer.
846 fIdleTimerPeriod
= 0;
847 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
850 PM_LOG2("%s: %p %s done\n", getName(), this, __FUNCTION__
);
853 //*********************************************************************************
854 // [public] addPowerChild
856 // Power Management is informing us who our children are.
857 //*********************************************************************************
859 IOReturn
IOService::addPowerChild ( IOService
* child
)
861 IOPowerConnection
* connection
= 0;
862 IOPMRequest
* requests
[3] = {0, 0, 0};
867 return kIOReturnBadArgument
;
869 if (!initialized
|| !child
->initialized
)
870 return IOPMNotYetInitialized
;
872 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
875 // Is this child already one of our children?
877 iter
= child
->getParentIterator( gIOPowerPlane
);
880 IORegistryEntry
* entry
;
883 while ((next
= iter
->getNextObject()))
885 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
886 isChild(entry
, gIOPowerPlane
))
896 PM_LOG("%s: %s (%p) is already a child\n",
897 getName(), child
->getName(), child
);
901 // Add the child to the power plane immediately, but the
902 // joining connection is marked as not ready.
903 // We want the child to appear in the power plane before
904 // returning to the caller, but don't want the caller to
905 // block on the PM work loop.
907 connection
= new IOPowerConnection
;
911 // Create a chain of PM requests to perform the bottom-half
912 // work from the PM work loop.
914 requests
[0] = acquirePMRequest(
916 /* type */ kIOPMRequestTypeAddPowerChild1
);
918 requests
[1] = acquirePMRequest(
920 /* type */ kIOPMRequestTypeAddPowerChild2
);
922 requests
[2] = acquirePMRequest(
924 /* type */ kIOPMRequestTypeAddPowerChild3
);
926 if (!requests
[0] || !requests
[1] || !requests
[2])
929 requests
[0]->attachNextRequest( requests
[1] );
930 requests
[1]->attachNextRequest( requests
[2] );
933 connection
->start(this);
934 connection
->setAwaitingAck(false);
935 connection
->setReadyFlag(false);
937 attachToChild( connection
, gIOPowerPlane
);
938 connection
->attachToChild( child
, gIOPowerPlane
);
940 // connection needs to be released
941 requests
[0]->fArg0
= connection
;
942 requests
[1]->fArg0
= connection
;
943 requests
[2]->fArg0
= connection
;
945 submitPMRequest( requests
, 3 );
946 return kIOReturnSuccess
;
950 if (connection
) connection
->release();
951 if (requests
[0]) releasePMRequest(requests
[0]);
952 if (requests
[1]) releasePMRequest(requests
[1]);
953 if (requests
[2]) releasePMRequest(requests
[2]);
955 // Silent failure, to prevent platform drivers from adding the child
956 // to the root domain.
958 return kIOReturnSuccess
;
961 //*********************************************************************************
962 // [private] addPowerChild1
964 // Step 1/3 of adding a power child. Called on the power parent.
965 //*********************************************************************************
967 void IOService::addPowerChild1 ( IOPMRequest
* request
)
969 unsigned long tempDesire
= 0;
971 // Make us temporary usable before adding the child.
974 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
976 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
978 tempDesire
= fNumberOfPowerStates
- 1;
981 if (tempDesire
&& (IS_PM_ROOT
|| (fMaxPowerState
>= tempDesire
)))
983 adjustPowerState(tempDesire
);
987 //*********************************************************************************
988 // [private] addPowerChild2
990 // Step 2/3 of adding a power child. Called on the joining child.
991 // Execution blocked behind addPowerChild1.
992 //*********************************************************************************
994 void IOService::addPowerChild2 ( IOPMRequest
* request
)
996 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
998 IOPMPowerFlags powerFlags
;
1000 unsigned long powerState
;
1001 unsigned long tempDesire
;
1003 PM_ASSERT_IN_GATE();
1004 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
1006 if (!parent
|| !inPlane(gIOPowerPlane
))
1008 PM_LOG("%s: addPowerChild2 not in power plane\n", getName());
1012 // Parent will be waiting for us to complete this stage.
1013 // It is safe to directly access parent's vars.
1015 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
1016 powerState
= parent
->fCurrentPowerState
;
1019 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerFlags
;
1023 // Set our power parent.
1025 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
1027 setParentInfo( powerFlags
, connection
, knowsState
);
1029 connection
->setReadyFlag(true);
1031 if ( fControllingDriver
&& fParentsKnowState
)
1033 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1034 // initially change into the state we are already in
1035 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1036 fPreviousRequestPowerFlags
= (IOPMPowerFlags
)(-1);
1037 adjustPowerState(tempDesire
);
1040 getPMRootDomain()->tagPowerPlaneService(this, &fPMActions
);
1043 //*********************************************************************************
1044 // [private] addPowerChild3
1046 // Step 3/3 of adding a power child. Called on the parent.
1047 // Execution blocked behind addPowerChild2.
1048 //*********************************************************************************
1050 void IOService::addPowerChild3 ( IOPMRequest
* request
)
1052 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
1054 IOPMrootDomain
* rootDomain
= getPMRootDomain();
1056 PM_ASSERT_IN_GATE();
1057 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
1059 if (child
&& inPlane(gIOPowerPlane
))
1061 if ((this != rootDomain
) && child
->getProperty("IOPMStrictTreeOrder"))
1063 PM_LOG1("%s: strict PM order enforced\n", getName());
1064 fStrictTreeOrder
= true;
1068 rootDomain
->joinAggressiveness( child
);
1072 PM_LOG("%s: addPowerChild3 not in power plane\n", getName());
1075 connection
->release();
1079 //*********************************************************************************
1080 // [deprecated] setPowerParent
1082 // Power Management is informing us who our parent is.
1083 // If we have a controlling driver, find out, given our newly-informed
1084 // power domain state, what state it would be in, and then tell it
1085 // to assume that state.
1086 //*********************************************************************************
1088 IOReturn
IOService::setPowerParent (
1089 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
1091 return kIOReturnUnsupported
;
1093 #endif /* !__LP64__ */
1095 //*********************************************************************************
1096 // [public] removePowerChild
1098 // Called on a parent whose child is being removed by PMstop().
1099 //*********************************************************************************
1101 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
1103 IORegistryEntry
* theChild
;
1105 PM_ASSERT_IN_GATE();
1106 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1110 // detach nub from child
1111 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1114 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1115 theChild
->release();
1117 // detach from the nub
1118 detachFromChild(theNub
, gIOPowerPlane
);
1120 // Are we awaiting an ack from this child?
1121 if ( theNub
->getAwaitingAck() )
1123 // yes, pretend we got one
1124 theNub
->setAwaitingAck(false);
1125 if (fHeadNotePendingAcks
!= 0 )
1127 // that's one fewer ack to worry about
1128 fHeadNotePendingAcks
--;
1130 // is that the last?
1131 if ( fHeadNotePendingAcks
== 0 )
1135 // Request unblocked, work queue
1136 // should re-scan all busy requests.
1137 gIOPMWorkQueue
->incrementProducerCount();
1144 // A child has gone away, re-scan children desires and clamp bits.
1145 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1147 if (!fAdjustPowerScheduled
)
1149 IOPMRequest
* request
;
1150 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1153 submitPMRequest( request
);
1154 fAdjustPowerScheduled
= true;
1161 //*********************************************************************************
1162 // [public] registerPowerDriver
1164 // A driver has called us volunteering to control power to our device.
1165 //*********************************************************************************
1167 IOReturn
IOService::registerPowerDriver (
1168 IOService
* powerDriver
,
1169 IOPMPowerState
* powerStates
,
1170 unsigned long numberOfStates
)
1172 IOPMRequest
* request
;
1173 IOPMPSEntry
* powerStatesCopy
= 0;
1176 return IOPMNotYetInitialized
;
1178 // Validate arguments.
1179 if (!powerStates
|| (numberOfStates
< 2))
1181 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1182 return kIOReturnBadArgument
;
1185 if (!powerDriver
|| !powerDriver
->initialized
)
1187 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1188 return kIOReturnBadArgument
;
1191 if (powerStates
[0].version
!= kIOPMPowerStateVersion1
)
1193 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1194 return kIOReturnBadArgument
;
1198 // Make a copy of the supplied power state array.
1199 powerStatesCopy
= IONew(IOPMPSEntry
, numberOfStates
);
1200 if (!powerStatesCopy
)
1203 for (uint32_t i
= 0; i
< numberOfStates
; i
++)
1205 powerStatesCopy
[i
].capabilityFlags
= powerStates
[i
].capabilityFlags
;
1206 powerStatesCopy
[i
].outputPowerFlags
= powerStates
[i
].outputPowerCharacter
;
1207 powerStatesCopy
[i
].inputPowerFlags
= powerStates
[i
].inputPowerRequirement
;
1208 powerStatesCopy
[i
].staticPower
= powerStates
[i
].staticPower
;
1209 powerStatesCopy
[i
].settleUpTime
= powerStates
[i
].settleUpTime
;
1210 powerStatesCopy
[i
].settleDownTime
= powerStates
[i
].settleDownTime
;
1213 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1217 powerDriver
->retain();
1218 request
->fArg0
= (void *) powerDriver
;
1219 request
->fArg1
= (void *) powerStatesCopy
;
1220 request
->fArg2
= (void *) numberOfStates
;
1222 submitPMRequest( request
);
1223 return kIOReturnSuccess
;
1227 if (powerStatesCopy
)
1228 IODelete(powerStatesCopy
, IOPMPSEntry
, numberOfStates
);
1229 return kIOReturnNoMemory
;
1232 //*********************************************************************************
1233 // [private] handleRegisterPowerDriver
1234 //*********************************************************************************
1236 void IOService::handleRegisterPowerDriver ( IOPMRequest
* request
)
1238 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1239 IOPMPSEntry
* powerStates
= (IOPMPSEntry
*) request
->fArg1
;
1240 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1245 PM_ASSERT_IN_GATE();
1246 assert(powerStates
);
1247 assert(powerDriver
);
1248 assert(numberOfStates
> 1);
1250 if ( !fNumberOfPowerStates
)
1252 OUR_PMLog(kPMLogControllingDriver
,
1253 (unsigned long) numberOfStates
,
1254 (unsigned long) kIOPMPowerStateVersion1
);
1256 fPowerStates
= powerStates
;
1257 fNumberOfPowerStates
= numberOfStates
;
1258 fControllingDriver
= powerDriver
;
1259 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1261 // make a mask of all the character bits we know about
1262 fOutputPowerCharacterFlags
= 0;
1263 for ( i
= 0; i
< numberOfStates
; i
++ ) {
1264 fOutputPowerCharacterFlags
|= fPowerStates
[i
].outputPowerFlags
;
1265 if (!fDeviceUsablePowerState
&&
1266 (fPowerStates
[i
].capabilityFlags
& IOPMDeviceUsable
))
1268 // The minimum power state that the device is usable
1269 fDeviceUsablePowerState
= i
;
1273 // Register powerDriver as interested, unless already done.
1274 // We don't want to register the default implementation since
1275 // it does nothing. One ramification of not always registering
1276 // is the one fewer retain count held.
1278 root
= getPlatform()->getProvider();
1281 ((OSMemberFunctionCast(void (*)(void),
1282 root
, &IOService::powerStateDidChangeTo
)) !=
1283 ((OSMemberFunctionCast(void (*)(void),
1284 this, &IOService::powerStateDidChangeTo
)))) ||
1285 ((OSMemberFunctionCast(void (*)(void),
1286 root
, &IOService::powerStateWillChangeTo
)) !=
1287 ((OSMemberFunctionCast(void (*)(void),
1288 this, &IOService::powerStateWillChangeTo
)))))
1290 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
)
1293 fInterestedDrivers
->appendNewInformee(powerDriver
);
1298 // Examine all existing power clients and perform limit check.
1302 iter
= OSCollectionIterator::withCollection(fPowerClients
);
1305 const OSSymbol
* client
;
1306 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
1308 uint32_t powerState
= getPowerStateForClient(client
);
1309 if (powerState
>= numberOfStates
)
1311 updatePowerClient(client
, numberOfStates
- 1);
1318 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1320 unsigned long tempDesire
;
1321 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1322 // initially change into the state we are already in
1323 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1324 adjustPowerState(tempDesire
);
1329 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1330 IODelete(powerStates
, IOPMPSEntry
, numberOfStates
);
1333 powerDriver
->release();
1336 //*********************************************************************************
1337 // [public] registerInterestedDriver
1339 // Add the caller to our list of interested drivers and return our current
1340 // power state. If we don't have a power-controlling driver yet, we will
1341 // call this interested driver again later when we do get a driver and find
1342 // out what the current power state of the device is.
1343 //*********************************************************************************
1345 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* driver
)
1347 IOPMRequest
* request
;
1350 if (!driver
|| !initialized
|| !fInterestedDrivers
)
1354 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1355 if (fInsertInterestSet
== NULL
)
1356 fInsertInterestSet
= OSSet::withCapacity(4);
1357 if (fInsertInterestSet
)
1359 fInsertInterestSet
->setObject(driver
);
1360 if (fRemoveInterestSet
)
1361 fRemoveInterestSet
->removeObject(driver
);
1367 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1369 submitPMRequest( request
);
1372 // This return value cannot be trusted, but return a value
1373 // for those clients that care.
1375 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1376 return kIOPMDeviceUsable
;
1379 //*********************************************************************************
1380 // [public] deRegisterInterestedDriver
1381 //*********************************************************************************
1383 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* driver
)
1385 IOPMinformeeList
* list
;
1386 IOPMinformee
* item
;
1387 IOPMRequest
* request
;
1391 return kIOReturnBadArgument
;
1392 if (!initialized
|| !fInterestedDrivers
)
1393 return IOPMNotPowerManaged
;
1396 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1397 if (fRemoveInterestSet
== NULL
)
1398 fRemoveInterestSet
= OSSet::withCapacity(4);
1399 if (fRemoveInterestSet
)
1401 fRemoveInterestSet
->setObject(driver
);
1402 if (fInsertInterestSet
)
1403 fInsertInterestSet
->removeObject(driver
);
1405 list
= fInterestedDrivers
;
1406 item
= list
->findItem(driver
);
1407 if (item
&& item
->active
)
1409 item
->active
= false;
1410 waitForPMDriverCall( driver
);
1417 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1419 submitPMRequest( request
);
1425 //*********************************************************************************
1426 // [private] handleInterestChanged
1428 // Handle interest added or removed.
1429 //*********************************************************************************
1431 void IOService::handleInterestChanged( IOPMRequest
* request
)
1434 IOPMinformee
* informee
;
1435 IOPMinformeeList
* list
= fInterestedDrivers
;
1439 if (fInsertInterestSet
)
1441 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject()))
1443 if (list
->findItem(driver
) == NULL
)
1445 informee
= list
->appendNewInformee(driver
);
1447 fInsertInterestSet
->removeObject(driver
);
1449 fInsertInterestSet
->release();
1450 fInsertInterestSet
= 0;
1453 if (fRemoveInterestSet
)
1455 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject()))
1457 informee
= list
->findItem(driver
);
1460 // Clean-up async interest acknowledgement
1461 if (fHeadNotePendingAcks
&& informee
->timer
)
1463 informee
->timer
= 0;
1464 fHeadNotePendingAcks
--;
1466 list
->removeFromList(driver
);
1468 fRemoveInterestSet
->removeObject(driver
);
1470 fRemoveInterestSet
->release();
1471 fRemoveInterestSet
= 0;
1477 //*********************************************************************************
1478 // [public] acknowledgePowerChange
1480 // After we notified one of the interested drivers or a power-domain child
1481 // of an impending change in power, it has called to say it is now
1482 // prepared for the change. If this object is the last to
1483 // acknowledge this change, we take whatever action we have been waiting
1485 // That may include acknowledging to our parent. In this case, we do it
1486 // last of all to insure that this doesn't cause the parent to call us some-
1487 // where else and alter data we are relying on here (like the very existance
1488 // of a "current change note".)
1489 //*********************************************************************************
1491 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
1493 IOPMRequest
* request
;
1496 return IOPMNotYetInitialized
;
1498 return kIOReturnBadArgument
;
1500 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1502 return kIOReturnNoMemory
;
1504 whichObject
->retain();
1505 request
->fArg0
= whichObject
;
1507 submitPMRequest( request
);
1511 //*********************************************************************************
1512 // [private] handleAcknowledgePowerChange
1513 //*********************************************************************************
1515 bool IOService::handleAcknowledgePowerChange ( IOPMRequest
* request
)
1517 IOPMinformee
* informee
;
1518 unsigned long childPower
= kIOPMUnknown
;
1519 IOService
* theChild
;
1520 IOService
* whichObject
;
1521 bool all_acked
= false;
1523 PM_ASSERT_IN_GATE();
1524 whichObject
= (IOService
*) request
->fArg0
;
1525 assert(whichObject
);
1527 // one of our interested drivers?
1528 informee
= fInterestedDrivers
->findItem( whichObject
);
1529 if ( informee
== NULL
)
1531 if ( !isChild(whichObject
, gIOPowerPlane
) )
1533 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1536 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1539 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1542 if ( fHeadNotePendingAcks
!= 0 )
1544 assert(fPowerStates
!= NULL
);
1546 // yes, make sure we're expecting acks
1547 if ( informee
!= NULL
)
1549 // it's an interested driver
1550 // make sure we're expecting this ack
1551 if ( informee
->timer
!= 0 )
1553 #if LOG_SETPOWER_TIMES
1554 if (informee
->timer
> 0)
1556 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1557 if (nsec
> LOG_SETPOWER_TIMES
)
1558 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) async took %d ms\n",
1559 informee
->whatObject
->getName(),
1560 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
1561 informee
->whatObject
,
1562 fName
, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_US(nsec
));
1564 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
1565 ? kIOPMEventTypePSWillChangeTo
1566 : kIOPMEventTypePSDidChangeTo
;
1568 PMEventDetails
*details
= PMEventDetails::eventDetails(
1572 informee
->whatObject
->getName(),
1576 getPMRootDomain()->recordAndReleasePMEventGated( details
);
1580 informee
->timer
= 0;
1581 // that's one fewer to worry about
1582 fHeadNotePendingAcks
--;
1584 // this driver has already acked
1585 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1589 // make sure we're expecting this ack
1590 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1592 // that's one fewer to worry about
1593 fHeadNotePendingAcks
--;
1594 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1595 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1598 childPower
= theChild
->currentPowerConsumption();
1599 theChild
->release();
1601 if ( childPower
== kIOPMUnknown
)
1603 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1605 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
1607 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1613 if ( fHeadNotePendingAcks
== 0 ) {
1614 // yes, stop the timer
1616 // and now we can continue
1620 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1625 whichObject
->release();
1630 //*********************************************************************************
1631 // [public] acknowledgeSetPowerState
1633 // After we instructed our controlling driver to change power states,
1634 // it has called to say it has finished doing so.
1635 // We continue to process the power state change.
1636 //*********************************************************************************
1638 IOReturn
IOService::acknowledgeSetPowerState ( void )
1640 IOPMRequest
* request
;
1643 return IOPMNotYetInitialized
;
1645 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1647 return kIOReturnNoMemory
;
1649 submitPMRequest( request
);
1650 return kIOReturnSuccess
;
1653 //*********************************************************************************
1654 // [private] adjustPowerState
1655 //*********************************************************************************
1657 void IOService::adjustPowerState ( uint32_t clamp
)
1659 PM_ASSERT_IN_GATE();
1660 computeDesiredState(clamp
);
1661 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
))
1663 IOPMPowerChangeFlags changeFlags
= kIOPMSelfInitiated
;
1665 // Indicate that children desires were ignored, and do not ask
1666 // apps for permission to drop power. This is used by root domain
1667 // for demand sleep.
1669 if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
1670 changeFlags
|= (kIOPMIgnoreChildren
| kIOPMSkipAskPowerDown
);
1673 /* flags */ changeFlags
,
1674 /* power state */ fDesiredPowerState
,
1675 /* domain flags */ 0,
1677 /* parent flags */ 0);
1681 //*********************************************************************************
1682 // [public] synchronizePowerTree
1683 //*********************************************************************************
1685 IOReturn
IOService::synchronizePowerTree (
1686 IOOptionBits options
,
1687 IOService
* notifyRoot
)
1689 IOPMRequest
* request_c
= 0;
1690 IOPMRequest
* request_s
;
1692 if (this != getPMRootDomain())
1693 return kIOReturnBadArgument
;
1695 return kIOPMNotYetInitialized
;
1701 // Cancels don't need to be synchronized.
1702 nr
= acquirePMRequest(notifyRoot
, kIOPMRequestTypeChildNotifyDelayCancel
);
1703 if (nr
) submitPMRequest(nr
);
1704 nr
= acquirePMRequest(getPMRootDomain(), kIOPMRequestTypeChildNotifyDelayCancel
);
1705 if (nr
) submitPMRequest(nr
);
1708 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1710 goto error_no_memory
;
1712 if (options
& kIOPMSyncCancelPowerDown
)
1713 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1716 request_c
->attachNextRequest( request_s
);
1717 submitPMRequest(request_c
);
1720 request_s
->fArg0
= (void *)(uintptr_t) options
;
1721 submitPMRequest(request_s
);
1723 return kIOReturnSuccess
;
1726 if (request_c
) releasePMRequest(request_c
);
1727 if (request_s
) releasePMRequest(request_s
);
1728 return kIOReturnNoMemory
;
1731 //*********************************************************************************
1732 // [private] handleSynchronizePowerTree
1733 //*********************************************************************************
1735 void IOService::handleSynchronizePowerTree ( IOPMRequest
* request
)
1737 PM_ASSERT_IN_GATE();
1738 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1739 (fCurrentPowerState
== fNumberOfPowerStates
- 1))
1741 IOOptionBits options
= (uintptr_t) request
->fArg0
;
1744 /* flags */ kIOPMSelfInitiated
| kIOPMSynchronize
|
1745 (options
& kIOPMSyncNoChildNotify
),
1746 /* power state */ fCurrentPowerState
,
1747 /* domain flags */ 0,
1749 /* parent flags */ 0);
1754 //*********************************************************************************
1755 // [deprecated] powerDomainWillChangeTo
1757 // Called by the power-hierarchy parent notifying of a new power state
1758 // in the power domain.
1759 // We enqueue a parent power-change to our queue of power changes.
1760 // This may or may not cause us to change power, depending on what
1761 // kind of change is occuring in the domain.
1762 //*********************************************************************************
1764 IOReturn
IOService::powerDomainWillChangeTo (
1765 IOPMPowerFlags newPowerFlags
,
1766 IOPowerConnection
* whichParent
)
1769 return kIOReturnUnsupported
;
1771 #endif /* !__LP64__ */
1773 //*********************************************************************************
1774 // [private] handlePowerDomainWillChangeTo
1775 //*********************************************************************************
1777 void IOService::handlePowerDomainWillChangeTo ( IOPMRequest
* request
)
1779 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1780 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1781 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1782 IOPMPowerChangeFlags myChangeFlags
;
1785 IOPowerConnection
* connection
;
1786 IOPMPowerStateIndex newPowerState
;
1787 IOPMPowerFlags combinedPowerFlags
;
1788 bool savedParentsKnowState
;
1789 IOReturn result
= IOPMAckImplied
;
1791 PM_ASSERT_IN_GATE();
1792 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1794 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1796 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1800 savedParentsKnowState
= fParentsKnowState
;
1802 // Combine parents' output power flags.
1804 combinedPowerFlags
= 0;
1806 iter
= getParentIterator(gIOPowerPlane
);
1809 while ( (next
= iter
->getNextObject()) )
1811 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1813 if ( connection
== whichParent
)
1814 combinedPowerFlags
|= parentPowerFlags
;
1816 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1822 // If our initial change has yet to occur, then defer the power change
1823 // until after the power domain has completed its power transition.
1825 if ( fControllingDriver
&& !fInitialPowerChange
)
1827 newPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1828 combinedPowerFlags
);
1830 // Absorb parent's kIOPMSynchronize flag.
1831 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1832 (parentChangeFlags
& kIOPMSynchronize
);
1834 result
= startPowerChange(
1835 /* flags */ myChangeFlags
,
1836 /* power state */ newPowerState
,
1837 /* domain flags */ combinedPowerFlags
,
1838 /* connection */ whichParent
,
1839 /* parent flags */ parentPowerFlags
);
1842 // If parent is dropping power, immediately update the parent's
1843 // capability flags. Any future merging of parent(s) combined
1844 // power flags should account for this power drop.
1846 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1848 setParentInfo(parentPowerFlags
, whichParent
, true);
1851 // Parent is expecting an ACK from us. If we did not embark on a state
1852 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1853 // still required to issue an ACK to our parent.
1855 if (IOPMAckImplied
== result
)
1858 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1862 parent
->acknowledgePowerChange( whichParent
);
1868 // Drop the retain from notifyChild().
1869 if (whichParent
) whichParent
->release();
1873 //*********************************************************************************
1874 // [deprecated] powerDomainDidChangeTo
1876 // Called by the power-hierarchy parent after the power state of the power domain
1877 // has settled at a new level.
1878 // We enqueue a parent power-change to our queue of power changes.
1879 // This may or may not cause us to change power, depending on what
1880 // kind of change is occuring in the domain.
1881 //*********************************************************************************
1883 IOReturn
IOService::powerDomainDidChangeTo (
1884 IOPMPowerFlags newPowerFlags
,
1885 IOPowerConnection
* whichParent
)
1888 return kIOReturnUnsupported
;
1890 #endif /* !__LP64__ */
1892 //*********************************************************************************
1893 // [private] handlePowerDomainDidChangeTo
1894 //*********************************************************************************
1896 void IOService::handlePowerDomainDidChangeTo ( IOPMRequest
* request
)
1898 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1899 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1900 IOPMPowerChangeFlags parentChangeFlags
= (IOPMPowerChangeFlags
)(uintptr_t) request
->fArg2
;
1901 IOPMPowerChangeFlags myChangeFlags
;
1902 IOPMPowerStateIndex newPowerState
;
1903 IOPMPowerStateIndex initialDesire
;
1904 bool savedParentsKnowState
;
1905 IOReturn result
= IOPMAckImplied
;
1907 PM_ASSERT_IN_GATE();
1908 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1910 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1912 PM_LOG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1916 savedParentsKnowState
= fParentsKnowState
;
1918 setParentInfo(parentPowerFlags
, whichParent
, true);
1920 if ( fControllingDriver
)
1922 newPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1923 fParentsCurrentPowerFlags
);
1925 if (fInitialPowerChange
)
1927 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1928 fParentsCurrentPowerFlags
);
1929 computeDesiredState(initialDesire
);
1931 else if (fAdvisoryTickleUsed
&& (newPowerState
> 0) &&
1932 ((parentChangeFlags
& kIOPMSynchronize
) == 0))
1934 // re-compute desired state in case advisory tickle was enabled
1935 computeDesiredState();
1938 // Absorb parent's kIOPMSynchronize flag.
1939 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1940 (parentChangeFlags
& kIOPMSynchronize
);
1942 result
= startPowerChange(
1943 /* flags */ myChangeFlags
,
1944 /* power state */ newPowerState
,
1945 /* domain flags */ fParentsCurrentPowerFlags
,
1946 /* connection */ whichParent
,
1947 /* parent flags */ 0);
1950 // Parent is expecting an ACK from us. If we did not embark on a state
1951 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1952 // still required to issue an ACK to our parent.
1954 if (IOPMAckImplied
== result
)
1957 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1961 parent
->acknowledgePowerChange( whichParent
);
1966 // If the parent registers its power driver late, then this is the
1967 // first opportunity to tell our parent about our desire.
1969 if (!savedParentsKnowState
&& fParentsKnowState
)
1971 PM_LOG1("%s::powerDomainDidChangeTo parentsKnowState = true\n",
1973 requestDomainPower( fDesiredPowerState
);
1977 // Drop the retain from notifyChild().
1978 if (whichParent
) whichParent
->release();
1981 //*********************************************************************************
1982 // [private] setParentInfo
1984 // Set our connection data for one specific parent, and then combine all the parent
1986 //*********************************************************************************
1988 void IOService::setParentInfo (
1989 IOPMPowerFlags newPowerFlags
,
1990 IOPowerConnection
* whichParent
,
1995 IOPowerConnection
* conn
;
1997 PM_ASSERT_IN_GATE();
1999 // set our connection data
2000 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
2001 whichParent
->setParentKnowsState(knowsState
);
2003 // recompute our parent info
2004 fParentsCurrentPowerFlags
= 0;
2005 fParentsKnowState
= true;
2007 iter
= getParentIterator(gIOPowerPlane
);
2010 while ( (next
= iter
->getNextObject()) )
2012 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
2014 fParentsKnowState
&= conn
->parentKnowsState();
2015 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
2022 //******************************************************************************
2023 // [private] trackSystemSleepPreventers
2024 //******************************************************************************
2026 void IOService::trackSystemSleepPreventers(
2027 IOPMPowerStateIndex oldPowerState
,
2028 IOPMPowerStateIndex newPowerState
,
2029 IOPMPowerChangeFlags changeFlags __unused
)
2031 IOPMPowerFlags oldCapability
, newCapability
;
2033 oldCapability
= fPowerStates
[oldPowerState
].capabilityFlags
&
2034 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2035 newCapability
= fPowerStates
[newPowerState
].capabilityFlags
&
2036 (kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
2038 if (fHeadNoteChangeFlags
& kIOPMInitialPowerChange
)
2040 if (oldCapability
== newCapability
)
2043 if ((oldCapability
^ newCapability
) & kIOPMPreventIdleSleep
)
2045 #if SUPPORT_IDLE_CANCEL
2046 if ((oldCapability
& kIOPMPreventIdleSleep
) == 0)
2048 IOPMRequest
* cancelRequest
;
2050 cancelRequest
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
2053 getPMRootDomain()->submitPMRequest( cancelRequest
);
2058 getPMRootDomain()->updatePreventIdleSleepList(this,
2059 ((oldCapability
& kIOPMPreventIdleSleep
) == 0));
2062 if ((oldCapability
^ newCapability
) & kIOPMPreventSystemSleep
)
2065 getPMRootDomain()->updatePreventSystemSleepList(this,
2066 ((oldCapability
& kIOPMPreventSystemSleep
) == 0));
2070 //*********************************************************************************
2071 // [public] requestPowerDomainState
2073 // Called on a power parent when a child's power requirement changes.
2074 //*********************************************************************************
2076 IOReturn
IOService::requestPowerDomainState(
2077 IOPMPowerFlags childRequestPowerFlags
,
2078 IOPowerConnection
* childConnection
,
2079 unsigned long specification
)
2081 IOPMPowerStateIndex ps
;
2082 IOPMPowerFlags outputPowerFlags
;
2084 IOPMRequest
* subRequest
;
2085 bool adjustPower
= false;
2088 return IOPMNotYetInitialized
;
2090 if (gIOPMWorkLoop
->onThread() == false)
2092 PM_LOG("%s::requestPowerDomainState\n", getName());
2093 return kIOReturnSuccess
;
2096 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
2098 if (!isChild(childConnection
, gIOPowerPlane
))
2099 return kIOReturnNotAttached
;
2101 if (!fControllingDriver
|| !fNumberOfPowerStates
)
2102 return kIOReturnNotReady
;
2104 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
2107 // Merge in the power flags contributed by this power parent
2108 // at its current or impending power state.
2110 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerFlags
;
2111 if (fMachineState
!= kIOPM_Finished
)
2113 if (IS_POWER_DROP
&& !IS_ROOT_DOMAIN
)
2115 // Use the lower power state when dropping power.
2116 // Must be careful since a power drop can be canceled
2117 // from the following states:
2118 // - kIOPM_OurChangeTellClientsPowerDown
2119 // - kIOPM_OurChangeTellPriorityClientsPowerDown
2121 // The child must not wait for this parent to raise power
2122 // if the power drop was cancelled. The solution is to cancel
2123 // the power drop if possible, then schedule an adjustment to
2124 // re-evaluate the parent's power state.
2126 // Root domain is excluded to avoid idle sleep issues. And permit
2127 // root domain children to pop up when system is going to sleep.
2129 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
2130 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
2132 fDoNotPowerDown
= true; // cancel power drop
2133 adjustPower
= true; // schedule an adjustment
2134 PM_LOG1("%s: power drop cancelled in state %u by %s\n",
2135 getName(), fMachineState
, child
->getName());
2139 // Beyond cancellation point, report the impending state.
2141 fPowerStates
[fHeadNotePowerState
].outputPowerFlags
;
2144 else if (IS_POWER_RISE
)
2146 // When raising power, must report the output power flags from
2147 // child's perspective. A child power request may arrive while
2148 // parent is transitioning upwards. If a request arrives after
2149 // setParentInfo() has already recorded the output power flags
2150 // for the next power state, then using the power supplied by
2151 // fCurrentPowerState is incorrect, and might cause the child
2152 // to wait when it should not.
2154 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2157 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2159 // Map child's requested power flags to one of our power state.
2161 for (ps
= 0; ps
< fNumberOfPowerStates
; ps
++)
2163 if ((fPowerStates
[ps
].outputPowerFlags
& childRequestPowerFlags
) ==
2164 (fOutputPowerCharacterFlags
& childRequestPowerFlags
))
2167 if (ps
>= fNumberOfPowerStates
)
2169 ps
= 0; // should never happen
2172 // Conditions that warrants a power adjustment on this parent.
2173 // Adjust power will also propagate any changes to the child's
2174 // prevent idle/sleep flags towards the root domain.
2176 if (!childConnection
->childHasRequestedPower() ||
2177 (ps
!= childConnection
->getDesiredDomainState()))
2180 #if ENABLE_DEBUG_LOGS
2183 PM_LOG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2184 getName(), child
->getName(),
2185 !childConnection
->childHasRequestedPower(),
2186 (uint32_t) childConnection
->getDesiredDomainState(),
2191 // Record the child's desires on the connection.
2192 childConnection
->setChildHasRequestedPower();
2193 childConnection
->setDesiredDomainState( ps
);
2195 // Schedule a request to re-evaluate all children desires and
2196 // adjust power state. Submit a request if one wasn't pending,
2197 // or if the current request is part of a call tree.
2199 if (adjustPower
&& !fDeviceOverrideEnabled
&&
2200 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest()))
2202 subRequest
= acquirePMRequest(
2203 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2206 submitPMRequest( subRequest
);
2207 fAdjustPowerScheduled
= true;
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 if (client
== gIOPMPowerClientAdvisoryTickle
&&
2597 !gIOPMAdvisoryTickleEnabled
)
2600 desiredState
= getPowerStateForClient(client
);
2601 assert(desiredState
< fNumberOfPowerStates
);
2603 desiredState
, client
->getCStringNoCopy());
2605 newPowerState
= max(newPowerState
, desiredState
);
2607 if (client
== gIOPMPowerClientDevice
)
2608 fDeviceDesire
= desiredState
;
2613 // Factor in the temporary power desires.
2615 newPowerState
= max(newPowerState
, localClamp
);
2616 newPowerState
= max(newPowerState
, fTempClampPowerState
);
2618 // Limit check against max power override.
2620 newPowerState
= min(newPowerState
, fOverrideMaxPowerState
);
2622 // Limit check against number of power states.
2624 if (newPowerState
>= fNumberOfPowerStates
)
2625 newPowerState
= fNumberOfPowerStates
- 1;
2627 fDesiredPowerState
= newPowerState
;
2629 PM_LOG1(" temp %u, clamp %u, current %u, new %u\n",
2630 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2631 (uint32_t) fCurrentPowerState
, newPowerState
);
2633 // Restart idle timer if stopped and device desire has increased.
2634 // Or if advisory desire exists.
2636 if (fIdleTimerStopped
)
2638 if (fDeviceDesire
> 0)
2640 fIdleTimerStopped
= false;
2641 fActivityTickleCount
= 0;
2642 clock_get_uptime(&fIdleTimerStartTime
);
2643 start_PM_idle_timer();
2645 else if (fHasAdvisoryDesire
)
2647 fIdleTimerStopped
= false;
2648 start_PM_idle_timer();
2652 // Invalidate cached tickle power state when desires change, and not
2653 // due to a tickle request. This invalidation must occur before the
2654 // power state change to minimize races. We want to err on the side
2655 // of servicing more activity tickles rather than dropping one when
2656 // the device is in a low power state.
2658 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2659 (fActivityTicklePowerState
!= kInvalidTicklePowerState
))
2661 IOLockLock(fActivityLock
);
2662 fActivityTicklePowerState
= kInvalidTicklePowerState
;
2663 IOLockUnlock(fActivityLock
);
2667 //*********************************************************************************
2668 // [public] currentPowerConsumption
2670 //*********************************************************************************
2672 unsigned long IOService::currentPowerConsumption ( void )
2675 return kIOPMUnknown
;
2677 return fCurrentPowerConsumption
;
2680 //*********************************************************************************
2681 // [deprecated] getPMworkloop
2682 //*********************************************************************************
2684 IOWorkLoop
* IOService::getPMworkloop ( void )
2686 return gIOPMWorkLoop
;
2691 //*********************************************************************************
2692 // Power Parent/Children Applier
2693 //*********************************************************************************
2696 applyToPowerChildren(
2697 IOService
* service
,
2698 IOServiceApplierFunction applier
,
2700 IOOptionBits options
)
2702 PM_ASSERT_IN_GATE();
2704 IORegistryEntry
* entry
;
2705 IORegistryIterator
* iter
;
2706 IOPowerConnection
* connection
;
2709 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
, options
);
2712 while ((entry
= iter
->getNextObject()))
2714 // Get child of IOPowerConnection objects
2715 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2717 child
= (IOService
*) connection
->copyChildEntry(gIOPowerPlane
);
2720 (*applier
)(child
, context
);
2731 IOService
* service
,
2732 IOServiceApplierFunction applier
,
2734 IOOptionBits options
)
2736 PM_ASSERT_IN_GATE();
2738 IORegistryEntry
* entry
;
2739 IORegistryIterator
* iter
;
2740 IOPowerConnection
* connection
;
2743 iter
= IORegistryIterator::iterateOver(service
, gIOPowerPlane
,
2744 options
| kIORegistryIterateParents
);
2747 while ((entry
= iter
->getNextObject()))
2749 // Get child of IOPowerConnection objects
2750 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)))
2752 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
2755 (*applier
)(parent
, context
);
2764 #endif /* NOT_YET */
2767 // MARK: Activity Tickle & Idle Timer
2769 void IOService::setAdvisoryTickleEnable( bool enable
)
2771 gIOPMAdvisoryTickleEnabled
= enable
;
2774 //*********************************************************************************
2775 // [public] activityTickle
2777 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2778 // flag to be set, and the device state checked. If the device has been
2779 // powered down, it is powered up again.
2780 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2781 // should be intercepted by a subclass.
2782 //*********************************************************************************
2784 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
2786 IOPMRequest
* request
;
2787 bool noPowerChange
= true;
2790 return true; // no power change
2792 if ((type
== kIOPMSuperclassPolicy1
) && stateNumber
)
2794 IOLockLock(fActivityLock
);
2796 // Record device activity for the idle timer handler.
2798 fDeviceWasActive
= true;
2799 fActivityTickleCount
++;
2800 clock_get_uptime(&fDeviceActiveTimestamp
);
2802 PM_ACTION_0(actionActivityTickle
);
2804 // Record the last tickle power state.
2805 // This helps to filter out redundant tickles as
2806 // this function may be called from the data path.
2808 if (fActivityTicklePowerState
< (int)stateNumber
)
2810 fActivityTicklePowerState
= stateNumber
;
2811 noPowerChange
= false;
2813 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2816 request
->fArg0
= (void *) stateNumber
; // power state
2817 request
->fArg1
= (void *) true; // power rise
2818 request
->fArg2
= (void *) false; // regular tickle
2819 submitPMRequest(request
);
2823 IOLockUnlock(fActivityLock
);
2826 else if ((type
== kIOPMActivityTickleTypeAdvisory
) &&
2827 ((stateNumber
= fDeviceUsablePowerState
)))
2829 IOLockLock(fActivityLock
);
2831 fAdvisoryTickled
= true;
2833 if (fAdvisoryTicklePowerState
!= (int)stateNumber
)
2835 fAdvisoryTicklePowerState
= stateNumber
;
2836 noPowerChange
= false;
2838 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2841 request
->fArg0
= (void *) stateNumber
; // power state
2842 request
->fArg1
= (void *) true; // power rise
2843 request
->fArg2
= (void *) true; // advisory tickle
2844 submitPMRequest(request
);
2848 IOLockUnlock(fActivityLock
);
2851 // Returns false if the activityTickle might cause a transition to a
2852 // higher powered state, true otherwise.
2854 return noPowerChange
;
2857 //*********************************************************************************
2858 // [private] handleActivityTickle
2859 //*********************************************************************************
2861 void IOService::handleActivityTickle ( IOPMRequest
* request
)
2863 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2864 bool deviceWasActive
= (request
->fArg1
== (void *) true);
2865 bool isRegularTickle
= (request
->fArg2
== (void *) false);
2866 bool adjustPower
= false;
2868 PM_ASSERT_IN_GATE();
2869 if (isRegularTickle
)
2871 if (deviceWasActive
)
2873 if ((ticklePowerState
> fDeviceDesire
) &&
2874 (ticklePowerState
< fNumberOfPowerStates
))
2876 fIdleTimerMinPowerState
= ticklePowerState
;
2877 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2881 else if (fDeviceDesire
> fIdleTimerMinPowerState
)
2883 // Power drop due to idle timer expiration.
2884 // Do not allow idle timer to reduce power below tickle power.
2885 // This prevents the idle timer from decreasing the device desire
2886 // to zero and cancelling the effect of a pre-sleep tickle when
2887 // system wakes up to doze state, while the device is unable to
2888 // raise its power state to satisfy the tickle.
2890 ticklePowerState
= fDeviceDesire
- 1;
2891 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2895 else // advisory tickle
2897 if (deviceWasActive
)
2899 if ((ticklePowerState
== fDeviceUsablePowerState
) &&
2900 (ticklePowerState
< fNumberOfPowerStates
))
2902 updatePowerClient(gIOPMPowerClientAdvisoryTickle
, ticklePowerState
);
2903 fHasAdvisoryDesire
= true;
2904 fAdvisoryTickleUsed
= true;
2909 IOLockLock(fActivityLock
);
2910 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
2911 IOLockUnlock(fActivityLock
);
2914 else if (fHasAdvisoryDesire
)
2916 removePowerClient(gIOPMPowerClientAdvisoryTickle
);
2917 fHasAdvisoryDesire
= false;
2928 //******************************************************************************
2929 // [public] setIdleTimerPeriod
2931 // A subclass policy-maker is using our standard idleness detection service.
2932 // Start the idle timer. Period is in seconds.
2933 //******************************************************************************
2935 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
2938 return IOPMNotYetInitialized
;
2940 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, fIdleTimerPeriod
);
2942 IOPMRequest
* request
=
2943 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
2945 return kIOReturnNoMemory
;
2947 request
->fArg0
= (void *) period
;
2948 submitPMRequest( request
);
2950 return kIOReturnSuccess
;
2953 IOReturn
IOService::setIgnoreIdleTimer( bool ignore
)
2956 return IOPMNotYetInitialized
;
2958 OUR_PMLog(kIOPMRequestTypeIgnoreIdleTimer
, ignore
, 0);
2960 IOPMRequest
* request
=
2961 acquirePMRequest( this, kIOPMRequestTypeIgnoreIdleTimer
);
2963 return kIOReturnNoMemory
;
2965 request
->fArg0
= (void *) ignore
;
2966 submitPMRequest( request
);
2968 return kIOReturnSuccess
;
2971 //******************************************************************************
2972 // [public] nextIdleTimeout
2974 // Returns how many "seconds from now" the device should idle into its
2975 // next lowest power state.
2976 //******************************************************************************
2978 SInt32
IOService::nextIdleTimeout(
2979 AbsoluteTime currentTime
,
2980 AbsoluteTime lastActivity
,
2981 unsigned int powerState
)
2988 // Calculate time difference using funky macro from clock.h.
2989 delta
= currentTime
;
2990 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
2992 // Figure it in seconds.
2993 absolutetime_to_nanoseconds(delta
, &delta_ns
);
2994 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
2996 // Be paranoid about delta somehow exceeding timer period.
2997 if (delta_secs
< (int) fIdleTimerPeriod
)
2998 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
3000 delay_secs
= (int) fIdleTimerPeriod
;
3002 return (SInt32
)delay_secs
;
3005 //*********************************************************************************
3006 // [public] start_PM_idle_timer
3007 //*********************************************************************************
3009 void IOService::start_PM_idle_timer ( void )
3011 static const int maxTimeout
= 100000;
3012 static const int minTimeout
= 1;
3013 AbsoluteTime uptime
, deadline
;
3017 if (!initialized
|| !fIdleTimerPeriod
)
3020 IOLockLock(fActivityLock
);
3022 clock_get_uptime(&uptime
);
3024 // Subclasses may modify idle sleep algorithm
3025 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
3027 // Check for out-of range responses
3028 if (idle_in
> maxTimeout
)
3030 // use standard implementation
3031 idle_in
= IOService::nextIdleTimeout(uptime
,
3032 fDeviceActiveTimestamp
,
3033 fCurrentPowerState
);
3034 } else if (idle_in
< minTimeout
) {
3035 idle_in
= fIdleTimerPeriod
;
3038 IOLockUnlock(fActivityLock
);
3041 clock_interval_to_absolutetime_interval(idle_in
, kSecondScale
, &deadline
);
3042 ADD_ABSOLUTETIME(&deadline
, &uptime
);
3043 pending
= thread_call_enter_delayed(fIdleTimer
, deadline
);
3044 if (pending
) release();
3047 //*********************************************************************************
3048 // idle_timer_expired
3049 //*********************************************************************************
3052 idle_timer_expired (
3053 thread_call_param_t arg0
, thread_call_param_t arg1
)
3055 IOService
* me
= (IOService
*) arg0
;
3058 gIOPMWorkLoop
->runAction(
3059 OSMemberFunctionCast(IOWorkLoop::Action
, me
,
3060 &IOService::idleTimerExpired
),
3066 //*********************************************************************************
3067 // [private] idleTimerExpired
3069 // The idle timer has expired. If there has been activity since the last
3070 // expiration, just restart the timer and return. If there has not been
3071 // activity, switch to the next lower power state and restart the timer.
3072 //*********************************************************************************
3074 void IOService::idleTimerExpired( void )
3076 IOPMRequest
* request
;
3077 bool restartTimer
= true;
3079 if ( !initialized
|| !fIdleTimerPeriod
|| fLockedFlags
.PMStop
)
3082 IOLockLock(fActivityLock
);
3084 // Check for device activity (tickles) over last timer period.
3086 if (fDeviceWasActive
)
3088 // Device was active - do not drop power, restart timer.
3089 fDeviceWasActive
= false;
3091 else if (!fIdleTimerIgnored
)
3093 // No device activity - drop power state by one level.
3094 // Decrement the cached tickle power state when possible.
3095 // This value may be (-1) before activityTickle() is called,
3096 // but the power drop request must be issued regardless.
3098 if (fActivityTicklePowerState
> 0)
3099 fActivityTicklePowerState
--;
3101 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3104 request
->fArg0
= (void *) 0; // power state (irrelevant)
3105 request
->fArg1
= (void *) false; // timer expiration (not tickle)
3106 request
->fArg2
= (void *) false; // regular tickle
3107 submitPMRequest( request
);
3109 // Do not restart timer until after the tickle request has been
3112 restartTimer
= false;
3116 if (fAdvisoryTickled
)
3118 fAdvisoryTickled
= false;
3120 else if (fHasAdvisoryDesire
)
3122 // Want new tickles to turn into pm request after we drop the lock
3123 fAdvisoryTicklePowerState
= kInvalidTicklePowerState
;
3125 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
3128 request
->fArg0
= (void *) 0; // power state (irrelevant)
3129 request
->fArg1
= (void *) false; // timer expiration (not tickle)
3130 request
->fArg2
= (void *) true; // advisory tickle
3131 submitPMRequest( request
);
3133 // Do not restart timer until after the tickle request has been
3136 restartTimer
= false;
3140 IOLockUnlock(fActivityLock
);
3143 start_PM_idle_timer();
3147 //*********************************************************************************
3148 // [deprecated] PM_idle_timer_expiration
3149 //*********************************************************************************
3151 void IOService::PM_idle_timer_expiration ( void )
3155 //*********************************************************************************
3156 // [deprecated] command_received
3157 //*********************************************************************************
3159 void IOService::command_received ( void *statePtr
, void *, void * , void * )
3162 #endif /* !__LP64__ */
3164 //*********************************************************************************
3165 // [public] setAggressiveness
3167 // Pass on the input parameters to all power domain children. All those which are
3168 // power domains will pass it on to their children, etc.
3169 //*********************************************************************************
3171 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
3173 return kIOReturnSuccess
;
3176 //*********************************************************************************
3177 // [public] getAggressiveness
3179 // Called by the user client.
3180 //*********************************************************************************
3182 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
3184 IOPMrootDomain
* rootDomain
= getPMRootDomain();
3187 return kIOReturnNotReady
;
3189 return rootDomain
->getAggressiveness( type
, currentLevel
);
3192 //*********************************************************************************
3193 // [public] getPowerState
3195 //*********************************************************************************
3197 UInt32
IOService::getPowerState ( void )
3202 return fCurrentPowerState
;
3206 //*********************************************************************************
3207 // [deprecated] systemWake
3209 // Pass this to all power domain children. All those which are
3210 // power domains will pass it on to their children, etc.
3211 //*********************************************************************************
3213 IOReturn
IOService::systemWake ( void )
3217 IOPowerConnection
* connection
;
3218 IOService
* theChild
;
3220 iter
= getChildIterator(gIOPowerPlane
);
3223 while ( (next
= iter
->getNextObject()) )
3225 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
3227 if (connection
->getReadyFlag() == false)
3229 PM_LOG3("[%s] %s: connection not ready\n",
3230 getName(), __FUNCTION__
);
3234 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
3237 theChild
->systemWake();
3238 theChild
->release();
3245 if ( fControllingDriver
!= NULL
)
3247 if ( fControllingDriver
->didYouWakeSystem() )
3256 //*********************************************************************************
3257 // [deprecated] temperatureCriticalForZone
3258 //*********************************************************************************
3260 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
3262 IOService
* theParent
;
3265 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
3267 if ( inPlane(gIOPowerPlane
) && !IS_PM_ROOT
)
3269 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
3272 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
3276 theParent
->temperatureCriticalForZone(whichZone
);
3277 theParent
->release();
3283 #endif /* !__LP64__ */
3286 // MARK: Power Change (Common)
3288 //*********************************************************************************
3289 // [private] startPowerChange
3291 // All power state changes starts here.
3292 //*********************************************************************************
3294 IOReturn
IOService::startPowerChange(
3295 IOPMPowerChangeFlags changeFlags
,
3296 IOPMPowerStateIndex powerState
,
3297 IOPMPowerFlags domainFlags
,
3298 IOPowerConnection
* parentConnection
,
3299 IOPMPowerFlags parentFlags
)
3301 PM_ASSERT_IN_GATE();
3302 assert( fMachineState
== kIOPM_Finished
);
3303 assert( powerState
< fNumberOfPowerStates
);
3305 if (powerState
>= fNumberOfPowerStates
)
3306 return IOPMAckImplied
;
3308 fIsPreChange
= true;
3309 PM_ACTION_2(actionPowerChangeOverride
, &powerState
, &changeFlags
);
3311 // Forks to either Driver or Parent initiated power change paths.
3313 fHeadNoteChangeFlags
= changeFlags
;
3314 fHeadNotePowerState
= powerState
;
3315 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
3316 fHeadNoteParentConnection
= NULL
;
3318 if (changeFlags
& kIOPMSelfInitiated
)
3320 if (changeFlags
& kIOPMSynchronize
)
3328 assert(changeFlags
& kIOPMParentInitiated
);
3329 fHeadNoteDomainFlags
= domainFlags
;
3330 fHeadNoteParentFlags
= parentFlags
;
3331 fHeadNoteParentConnection
= parentConnection
;
3332 return ParentChangeStart();
3336 //*********************************************************************************
3337 // [private] notifyInterestedDrivers
3338 //*********************************************************************************
3340 bool IOService::notifyInterestedDrivers ( void )
3342 IOPMinformee
* informee
;
3343 IOPMinformeeList
* list
= fInterestedDrivers
;
3344 DriverCallParam
* param
;
3347 PM_ASSERT_IN_GATE();
3348 assert( fDriverCallParamCount
== 0 );
3349 assert( fHeadNotePendingAcks
== 0 );
3351 fHeadNotePendingAcks
= 0;
3353 count
= list
->numberOfItems();
3355 goto done
; // no interested drivers
3357 // Allocate an array of interested drivers and their return values
3358 // for the callout thread. Everything else is still "owned" by the
3359 // PM work loop, which can run to process acknowledgePowerChange()
3362 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3363 if (count
> fDriverCallParamSlots
)
3365 if (fDriverCallParamSlots
)
3367 assert(fDriverCallParamPtr
);
3368 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3369 fDriverCallParamPtr
= 0;
3370 fDriverCallParamSlots
= 0;
3373 param
= IONew(DriverCallParam
, count
);
3375 goto done
; // no memory
3377 fDriverCallParamPtr
= (void *) param
;
3378 fDriverCallParamSlots
= count
;
3381 informee
= list
->firstInList();
3383 for (IOItemCount i
= 0; i
< count
; i
++)
3385 informee
->timer
= -1;
3386 param
[i
].Target
= informee
;
3388 informee
= list
->nextInList( informee
);
3391 fDriverCallParamCount
= count
;
3392 fHeadNotePendingAcks
= count
;
3394 // Block state machine and wait for callout completion.
3395 assert(!fDriverCallBusy
);
3396 fDriverCallBusy
= true;
3397 thread_call_enter( fDriverCallEntry
);
3401 // Return false if there are no interested drivers or could not schedule
3402 // callout thread due to error.
3406 //*********************************************************************************
3407 // [private] notifyInterestedDriversDone
3408 //*********************************************************************************
3410 void IOService::notifyInterestedDriversDone ( void )
3412 IOPMinformee
* informee
;
3414 DriverCallParam
* param
;
3417 PM_ASSERT_IN_GATE();
3418 assert( fDriverCallBusy
== false );
3419 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3421 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3422 count
= fDriverCallParamCount
;
3426 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3428 informee
= (IOPMinformee
*) param
->Target
;
3429 result
= param
->Result
;
3431 if ((result
== IOPMAckImplied
) || (result
< 0))
3433 // Interested driver return IOPMAckImplied.
3434 // If informee timer is zero, it must have de-registered
3435 // interest during the thread callout. That also drops
3436 // the pending ack count.
3438 if (fHeadNotePendingAcks
&& informee
->timer
)
3439 fHeadNotePendingAcks
--;
3441 informee
->timer
= 0;
3443 else if (informee
->timer
)
3445 assert(informee
->timer
== -1);
3447 // Driver has not acked, and has returned a positive result.
3448 // Enforce a minimum permissible timeout value.
3449 // Make the min value large enough so timeout is less likely
3450 // to occur if a driver misinterpreted that the return value
3451 // should be in microsecond units. And make it large enough
3452 // to be noticeable if a driver neglects to ack.
3454 if (result
< kMinAckTimeoutTicks
)
3455 result
= kMinAckTimeoutTicks
;
3457 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3459 // else, child has already acked or driver has removed interest,
3460 // and head_note_pendingAcks decremented.
3461 // informee may have been removed from the interested drivers list,
3462 // thus the informee must be retained across the callout.
3464 informee
->release();
3467 fDriverCallParamCount
= 0;
3469 if ( fHeadNotePendingAcks
)
3471 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3476 MS_POP(); // pushed by notifyAll()
3478 // If interest acks are outstanding, wait for fHeadNotePendingAcks to become
3479 // zero before notifying children. This enforces the children after interest
3480 // ordering even for async interest clients.
3482 if (!fHeadNotePendingAcks
)
3488 MS_PUSH(fMachineState
);
3489 fMachineState
= kIOPM_NotifyChildrenStart
;
3490 PM_LOG2("%s: %u outstanding async interest\n",
3491 getName(), fHeadNotePendingAcks
);
3495 //*********************************************************************************
3496 // [private] notifyChildren
3497 //*********************************************************************************
3499 void IOService::notifyChildren ( void )
3503 IOPowerConnection
* connection
;
3504 OSArray
* children
= 0;
3505 IOPMrootDomain
* rootDomain
;
3506 bool delayNotify
= false;
3508 if ((fHeadNotePowerState
!= fCurrentPowerState
) &&
3509 (IS_POWER_DROP
== fIsPreChange
) &&
3510 ((rootDomain
= getPMRootDomain()) == this))
3512 rootDomain
->tracePoint( IS_POWER_DROP
?
3513 kIOPMTracePointSleepPowerPlaneDrivers
:
3514 kIOPMTracePointWakePowerPlaneDrivers
);
3517 if (fStrictTreeOrder
)
3518 children
= OSArray::withCapacity(8);
3520 // Sum child power consumption in notifyChild()
3521 fHeadNotePowerArrayEntry
->staticPower
= 0;
3523 iter
= getChildIterator(gIOPowerPlane
);
3526 while ((next
= iter
->getNextObject()))
3528 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3530 if (connection
->getReadyFlag() == false)
3532 PM_LOG3("[%s] %s: connection not ready\n",
3533 getName(), __FUNCTION__
);
3537 // Mechanism to postpone the did-change notification to
3538 // certain power children to order those children last.
3539 // Cannot be used together with strict tree ordering.
3541 if (!fIsPreChange
&&
3542 (connection
->delayChildNotification
) &&
3543 getPMRootDomain()->shouldDelayChildNotification(this))
3547 children
= OSArray::withCapacity(8);
3553 children
->setObject( connection
);
3558 if (!delayNotify
&& children
)
3559 children
->setObject( connection
);
3561 notifyChild( connection
);
3567 if (children
&& (children
->getCount() == 0))
3569 children
->release();
3574 assert(fNotifyChildArray
== 0);
3575 fNotifyChildArray
= children
;
3576 MS_PUSH(fMachineState
);
3580 // Wait for exiting child notifications to complete,
3581 // before notifying the children in the array.
3582 fMachineState
= kIOPM_NotifyChildrenDelayed
;
3583 PM_LOG2("%s: %d children in delayed array\n",
3584 getName(), children
->getCount());
3588 // Notify children in the array one at a time.
3589 fMachineState
= kIOPM_NotifyChildrenOrdered
;
3594 //*********************************************************************************
3595 // [private] notifyChildrenOrdered
3596 //*********************************************************************************
3598 void IOService::notifyChildrenOrdered ( void )
3600 PM_ASSERT_IN_GATE();
3601 assert(fNotifyChildArray
);
3602 assert(fMachineState
== kIOPM_NotifyChildrenOrdered
);
3604 // Notify one child, wait for it to ack, then repeat for next child.
3605 // This is a workaround for some drivers with multiple instances at
3606 // the same branch in the power tree, but the driver is slow to power
3607 // up unless the tree ordering is observed. Problem observed only on
3608 // system wake, not on system sleep.
3610 // We have the ability to power off in reverse child index order.
3611 // That works nicely on some machines, but not on all HW configs.
3613 if (fNotifyChildArray
->getCount())
3615 IOPowerConnection
* connection
;
3616 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3617 notifyChild( connection
);
3618 fNotifyChildArray
->removeObject(0);
3622 fNotifyChildArray
->release();
3623 fNotifyChildArray
= 0;
3625 MS_POP(); // pushed by notifyChildren()
3629 //*********************************************************************************
3630 // [private] notifyChildrenDelayed
3631 //*********************************************************************************
3633 void IOService::notifyChildrenDelayed ( void )
3635 IOPowerConnection
* connection
;
3637 PM_ASSERT_IN_GATE();
3638 assert(fNotifyChildArray
);
3639 assert(fMachineState
== kIOPM_NotifyChildrenDelayed
);
3641 // Wait after all non-delayed children and interested drivers have ack'ed,
3642 // then notify all delayed children. When explicitly cancelled, interest
3643 // acks (and ack timer) may still be outstanding.
3645 for (int i
= 0; ; i
++)
3647 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(i
);
3651 notifyChild( connection
);
3654 PM_LOG2("%s: notified delayed children\n", getName());
3655 fNotifyChildArray
->release();
3656 fNotifyChildArray
= 0;
3658 MS_POP(); // pushed by notifyChildren()
3661 //*********************************************************************************
3662 // [private] notifyAll
3663 //*********************************************************************************
3665 IOReturn
IOService::notifyAll ( uint32_t nextMS
)
3667 // Save the next machine_state to be restored by notifyInterestedDriversDone()
3669 PM_ASSERT_IN_GATE();
3671 fMachineState
= kIOPM_DriverThreadCallDone
;
3672 fDriverCallReason
= fIsPreChange
?
3673 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3675 if (!notifyInterestedDrivers())
3676 notifyInterestedDriversDone();
3678 return IOPMWillAckLater
;
3681 //*********************************************************************************
3682 // [private, static] pmDriverCallout
3684 // Thread call context
3685 //*********************************************************************************
3687 IOReturn
IOService::actionDriverCalloutDone (
3689 void * arg0
, void * arg1
,
3690 void * arg2
, void * arg3
)
3692 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3694 assert( fDriverCallBusy
);
3695 fDriverCallBusy
= false;
3697 assert(gIOPMWorkQueue
);
3698 gIOPMWorkQueue
->signalWorkAvailable();
3700 return kIOReturnSuccess
;
3703 void IOService::pmDriverCallout ( IOService
* from
)
3706 switch (from
->fDriverCallReason
)
3708 case kDriverCallSetPowerState
:
3709 from
->driverSetPowerState();
3712 case kDriverCallInformPreChange
:
3713 case kDriverCallInformPostChange
:
3714 from
->driverInformPowerChange();
3718 panic("IOService::pmDriverCallout bad machine state %x",
3719 from
->fDriverCallReason
);
3722 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3724 /* arg0 */ (void *) from
->pwrMgt
);
3727 //*********************************************************************************
3728 // [private] driverSetPowerState
3730 // Thread call context
3731 //*********************************************************************************
3733 void IOService::driverSetPowerState ( void )
3735 IOPMPowerStateIndex powerState
;
3736 DriverCallParam
* param
;
3737 IOPMDriverCallEntry callEntry
;
3740 uint32_t oldPowerState
= getPowerState();
3742 assert( fDriverCallBusy
);
3743 assert( fDriverCallParamPtr
);
3744 assert( fDriverCallParamCount
== 1 );
3746 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3747 powerState
= fHeadNotePowerState
;
3749 if (assertPMDriverCall(&callEntry
))
3751 OUR_PMLog( kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3752 clock_get_uptime(&fDriverCallStartTime
);
3753 result
= fControllingDriver
->setPowerState( powerState
, this );
3754 clock_get_uptime(&end
);
3755 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3757 deassertPMDriverCall(&callEntry
);
3761 PM_LOG("%s::setPowerState(%p, %lu -> %lu) returned 0x%x\n",
3762 fName
, this, fCurrentPowerState
, powerState
, result
);
3765 #if LOG_SETPOWER_TIMES
3766 if ((result
== IOPMAckImplied
) || (result
< 0))
3770 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
3771 absolutetime_to_nanoseconds(end
, &nsec
);
3772 if (nsec
> LOG_SETPOWER_TIMES
)
3773 PM_LOG("%s::setPowerState(%p, %lu -> %lu) took %d ms\n",
3774 fName
, this, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3776 PMEventDetails
*details
= PMEventDetails::eventDetails(
3777 kIOPMEventTypeSetPowerStateImmediate
, // type
3779 (uintptr_t)this, // owner unique
3780 NULL
, // interest name
3781 (uint8_t)oldPowerState
, // old
3782 (uint8_t)powerState
, // new
3784 NS_TO_US(nsec
)); // usec completion time
3786 getPMRootDomain()->recordAndReleasePMEventGated( details
);
3791 result
= kIOPMAckImplied
;
3793 param
->Result
= result
;
3796 //*********************************************************************************
3797 // [private] driverInformPowerChange
3799 // Thread call context
3800 //*********************************************************************************
3802 void IOService::driverInformPowerChange ( void )
3804 IOPMinformee
* informee
;
3806 DriverCallParam
* param
;
3807 IOPMDriverCallEntry callEntry
;
3808 IOPMPowerFlags powerFlags
;
3809 IOPMPowerStateIndex powerState
;
3814 assert( fDriverCallBusy
);
3815 assert( fDriverCallParamPtr
);
3816 assert( fDriverCallParamCount
);
3818 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3819 count
= fDriverCallParamCount
;
3821 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
3822 powerState
= fHeadNotePowerState
;
3824 for (IOItemCount i
= 0; i
< count
; i
++)
3826 informee
= (IOPMinformee
*) param
->Target
;
3827 driver
= informee
->whatObject
;
3829 if (assertPMDriverCall(&callEntry
, 0, informee
))
3831 if (fDriverCallReason
== kDriverCallInformPreChange
)
3833 OUR_PMLog(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
3834 clock_get_uptime(&informee
->startTime
);
3835 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
3836 clock_get_uptime(&end
);
3837 OUR_PMLog((UInt32
)-kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
3841 OUR_PMLog(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
3842 clock_get_uptime(&informee
->startTime
);
3843 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
3844 clock_get_uptime(&end
);
3845 OUR_PMLog((UInt32
)-kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
3848 deassertPMDriverCall(&callEntry
);
3850 #if LOG_SETPOWER_TIMES
3851 if ((result
== IOPMAckImplied
) || (result
< 0))
3855 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
3856 absolutetime_to_nanoseconds(end
, &nsec
);
3857 if (nsec
> LOG_SETPOWER_TIMES
)
3858 PM_LOG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) took %d ms\n",
3860 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
3861 driver
, fName
, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3863 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
3864 ? kIOPMEventTypePSWillChangeTo
3865 : kIOPMEventTypePSDidChangeTo
;
3867 PMEventDetails
*details
= PMEventDetails::eventDetails(
3870 (uintptr_t)this, // owner unique
3871 driver
->getName(), // interest name
3872 (uint8_t)fCurrentPowerState
, // old
3873 (uint8_t)fHeadNotePowerState
, // new
3875 NS_TO_US(nsec
)); // usec completion time
3877 getPMRootDomain()->recordAndReleasePMEventGated( details
);
3882 result
= kIOPMAckImplied
;
3884 param
->Result
= result
;
3889 //*********************************************************************************
3890 // [private] notifyChild
3892 // Notify a power domain child of an upcoming power change.
3893 // If the object acknowledges the current change, we return TRUE.
3894 //*********************************************************************************
3896 bool IOService::notifyChild ( IOPowerConnection
* theNub
)
3898 IOReturn ret
= IOPMAckImplied
;
3899 unsigned long childPower
;
3900 IOService
* theChild
;
3901 IOPMRequest
* childRequest
;
3902 IOPMPowerChangeFlags requestArg2
;
3905 PM_ASSERT_IN_GATE();
3906 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
3912 // Unless the child handles the notification immediately and returns
3913 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
3914 fHeadNotePendingAcks
++;
3915 theNub
->setAwaitingAck(true);
3917 requestArg2
= fHeadNoteChangeFlags
;
3918 if (fHeadNotePowerState
< fCurrentPowerState
)
3919 requestArg2
|= kIOPMDomainPowerDrop
;
3921 requestType
= fIsPreChange
?
3922 kIOPMRequestTypePowerDomainWillChange
:
3923 kIOPMRequestTypePowerDomainDidChange
;
3925 childRequest
= acquirePMRequest( theChild
, requestType
);
3929 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerFlags
;
3930 childRequest
->fArg1
= (void *) theNub
;
3931 childRequest
->fArg2
= (void *) requestArg2
;
3932 theChild
->submitPMRequest( childRequest
);
3933 ret
= IOPMWillAckLater
;
3937 ret
= IOPMAckImplied
;
3938 fHeadNotePendingAcks
--;
3939 theNub
->setAwaitingAck(false);
3940 childPower
= theChild
->currentPowerConsumption();
3941 if ( childPower
== kIOPMUnknown
)
3943 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
3945 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
3946 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
3950 theChild
->release();
3951 return (IOPMAckImplied
== ret
);
3954 //*********************************************************************************
3955 // [private] notifyControllingDriver
3956 //*********************************************************************************
3958 bool IOService::notifyControllingDriver ( void )
3960 DriverCallParam
* param
;
3962 PM_ASSERT_IN_GATE();
3963 assert( fDriverCallParamCount
== 0 );
3964 assert( fControllingDriver
);
3966 if (fInitialSetPowerState
)
3968 fInitialSetPowerState
= false;
3969 fHeadNoteChangeFlags
|= kIOPMInitialPowerChange
;
3971 // Driver specified flag to skip the inital setPowerState()
3972 if (fHeadNotePowerArrayEntry
->capabilityFlags
& kIOPMInitialDeviceState
)
3978 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3981 param
= IONew(DriverCallParam
, 1);
3983 return false; // no memory
3985 fDriverCallParamPtr
= (void *) param
;
3986 fDriverCallParamSlots
= 1;
3989 param
->Target
= fControllingDriver
;
3990 fDriverCallParamCount
= 1;
3993 // Block state machine and wait for callout completion.
3994 assert(!fDriverCallBusy
);
3995 fDriverCallBusy
= true;
3996 thread_call_enter( fDriverCallEntry
);
4001 //*********************************************************************************
4002 // [private] notifyControllingDriverDone
4003 //*********************************************************************************
4005 void IOService::notifyControllingDriverDone( void )
4007 DriverCallParam
* param
;
4010 PM_ASSERT_IN_GATE();
4011 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4013 assert( fDriverCallBusy
== false );
4014 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4016 if (param
&& fDriverCallParamCount
)
4018 assert(fDriverCallParamCount
== 1);
4020 // the return value from setPowerState()
4021 result
= param
->Result
;
4023 if ((result
== IOPMAckImplied
) || (result
< 0))
4027 else if (fDriverTimer
)
4029 assert(fDriverTimer
== -1);
4031 // Driver has not acked, and has returned a positive result.
4032 // Enforce a minimum permissible timeout value.
4033 // Make the min value large enough so timeout is less likely
4034 // to occur if a driver misinterpreted that the return value
4035 // should be in microsecond units. And make it large enough
4036 // to be noticeable if a driver neglects to ack.
4038 if (result
< kMinAckTimeoutTicks
)
4039 result
= kMinAckTimeoutTicks
;
4041 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4043 // else, child has already acked and driver_timer reset to 0.
4045 fDriverCallParamCount
= 0;
4049 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4054 MS_POP(); // pushed by OurChangeSetPowerState()
4055 fIsPreChange
= false;
4058 //*********************************************************************************
4059 // [private] all_done
4061 // A power change is done.
4062 //*********************************************************************************
4064 void IOService::all_done ( void )
4066 IOPMPowerStateIndex prevPowerState
;
4067 const IOPMPSEntry
* powerStatePtr
;
4068 IOPMDriverCallEntry callEntry
;
4069 uint32_t prevMachineState
= fMachineState
;
4070 bool callAction
= false;
4072 fMachineState
= kIOPM_Finished
;
4074 if ((fHeadNoteChangeFlags
& kIOPMSynchronize
) &&
4075 ((prevMachineState
== kIOPM_Finished
) ||
4076 (prevMachineState
== kIOPM_SyncFinish
)))
4078 // Sync operation and no power change occurred.
4079 // Do not inform driver and clients about this request completion,
4080 // except for the originator (root domain).
4082 PM_ACTION_2(actionPowerChangeDone
,
4083 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4085 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
4087 powerChangeDone(fCurrentPowerState
);
4089 else if (fAdvisoryTickleUsed
)
4091 // Not root domain and advisory tickle target
4092 // Re-adjust power after power tree sync at the 'did' pass
4093 if (!fAdjustPowerScheduled
&&
4094 (fHeadNoteChangeFlags
& kIOPMDomainDidChange
))
4096 IOPMRequest
* request
;
4097 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
4100 submitPMRequest( request
);
4101 fAdjustPowerScheduled
= true;
4110 if ( fHeadNoteChangeFlags
& kIOPMSelfInitiated
)
4112 // could our driver switch to the new state?
4113 if ( !( fHeadNoteChangeFlags
& kIOPMNotDone
) )
4115 trackSystemSleepPreventers(
4116 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4118 // we changed, tell our parent
4119 requestDomainPower(fHeadNotePowerState
);
4121 // yes, did power raise?
4122 if ( fCurrentPowerState
< fHeadNotePowerState
)
4124 // yes, inform clients and apps
4125 tellChangeUp (fHeadNotePowerState
);
4127 prevPowerState
= fCurrentPowerState
;
4129 fCurrentPowerState
= fHeadNotePowerState
;
4131 fPMVars
->myCurrentState
= fCurrentPowerState
;
4133 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, 0);
4134 PM_ACTION_2(actionPowerChangeDone
,
4135 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4138 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4139 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4140 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4141 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4143 // inform subclass policy-maker
4144 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4145 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4147 powerChangeDone(prevPowerState
);
4148 deassertPMDriverCall(&callEntry
);
4151 else if (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)
4153 // changePowerStateWithOverrideTo() was cancelled
4154 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
4158 // parent's power change
4159 if ( fHeadNoteChangeFlags
& kIOPMParentInitiated
)
4161 if (((fHeadNoteChangeFlags
& kIOPMDomainWillChange
) &&
4162 (fCurrentPowerState
>= fHeadNotePowerState
)) ||
4163 ((fHeadNoteChangeFlags
& kIOPMDomainDidChange
) &&
4164 (fCurrentPowerState
< fHeadNotePowerState
)))
4166 trackSystemSleepPreventers(
4167 fCurrentPowerState
, fHeadNotePowerState
, fHeadNoteChangeFlags
);
4170 if ( fCurrentPowerState
< fHeadNotePowerState
)
4172 // yes, inform clients and apps
4173 tellChangeUp (fHeadNotePowerState
);
4176 prevPowerState
= fCurrentPowerState
;
4177 fCurrentPowerState
= fHeadNotePowerState
;
4179 fPMVars
->myCurrentState
= fCurrentPowerState
;
4181 fMaxPowerState
= fControllingDriver
->maxCapabilityForDomainState(fHeadNoteDomainFlags
);
4183 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, 0);
4184 PM_ACTION_2(actionPowerChangeDone
,
4185 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4188 powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4189 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4190 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4191 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4193 // inform subclass policy-maker
4194 if (fPCDFunctionOverride
&& fParentsKnowState
&&
4195 assertPMDriverCall(&callEntry
, kIOPMADC_NoInactiveCheck
))
4197 powerChangeDone(prevPowerState
);
4198 deassertPMDriverCall(&callEntry
);
4203 // When power rises enough to satisfy the tickle's desire for more power,
4204 // the condition preventing idle-timer from dropping power is removed.
4206 if (fCurrentPowerState
>= fIdleTimerMinPowerState
)
4208 fIdleTimerMinPowerState
= 0;
4213 PM_ACTION_2(actionPowerChangeDone
,
4214 fHeadNotePowerState
, fHeadNoteChangeFlags
);
4219 // MARK: Power Change Initiated by Driver
4221 //*********************************************************************************
4222 // [private] OurChangeStart
4224 // Begin the processing of a power change initiated by us.
4225 //*********************************************************************************
4227 void IOService::OurChangeStart ( void )
4229 PM_ASSERT_IN_GATE();
4230 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
4232 // fMaxPowerState is our maximum possible power state based on the current
4233 // power state of our parents. If we are trying to raise power beyond the
4234 // maximum, send an async request for more power to all parents.
4236 if (!IS_PM_ROOT
&& (fMaxPowerState
< fHeadNotePowerState
))
4238 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4239 requestDomainPower(fHeadNotePowerState
);
4244 // Redundant power changes skips to the end of the state machine.
4246 if (!fInitialPowerChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
4251 fInitialPowerChange
= false;
4253 // Change started, but may not complete...
4254 // Can be canceled (power drop) or deferred (power rise).
4256 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4258 // Two separate paths, depending if power is being raised or lowered.
4259 // Lowering power is subject to approval by clients of this service.
4263 fDoNotPowerDown
= false;
4265 // Ask for persmission to drop power state
4266 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
4267 fOutOfBandParameter
= kNotifyApps
;
4268 askChangeDown(fHeadNotePowerState
);
4272 // This service is raising power and parents are able to support the
4273 // new power state. However a parent may have already committed to
4274 // drop power, which might force this object to temporarily drop power.
4275 // This results in "oscillations" before the state machines converge
4276 // to a steady state.
4278 // To prevent this, a child must make a power reservation against all
4279 // parents before raising power. If the reservation fails, indicating
4280 // that the child will be unable to sustain the higher power state,
4281 // then the child will signal the parent to adjust power, and the child
4282 // will defer its power change.
4286 // Reserve parent power necessary to achieve fHeadNotePowerState.
4287 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
4288 if (ret
!= kIOReturnSuccess
)
4290 // Reservation failed, defer power rise.
4291 fHeadNoteChangeFlags
|= kIOPMNotDone
;
4296 OurChangeTellCapabilityWillChange();
4300 //*********************************************************************************
4302 struct IOPMRequestDomainPowerContext
{
4303 IOService
* child
; // the requesting child
4304 IOPMPowerFlags requestPowerFlags
; // power flags requested by child
4308 requestDomainPowerApplier(
4309 IORegistryEntry
* entry
,
4312 IOPowerConnection
* connection
;
4314 IOPMRequestDomainPowerContext
* context
;
4316 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0)
4318 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
4323 context
= (IOPMRequestDomainPowerContext
*) inContext
;
4325 if (connection
->parentKnowsState() && connection
->getReadyFlag())
4327 parent
->requestPowerDomainState(
4328 context
->requestPowerFlags
,
4336 //*********************************************************************************
4337 // [private] requestDomainPower
4338 //*********************************************************************************
4340 IOReturn
IOService::requestDomainPower(
4341 IOPMPowerStateIndex ourPowerState
,
4342 IOOptionBits options
)
4344 IOPMPowerFlags requestPowerFlags
;
4345 IOPMPowerStateIndex maxPowerState
;
4346 IOPMRequestDomainPowerContext context
;
4348 PM_ASSERT_IN_GATE();
4349 assert(ourPowerState
< fNumberOfPowerStates
);
4350 if (ourPowerState
>= fNumberOfPowerStates
)
4351 return kIOReturnBadArgument
;
4353 return kIOReturnSuccess
;
4355 // Fetch the input power flags for the requested power state.
4356 // Parent request is stated in terms of required power flags.
4358 requestPowerFlags
= fPowerStates
[ourPowerState
].inputPowerFlags
;
4360 // Disregard the "previous request" for power reservation.
4362 if (((options
& kReserveDomainPower
) == 0) &&
4363 (fPreviousRequestPowerFlags
== requestPowerFlags
))
4365 // skip if domain already knows our requirements
4368 fPreviousRequestPowerFlags
= requestPowerFlags
;
4370 context
.child
= this;
4371 context
.requestPowerFlags
= requestPowerFlags
;
4372 fHeadNoteDomainTargetFlags
= 0;
4373 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
4375 if (options
& kReserveDomainPower
)
4377 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
4378 fHeadNoteDomainTargetFlags
);
4380 if (maxPowerState
< fHeadNotePowerState
)
4382 PM_LOG1("%s: power desired %u:0x%x got %u:0x%x\n",
4384 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
4385 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
4386 return kIOReturnNoPower
;
4391 return kIOReturnSuccess
;
4394 //*********************************************************************************
4395 // [private] OurSyncStart
4396 //*********************************************************************************
4398 void IOService::OurSyncStart ( void )
4400 PM_ASSERT_IN_GATE();
4402 if (fInitialPowerChange
)
4405 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4407 if (fHeadNoteChangeFlags
& kIOPMNotDone
)
4413 if (fHeadNoteChangeFlags
& kIOPMSyncTellPowerDown
)
4415 fDoNotPowerDown
= false;
4417 // Ask for permission to drop power state
4418 fMachineState
= kIOPM_SyncTellClientsPowerDown
;
4419 fOutOfBandParameter
= kNotifyApps
;
4420 askChangeDown(fHeadNotePowerState
);
4424 // Only inform capability app and clients.
4425 tellSystemCapabilityChange( kIOPM_SyncNotifyWillChange
);
4429 //*********************************************************************************
4430 // [private] OurChangeTellClientsPowerDown
4432 // All applications and kernel clients have acknowledged our permission to drop
4433 // power. Here we notify them that we will lower the power and wait for acks.
4434 //*********************************************************************************
4436 void IOService::OurChangeTellClientsPowerDown ( void )
4438 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
4439 tellChangeDown1(fHeadNotePowerState
);
4442 //*********************************************************************************
4443 // [private] OurChangeTellPriorityClientsPowerDown
4445 // All applications and kernel clients have acknowledged our intention to drop
4446 // power. Here we notify "priority" clients that we are lowering power.
4447 //*********************************************************************************
4449 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
4451 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
4452 tellChangeDown2(fHeadNotePowerState
);
4455 //*********************************************************************************
4456 // [private] OurChangeTellCapabilityWillChange
4458 // Extra stage for root domain to notify apps and drivers about the
4459 // system capability change when raising power state.
4460 //*********************************************************************************
4462 void IOService::OurChangeTellCapabilityWillChange ( void )
4464 if (!IS_ROOT_DOMAIN
)
4465 return OurChangeNotifyInterestedDriversWillChange();
4467 tellSystemCapabilityChange( kIOPM_OurChangeNotifyInterestedDriversWillChange
);
4470 //*********************************************************************************
4471 // [private] OurChangeNotifyInterestedDriversWillChange
4473 // All applications and kernel clients have acknowledged our power state change.
4474 // Here we notify interested drivers pre-change.
4475 //*********************************************************************************
4477 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
4479 IOPMrootDomain
* rootDomain
;
4480 if ((rootDomain
= getPMRootDomain()) == this)
4484 rootDomain
->tracePoint( kIOPMTracePointSleepWillChangeInterests
);
4486 PMEventDetails
*details
= PMEventDetails::eventDetails(
4487 kIOPMEventTypeAppNotificationsFinished
,
4491 rootDomain
->recordAndReleasePMEventGated( details
);
4494 rootDomain
->tracePoint( kIOPMTracePointWakeWillChangeInterests
);
4497 notifyAll( kIOPM_OurChangeSetPowerState
);
4500 //*********************************************************************************
4501 // [private] OurChangeSetPowerState
4503 // Instruct our controlling driver to program the hardware for the power state
4504 // change. Wait for async completions.
4505 //*********************************************************************************
4507 void IOService::OurChangeSetPowerState ( void )
4509 MS_PUSH( kIOPM_OurChangeWaitForPowerSettle
);
4510 fMachineState
= kIOPM_DriverThreadCallDone
;
4511 fDriverCallReason
= kDriverCallSetPowerState
;
4513 if (notifyControllingDriver() == false)
4514 notifyControllingDriverDone();
4517 //*********************************************************************************
4518 // [private] OurChangeWaitForPowerSettle
4520 // Our controlling driver has completed the power state change we initiated.
4521 // Wait for the driver specified settle time to expire.
4522 //*********************************************************************************
4524 void IOService::OurChangeWaitForPowerSettle ( void )
4526 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
4530 //*********************************************************************************
4531 // [private] OurChangeNotifyInterestedDriversDidChange
4533 // Power has settled on a power change we initiated. Here we notify
4534 // all our interested drivers post-change.
4535 //*********************************************************************************
4537 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
4539 IOPMrootDomain
* rootDomain
;
4540 if ((rootDomain
= getPMRootDomain()) == this)
4542 rootDomain
->tracePoint( IS_POWER_DROP
?
4543 kIOPMTracePointSleepDidChangeInterests
:
4544 kIOPMTracePointWakeDidChangeInterests
);
4547 notifyAll( kIOPM_OurChangeTellCapabilityDidChange
);
4550 //*********************************************************************************
4551 // [private] OurChangeTellCapabilityDidChange
4553 // For root domain to notify capability power-change.
4554 //*********************************************************************************
4556 void IOService::OurChangeTellCapabilityDidChange ( void )
4558 if (!IS_ROOT_DOMAIN
)
4559 return OurChangeFinish();
4561 getPMRootDomain()->tracePoint( IS_POWER_DROP
?
4562 kIOPMTracePointSleepCapabilityClients
:
4563 kIOPMTracePointWakeCapabilityClients
);
4565 tellSystemCapabilityChange( kIOPM_OurChangeFinish
);
4568 //*********************************************************************************
4569 // [private] OurChangeFinish
4571 // Done with this self-induced power state change.
4572 //*********************************************************************************
4574 void IOService::OurChangeFinish ( void )
4580 // MARK: Power Change Initiated by Parent
4582 //*********************************************************************************
4583 // [private] ParentChangeStart
4585 // Here we begin the processing of a power change initiated by our parent.
4586 //*********************************************************************************
4588 IOReturn
IOService::ParentChangeStart ( void )
4590 PM_ASSERT_IN_GATE();
4591 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4593 // Power domain is lowering power
4594 if ( fHeadNotePowerState
< fCurrentPowerState
)
4596 // Piggy-back idle timer cancellation on a parent down
4597 if (0 == fHeadNotePowerState
)
4598 ParentChangeCancelIdleTimer(fHeadNotePowerState
);
4600 // TODO: redundant? See handlePowerDomainWillChangeTo()
4601 setParentInfo( fHeadNoteParentFlags
, fHeadNoteParentConnection
, true );
4603 PM_ACTION_2(actionPowerChangeStart
, fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4605 // Tell apps and kernel clients
4606 fInitialPowerChange
= false;
4607 fMachineState
= kIOPM_ParentChangeTellPriorityClientsPowerDown
;
4608 tellChangeDown1(fHeadNotePowerState
);
4609 return IOPMWillAckLater
;
4612 // Power domain is raising power
4613 if ( fHeadNotePowerState
> fCurrentPowerState
)
4615 if ( fDesiredPowerState
> fCurrentPowerState
)
4617 if ( fDesiredPowerState
< fHeadNotePowerState
)
4619 // We power up, but not all the way
4620 fHeadNotePowerState
= fDesiredPowerState
;
4621 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
4622 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4625 // We don't need to change
4626 fHeadNotePowerState
= fCurrentPowerState
;
4627 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
4628 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
4632 if ( fHeadNoteChangeFlags
& kIOPMDomainDidChange
)
4634 if ( fHeadNotePowerState
> fCurrentPowerState
)
4636 PM_ACTION_2(actionPowerChangeStart
,
4637 fHeadNotePowerState
, &fHeadNoteChangeFlags
);
4639 // Parent did change up - start our change up
4640 fInitialPowerChange
= false;
4641 ParentChangeTellCapabilityWillChange();
4642 return IOPMWillAckLater
;
4644 else if (fHeadNoteChangeFlags
& kIOPMSynchronize
)
4646 // We do not need to change power state, but notify
4647 // children to propagate tree synchronization.
4648 fMachineState
= kIOPM_SyncNotifyDidChange
;
4649 fDriverCallReason
= kDriverCallInformPreChange
;
4651 return IOPMWillAckLater
;
4656 return IOPMAckImplied
;
4659 //*********************************************************************************
4660 // [private] ParentChangeTellPriorityClientsPowerDown
4662 // All applications and kernel clients have acknowledged our intention to drop
4663 // power. Here we notify "priority" clients that we are lowering power.
4664 //*********************************************************************************
4666 void IOService::ParentChangeTellPriorityClientsPowerDown ( void )
4668 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversWillChange
;
4669 tellChangeDown2(fHeadNotePowerState
);
4672 //*********************************************************************************
4673 // [private] ParentChangeTellCapabilityWillChange
4675 // All (legacy) applications and kernel clients have acknowledged, extra stage for
4676 // root domain to notify apps and drivers about the system capability change.
4677 //*********************************************************************************
4679 void IOService::ParentChangeTellCapabilityWillChange ( void )
4681 if (!IS_ROOT_DOMAIN
)
4682 return ParentChangeNotifyInterestedDriversWillChange();
4684 tellSystemCapabilityChange( kIOPM_ParentChangeNotifyInterestedDriversWillChange
);
4687 //*********************************************************************************
4688 // [private] ParentChangeNotifyInterestedDriversWillChange
4690 // All applications and kernel clients have acknowledged our power state change.
4691 // Here we notify interested drivers pre-change.
4692 //*********************************************************************************
4694 void IOService::ParentChangeNotifyInterestedDriversWillChange ( void )
4696 notifyAll( kIOPM_ParentChangeSetPowerState
);
4699 //*********************************************************************************
4700 // [private] ParentChangeSetPowerState
4702 // Instruct our controlling driver to program the hardware for the power state
4703 // change. Wait for async completions.
4704 //*********************************************************************************
4706 void IOService::ParentChangeSetPowerState ( void )
4708 MS_PUSH( kIOPM_ParentChangeWaitForPowerSettle
);
4709 fMachineState
= kIOPM_DriverThreadCallDone
;
4710 fDriverCallReason
= kDriverCallSetPowerState
;
4712 if (notifyControllingDriver() == false)
4713 notifyControllingDriverDone();
4716 //*********************************************************************************
4717 // [private] ParentChangeWaitForPowerSettle
4719 // Our controlling driver has completed the power state change initiated by our
4720 // parent. Wait for the driver specified settle time to expire.
4721 //*********************************************************************************
4723 void IOService::ParentChangeWaitForPowerSettle ( void )
4725 fMachineState
= kIOPM_ParentChangeNotifyInterestedDriversDidChange
;
4729 //*********************************************************************************
4730 // [private] ParentChangeNotifyInterestedDriversDidChange
4732 // Power has settled on a power change initiated by our parent. Here we notify
4733 // all our interested drivers post-change.
4734 //*********************************************************************************
4736 void IOService::ParentChangeNotifyInterestedDriversDidChange ( void )
4738 notifyAll( kIOPM_ParentChangeTellCapabilityDidChange
);
4741 //*********************************************************************************
4742 // [private] ParentChangeTellCapabilityDidChange
4744 // For root domain to notify capability power-change.
4745 //*********************************************************************************
4747 void IOService::ParentChangeTellCapabilityDidChange ( void )
4749 if (!IS_ROOT_DOMAIN
)
4750 return ParentChangeAcknowledgePowerChange();
4752 tellSystemCapabilityChange( kIOPM_ParentChangeAcknowledgePowerChange
);
4755 //*********************************************************************************
4756 // [private] ParentAcknowledgePowerChange
4758 // Acknowledge our power parent that our power change is done.
4759 //*********************************************************************************
4761 void IOService::ParentChangeAcknowledgePowerChange ( void )
4763 IORegistryEntry
* nub
;
4766 nub
= fHeadNoteParentConnection
;
4769 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
4772 parent
->acknowledgePowerChange((IOService
*)nub
);
4778 void IOService::ParentChangeCancelIdleTimer( IOPMPowerStateIndex newPowerState
)
4782 bool cancel
= false;
4784 // No ready or idle timer not in use
4785 if (!initialized
|| !fIdleTimerPeriod
|| fLockedFlags
.PMStop
||
4786 !fAdvisoryTickleUsed
)
4789 // Not allowed to induce artifical idle timeout
4790 if (fIdleTimerIgnored
|| fIdleTimerMinPowerState
)
4793 // Idle timer already has no influence
4794 if (!fDesiredPowerState
|| fIdleTimerStopped
)
4797 IOLockLock(fActivityLock
);
4799 if (!fDeviceWasActive
)
4801 // No tickles since the last idle timer expiration.
4802 // Safe to drop the device desire to zero.
4807 // Was tickled since the last idle timer expiration,
4808 // but not in the last minute.
4809 clock_get_uptime(&now
);
4810 SUB_ABSOLUTETIME(&now
, &fDeviceActiveTimestamp
);
4811 absolutetime_to_nanoseconds(now
, &nsec
);
4812 if (nsec
>= kNoTickleCancelWindow
)
4820 // Force the next tickle to raise power state
4821 fActivityTicklePowerState
= kInvalidTicklePowerState
;
4822 fDeviceWasActive
= false;
4825 IOLockUnlock(fActivityLock
);
4829 // cancel idle timer
4830 if (fIdleTimer
&& thread_call_cancel(fIdleTimer
))
4833 updatePowerClient(gIOPMPowerClientDevice
, 0);
4834 computeDesiredState();
4836 fIdleTimerStopped
= true;
4840 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
4841 PM_LOG("%s::%s cancel=%d\n", fName
, __FUNCTION__
, cancel
);
4845 // MARK: Ack and Settle timers
4847 //*********************************************************************************
4848 // [private] settleTimerExpired
4850 // Power has settled after our last change. Notify interested parties that
4851 // there is a new power state.
4852 //*********************************************************************************
4854 void IOService::settleTimerExpired( void )
4857 gIOPMWorkQueue
->signalWorkAvailable();
4860 //*********************************************************************************
4861 // settle_timer_expired
4863 // Holds a retain while the settle timer callout is in flight.
4864 //*********************************************************************************
4867 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
4869 IOService
* me
= (IOService
*) arg0
;
4871 if (gIOPMWorkLoop
&& gIOPMWorkQueue
)
4873 gIOPMWorkLoop
->runAction(
4874 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
4880 //*********************************************************************************
4881 // [private] startSettleTimer
4883 // Calculate a power-settling delay in microseconds and start a timer.
4884 //*********************************************************************************
4886 void IOService::startSettleTimer( void )
4888 AbsoluteTime deadline
;
4889 IOPMPowerStateIndex i
;
4890 uint32_t settleTime
= 0;
4893 PM_ASSERT_IN_GATE();
4895 i
= fCurrentPowerState
;
4898 if ( fHeadNotePowerState
< fCurrentPowerState
)
4900 while ( i
> fHeadNotePowerState
)
4902 settleTime
+= (uint32_t) fPowerStates
[i
].settleDownTime
;
4908 if ( fHeadNotePowerState
> fCurrentPowerState
)
4910 while ( i
< fHeadNotePowerState
)
4912 settleTime
+= (uint32_t) fPowerStates
[i
+1].settleUpTime
;
4920 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
4921 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
4922 if (pending
) release();
4926 //*********************************************************************************
4927 // [private] ackTimerTick
4929 // The acknowledgement timeout periodic timer has ticked.
4930 // If we are awaiting acks for a power change notification,
4931 // we decrement the timer word of each interested driver which hasn't acked.
4932 // If a timer word becomes zero, we pretend the driver aknowledged.
4933 // If we are waiting for the controlling driver to change the power
4934 // state of the hardware, we decrement its timer word, and if it becomes
4935 // zero, we pretend the driver acknowledged.
4937 // Returns true if the timer tick made it possible to advance to the next
4938 // machine state, false otherwise.
4939 //*********************************************************************************
4942 void IOService::ack_timer_ticked ( void )
4946 #endif /* !__LP64__ */
4948 bool IOService::ackTimerTick( void )
4950 IOPMinformee
* nextObject
;
4953 PM_ASSERT_IN_GATE();
4954 switch (fMachineState
) {
4955 case kIOPM_OurChangeWaitForPowerSettle
:
4956 case kIOPM_ParentChangeWaitForPowerSettle
:
4957 // are we waiting for controlling driver to acknowledge?
4958 if ( fDriverTimer
> 0 )
4960 // yes, decrement timer tick
4962 if ( fDriverTimer
== 0 )
4964 // controlling driver is tardy
4965 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
4966 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
4967 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
4968 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
4969 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
4971 #if LOG_SETPOWER_TIMES
4972 PMEventDetails
*details
= PMEventDetails::eventDetails(
4973 kIOPMEventTypeSetPowerStateDelayed
, // type
4975 (uintptr_t)this, // owner unique
4976 NULL
, // interest name
4977 (uint8_t)getPowerState(), // old
4979 kIOReturnTimeout
, // result
4980 NS_TO_US(nsec
)); // usec completion time
4982 getPMRootDomain()->recordAndReleasePMEventGated( details
);
4985 if (gIOKitDebug
& kIOLogDebugPower
)
4987 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
4988 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
4992 // Unblock state machine and pretend driver has acked.
4996 // still waiting, set timer again
5002 case kIOPM_NotifyChildrenStart
:
5003 // are we waiting for interested parties to acknowledge?
5004 if ( fHeadNotePendingAcks
!= 0 )
5006 // yes, go through the list of interested drivers
5007 nextObject
= fInterestedDrivers
->firstInList();
5008 // and check each one
5009 while ( nextObject
!= NULL
)
5011 if ( nextObject
->timer
> 0 )
5013 nextObject
->timer
--;
5014 // this one should have acked by now
5015 if ( nextObject
->timer
== 0 )
5017 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
5018 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
5019 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
5020 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
5021 nextObject
->whatObject
->getName(),
5022 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
5023 nextObject
->whatObject
, fName
, fCurrentPowerState
, fHeadNotePowerState
,
5026 #if LOG_SETPOWER_TIMES
5027 uint16_t logType
= (fDriverCallReason
== kDriverCallInformPreChange
)
5028 ? kIOPMEventTypePSWillChangeTo
5029 : kIOPMEventTypePSDidChangeTo
;
5031 PMEventDetails
*details
= PMEventDetails::eventDetails(
5034 (uintptr_t)this, // owner unique
5035 nextObject
->whatObject
->getName(), // interest name
5036 (uint8_t)fCurrentPowerState
, // old
5037 (uint8_t)fHeadNotePowerState
, // new
5038 kIOReturnTimeout
, // result
5039 NS_TO_US(nsec
)); // usec completion time
5041 getPMRootDomain()->recordAndReleasePMEventGated( details
);
5044 // Pretend driver has acked.
5045 fHeadNotePendingAcks
--;
5048 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
5051 // is that the last?
5052 if ( fHeadNotePendingAcks
== 0 )
5054 // yes, we can continue
5057 // no, set timer again
5063 // TODO: aggreggate this
5064 case kIOPM_OurChangeTellClientsPowerDown
:
5065 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5066 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5067 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
5068 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
5069 case kIOPM_SyncTellClientsPowerDown
:
5070 case kIOPM_SyncTellPriorityClientsPowerDown
:
5071 case kIOPM_SyncNotifyWillChange
:
5072 case kIOPM_TellCapabilityChangeDone
:
5073 // apps didn't respond in time
5074 cleanClientResponses(true);
5075 OUR_PMLog(kPMLogClientTardy
, 0, 1);
5076 // tardy equates to approval
5081 PM_LOG1("%s: unexpected ack timer tick (state = %d)\n",
5082 getName(), fMachineState
);
5088 //*********************************************************************************
5089 // [private] start_ack_timer
5090 //*********************************************************************************
5092 void IOService::start_ack_timer ( void )
5094 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
5097 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
5099 AbsoluteTime deadline
;
5102 clock_interval_to_deadline(interval
, scale
, &deadline
);
5105 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
5106 if (pending
) release();
5109 //*********************************************************************************
5110 // [private] stop_ack_timer
5111 //*********************************************************************************
5113 void IOService::stop_ack_timer ( void )
5117 pending
= thread_call_cancel(fAckTimer
);
5118 if (pending
) release();
5121 //*********************************************************************************
5122 // [static] actionAckTimerExpired
5124 // Inside PM work loop's gate.
5125 //*********************************************************************************
5128 IOService::actionAckTimerExpired (
5130 void * arg0
, void * arg1
,
5131 void * arg2
, void * arg3
)
5133 IOService
* me
= (IOService
*) target
;
5136 // done will be true if the timer tick unblocks the machine state,
5137 // otherwise no need to signal the work loop.
5139 done
= me
->ackTimerTick();
5140 if (done
&& gIOPMWorkQueue
)
5141 gIOPMWorkQueue
->signalWorkAvailable();
5143 return kIOReturnSuccess
;
5146 //*********************************************************************************
5147 // ack_timer_expired
5149 // Thread call function. Holds a retain while the callout is in flight.
5150 //*********************************************************************************
5153 IOService::ack_timer_expired ( thread_call_param_t arg0
, thread_call_param_t arg1
)
5155 IOService
* me
= (IOService
*) arg0
;
5159 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
5165 // MARK: Client Messaging
5167 //*********************************************************************************
5168 // [private] tellSystemCapabilityChange
5169 //*********************************************************************************
5171 void IOService::tellSystemCapabilityChange( uint32_t nextMS
)
5174 fMachineState
= kIOPM_TellCapabilityChangeDone
;
5175 fOutOfBandMessage
= kIOMessageSystemCapabilityChange
;
5179 // Notify app first on pre-change.
5180 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
5184 // Notify kernel clients first on post-change.
5185 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
5188 tellClientsWithResponse( fOutOfBandMessage
);
5191 //*********************************************************************************
5192 // [public] askChangeDown
5194 // Ask registered applications and kernel clients if we can change to a lower
5197 // Subclass can override this to send a different message type. Parameter is
5198 // the destination state number.
5200 // Return true if we don't have to wait for acknowledgements
5201 //*********************************************************************************
5203 bool IOService::askChangeDown ( unsigned long stateNum
)
5205 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
5208 //*********************************************************************************
5209 // [private] tellChangeDown1
5211 // Notify registered applications and kernel clients that we are definitely
5214 // Return true if we don't have to wait for acknowledgements
5215 //*********************************************************************************
5217 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
5219 fOutOfBandParameter
= kNotifyApps
;
5220 return tellChangeDown(stateNum
);
5223 //*********************************************************************************
5224 // [private] tellChangeDown2
5226 // Notify priority clients that we are definitely dropping power.
5228 // Return true if we don't have to wait for acknowledgements
5229 //*********************************************************************************
5231 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
5233 fOutOfBandParameter
= kNotifyPriority
;
5234 return tellChangeDown(stateNum
);
5237 //*********************************************************************************
5238 // [public] tellChangeDown
5240 // Notify registered applications and kernel clients that we are definitely
5243 // Subclass can override this to send a different message type. Parameter is
5244 // the destination state number.
5246 // Return true if we don't have to wait for acknowledgements
5247 //*********************************************************************************
5249 bool IOService::tellChangeDown ( unsigned long stateNum
)
5251 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
5254 //*********************************************************************************
5255 // cleanClientResponses
5257 //*********************************************************************************
5259 static void logAppTimeouts ( OSObject
* object
, void * arg
)
5261 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5263 unsigned int clientIndex
;
5265 if (OSDynamicCast(_IOServiceInterestNotifier
, object
))
5267 // Discover the 'counter' value or index assigned to this client
5268 // when it was notified, by searching for the array index of the
5269 // client in an array holding the cached interested clients.
5271 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
5273 if ((clientIndex
!= (unsigned int) -1) &&
5274 (flag
= context
->responseArray
->getObject(clientIndex
)) &&
5275 (flag
!= kOSBooleanTrue
))
5277 OSString
*logClientID
= NULL
;
5278 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5281 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
5282 clientID
->release();
5285 PM_ERROR(context
->errorLog
, logClientID
? logClientID
->getCStringNoCopy() : "");
5287 // TODO: record message type if possible
5288 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
5289 gIOPMStatsApplicationResponseTimedOut
,
5290 logClientID
? logClientID
->getCStringNoCopy() : "",
5294 logClientID
->release();
5299 void IOService::cleanClientResponses ( bool logErrors
)
5301 if (logErrors
&& fResponseArray
)
5303 switch ( fOutOfBandParameter
) {
5305 case kNotifyCapabilityChangeApps
:
5306 if (fNotifyClientArray
)
5308 IOPMInterestContext context
;
5310 context
.responseArray
= fResponseArray
;
5311 context
.notifyClients
= fNotifyClientArray
;
5312 context
.serialNumber
= fSerialNumber
;
5313 context
.messageType
= kIOMessageCopyClientID
;
5314 context
.notifyType
= kNotifyApps
;
5315 context
.isPreChange
= fIsPreChange
;
5316 context
.enableTracing
= false;
5318 context
.maxTimeRequested
= 0;
5319 context
.stateNumber
= fHeadNotePowerState
;
5320 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5321 context
.changeFlags
= fHeadNoteChangeFlags
;
5322 context
.errorLog
= "PM notification timeout (%s)\n";
5324 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
5329 // kNotifyPriority, kNotifyCapabilityChangePriority
5330 // TODO: identify the priority client that has not acked
5331 PM_ERROR("PM priority notification timeout\n");
5332 if (gIOKitDebug
& kIOLogDebugPower
)
5334 panic("PM priority notification timeout");
5342 fResponseArray
->release();
5343 fResponseArray
= NULL
;
5345 if (fNotifyClientArray
)
5347 fNotifyClientArray
->release();
5348 fNotifyClientArray
= NULL
;
5352 //*********************************************************************************
5353 // [protected] tellClientsWithResponse
5355 // Notify registered applications and kernel clients that we are definitely
5358 // Return true if we don't have to wait for acknowledgements
5359 //*********************************************************************************
5361 bool IOService::tellClientsWithResponse ( int messageType
)
5363 IOPMInterestContext context
;
5364 bool isRootDomain
= IS_ROOT_DOMAIN
;
5366 PM_ASSERT_IN_GATE();
5367 assert( fResponseArray
== NULL
);
5368 assert( fNotifyClientArray
== NULL
);
5370 RD_LOG("tellClientsWithResponse( %s, %d )\n",
5371 getIOMessageString(messageType
), fOutOfBandParameter
);
5373 fResponseArray
= OSArray::withCapacity( 1 );
5374 if (!fResponseArray
)
5377 fResponseArray
->setCapacityIncrement(8);
5378 if (++fSerialNumber
== 0)
5381 context
.responseArray
= fResponseArray
;
5382 context
.notifyClients
= 0;
5383 context
.serialNumber
= fSerialNumber
;
5384 context
.messageType
= messageType
;
5385 context
.notifyType
= fOutOfBandParameter
;
5386 context
.isPreChange
= fIsPreChange
;
5387 context
.enableTracing
= false;
5389 context
.maxTimeRequested
= 0;
5390 context
.stateNumber
= fHeadNotePowerState
;
5391 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5392 context
.changeFlags
= fHeadNoteChangeFlags
;
5393 context
.messageFilter
= (isRootDomain
) ?
5394 OSMemberFunctionCast(
5397 &IOPMrootDomain::systemMessageFilter
) : 0;
5399 switch ( fOutOfBandParameter
) {
5401 applyToInterested( gIOAppPowerStateInterest
,
5402 pmTellAppWithResponse
, (void *) &context
);
5405 (fMachineState
!= kIOPM_OurChangeTellClientsPowerDown
) &&
5406 (fMachineState
!= kIOPM_SyncTellClientsPowerDown
))
5408 // Notify capability app for tellChangeDown1()
5409 // but not for askChangeDown().
5410 context
.notifyType
= kNotifyCapabilityChangeApps
;
5411 context
.messageType
= kIOMessageSystemCapabilityChange
;
5412 applyToInterested( gIOAppPowerStateInterest
,
5413 pmTellCapabilityAppWithResponse
, (void *) &context
);
5414 context
.notifyType
= fOutOfBandParameter
;
5415 context
.messageType
= messageType
;
5417 context
.maxTimeRequested
= k30Seconds
;
5419 applyToInterested( gIOGeneralInterest
,
5420 pmTellClientWithResponse
, (void *) &context
);
5422 fNotifyClientArray
= context
.notifyClients
;
5425 case kNotifyPriority
:
5426 context
.enableTracing
= isRootDomain
;
5427 applyToInterested( gIOPriorityPowerStateInterest
,
5428 pmTellClientWithResponse
, (void *) &context
);
5432 // Notify capability clients for tellChangeDown2().
5433 context
.notifyType
= kNotifyCapabilityChangePriority
;
5434 context
.messageType
= kIOMessageSystemCapabilityChange
;
5435 applyToInterested( gIOPriorityPowerStateInterest
,
5436 pmTellCapabilityClientWithResponse
, (void *) &context
);
5440 case kNotifyCapabilityChangeApps
:
5441 applyToInterested( gIOAppPowerStateInterest
,
5442 pmTellCapabilityAppWithResponse
, (void *) &context
);
5443 fNotifyClientArray
= context
.notifyClients
;
5444 context
.maxTimeRequested
= k30Seconds
;
5447 case kNotifyCapabilityChangePriority
:
5448 applyToInterested( gIOPriorityPowerStateInterest
,
5449 pmTellCapabilityClientWithResponse
, (void *) &context
);
5453 // do we have to wait for somebody?
5454 if ( !checkForDone() )
5456 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
5457 if (context
.enableTracing
)
5458 getPMRootDomain()->traceDetail( context
.maxTimeRequested
/ 1000 );
5459 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
5464 // everybody responded
5467 fResponseArray
->release();
5468 fResponseArray
= NULL
;
5470 if (fNotifyClientArray
)
5472 fNotifyClientArray
->release();
5473 fNotifyClientArray
= NULL
;
5479 //*********************************************************************************
5480 // [static private] pmTellAppWithResponse
5482 // We send a message to an application, and we expect a response, so we compute a
5483 // cookie we can identify the response with.
5484 //*********************************************************************************
5486 void IOService::pmTellAppWithResponse ( OSObject
* object
, void * arg
)
5488 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5489 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5490 uint32_t msgIndex
, msgRef
, msgType
;
5491 OSNumber
*clientID
= NULL
;
5493 boolean_t proc_suspended
= FALSE
;
5494 #if LOG_APP_RESPONSE_TIMES
5498 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5501 if (context
->us
== getPMRootDomain())
5503 if ((clientID
= copyClientIDForNotification(object
, context
)))
5505 uint32_t clientPID
= clientID
->unsigned32BitValue();
5506 clientID
->release();
5507 proc
= proc_find(clientPID
);
5511 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
5516 logClientIDForNotification(object
, context
, "PMTellAppWithResponse - Suspended");
5523 if (context
->messageFilter
&&
5524 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5526 if (kIOLogDebugPower
& gIOKitDebug
)
5528 logClientIDForNotification(object
, context
, "DROP App");
5533 // Create client array (for tracking purposes) only if the service
5534 // has app clients. Usually only root domain does.
5535 if (0 == context
->notifyClients
)
5536 context
->notifyClients
= OSArray::withCapacity( 32 );
5538 msgType
= context
->messageType
;
5539 msgIndex
= context
->responseArray
->getCount();
5540 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5542 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
5543 if (kIOLogDebugPower
& gIOKitDebug
)
5545 logClientIDForNotification(object
, context
, "MESG App");
5548 #if LOG_APP_RESPONSE_TIMES
5550 clock_get_uptime(&now
);
5551 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
5554 context
->responseArray
->setObject(msgIndex
, num
);
5559 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
5561 if (context
->notifyClients
)
5562 context
->notifyClients
->setObject(msgIndex
, object
);
5564 context
->us
->messageClient(msgType
, object
, (void *) msgRef
);
5567 //*********************************************************************************
5568 // [static private] pmTellClientWithResponse
5570 // We send a message to an in-kernel client, and we expect a response,
5571 // so we compute a cookie we can identify the response with.
5572 //*********************************************************************************
5574 void IOService::pmTellClientWithResponse ( OSObject
* object
, void * arg
)
5576 IOPowerStateChangeNotification notify
;
5577 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5578 OSObject
* replied
= kOSBooleanTrue
;
5579 _IOServiceInterestNotifier
* notifier
;
5580 uint32_t msgIndex
, msgRef
, msgType
;
5583 if (context
->messageFilter
&&
5584 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5586 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5587 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5589 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5590 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5591 context
->us
->getName(),
5592 getIOMessageString(context
->messageType
),
5593 object
, n
->handler
);
5598 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5599 msgType
= context
->messageType
;
5600 msgIndex
= context
->responseArray
->getCount();
5601 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5603 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5604 if (gIOKitDebug
& kIOLogPower
) {
5605 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
5606 if (OSDynamicCast(IOService
, object
)) {
5607 const char *who
= ((IOService
*) object
)->getName();
5608 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
5610 else if (notifier
) {
5611 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
5614 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
5616 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5617 context
->us
->getName(),
5618 getIOMessageString(msgType
),
5619 object
, notifier
->handler
);
5622 notify
.powerRef
= (void *)(uintptr_t) msgRef
;
5623 notify
.returnValue
= 0;
5624 notify
.stateNumber
= context
->stateNumber
;
5625 notify
.stateFlags
= context
->stateFlags
;
5627 if (context
->enableTracing
&& (notifier
!= 0))
5629 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
5630 ((msgType
& 0xfff) << 12) |
5631 (((uintptr_t) notifier
->handler
) & 0xfff);
5632 getPMRootDomain()->traceDetail( detail
);
5635 retCode
= context
->us
->messageClient(msgType
, object
, (void *) ¬ify
, sizeof(notify
));
5637 if (kIOReturnSuccess
== retCode
)
5639 if (0 == notify
.returnValue
) {
5640 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
5642 replied
= kOSBooleanFalse
;
5643 if ( notify
.returnValue
> context
->maxTimeRequested
)
5645 if (notify
.returnValue
> kPriorityClientMaxWait
)
5647 context
->maxTimeRequested
= kPriorityClientMaxWait
;
5648 PM_ERROR("%s: client %p returned %llu for %s\n",
5649 context
->us
->getName(),
5650 notifier
? (void *) notifier
->handler
: object
,
5651 (uint64_t) notify
.returnValue
,
5652 getIOMessageString(msgType
));
5655 context
->maxTimeRequested
= notify
.returnValue
;
5659 // not a client of ours
5660 // so we won't be waiting for response
5661 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
5664 context
->responseArray
->setObject(msgIndex
, replied
);
5667 //*********************************************************************************
5668 // [static private] pmTellCapabilityAppWithResponse
5669 //*********************************************************************************
5671 void IOService::pmTellCapabilityAppWithResponse ( OSObject
* object
, void * arg
)
5673 IOPMSystemCapabilityChangeParameters msgArg
;
5674 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5675 OSObject
* replied
= kOSBooleanTrue
;
5676 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5677 uint32_t msgIndex
, msgRef
, msgType
;
5678 #if LOG_APP_RESPONSE_TIMES
5682 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
5685 memset(&msgArg
, 0, sizeof(msgArg
));
5686 if (context
->messageFilter
&&
5687 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, &replied
))
5692 // Create client array (for tracking purposes) only if the service
5693 // has app clients. Usually only root domain does.
5694 if (0 == context
->notifyClients
)
5695 context
->notifyClients
= OSArray::withCapacity( 32 );
5697 msgType
= context
->messageType
;
5698 msgIndex
= context
->responseArray
->getCount();
5699 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5701 OUR_PMLog(kPMLogAppNotify
, msgType
, msgRef
);
5702 if (kIOLogDebugPower
& gIOKitDebug
)
5704 // Log client pid/name and client array index.
5705 OSNumber
* clientID
= NULL
;
5706 OSString
* clientIDString
= NULL
;;
5707 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
5709 clientIDString
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
5712 PM_LOG("%s MESG App(%u) %s, wait %u, %s\n",
5713 context
->us
->getName(),
5714 msgIndex
, getIOMessageString(msgType
),
5715 (replied
!= kOSBooleanTrue
),
5716 clientIDString
? clientIDString
->getCStringNoCopy() : "");
5717 if (clientID
) clientID
->release();
5718 if (clientIDString
) clientIDString
->release();
5721 msgArg
.notifyRef
= msgRef
;
5722 msgArg
.maxWaitForReply
= 0;
5724 if (replied
== kOSBooleanTrue
)
5726 msgArg
.notifyRef
= 0;
5727 context
->responseArray
->setObject(msgIndex
, kOSBooleanTrue
);
5728 if (context
->notifyClients
)
5729 context
->notifyClients
->setObject(msgIndex
, kOSBooleanTrue
);
5733 #if LOG_APP_RESPONSE_TIMES
5735 clock_get_uptime(&now
);
5736 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
5739 context
->responseArray
->setObject(msgIndex
, num
);
5744 context
->responseArray
->setObject(msgIndex
, kOSBooleanFalse
);
5746 if (context
->notifyClients
)
5747 context
->notifyClients
->setObject(msgIndex
, object
);
5750 context
->us
->messageClient(msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
5753 //*********************************************************************************
5754 // [static private] pmTellCapabilityClientWithResponse
5755 //*********************************************************************************
5757 void IOService::pmTellCapabilityClientWithResponse(
5758 OSObject
* object
, void * arg
)
5760 IOPMSystemCapabilityChangeParameters msgArg
;
5761 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5762 OSObject
* replied
= kOSBooleanTrue
;
5763 _IOServiceInterestNotifier
* notifier
;
5764 uint32_t msgIndex
, msgRef
, msgType
;
5767 memset(&msgArg
, 0, sizeof(msgArg
));
5768 if (context
->messageFilter
&&
5769 !context
->messageFilter(context
->us
, object
, context
, &msgArg
, 0))
5771 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5772 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5774 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5775 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5776 context
->us
->getName(),
5777 getIOMessageString(context
->messageType
),
5778 object
, n
->handler
);
5783 notifier
= OSDynamicCast(_IOServiceInterestNotifier
, object
);
5784 msgType
= context
->messageType
;
5785 msgIndex
= context
->responseArray
->getCount();
5786 msgRef
= ((context
->serialNumber
& 0xFFFF) << 16) + (msgIndex
& 0xFFFF);
5788 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
5789 if (gIOKitDebug
& kIOLogPower
) {
5790 OUR_PMLog(kPMLogClientNotify
, msgRef
, msgType
);
5791 if (OSDynamicCast(IOService
, object
)) {
5792 const char *who
= ((IOService
*) object
)->getName();
5793 gPlatform
->PMLog(who
, kPMLogClientNotify
, (uintptr_t) object
, 0);
5795 else if (notifier
) {
5796 OUR_PMLog(kPMLogClientNotify
, (uintptr_t) notifier
->handler
, 0);
5799 if ((kIOLogDebugPower
& gIOKitDebug
) && notifier
)
5801 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5802 context
->us
->getName(),
5803 getIOMessageString(msgType
),
5804 object
, notifier
->handler
);
5807 msgArg
.notifyRef
= msgRef
;
5808 msgArg
.maxWaitForReply
= 0;
5810 if (context
->enableTracing
&& (notifier
!= 0))
5812 uint32_t detail
= ((msgIndex
& 0xff) << 24) |
5813 ((msgType
& 0xfff) << 12) |
5814 (((uintptr_t) notifier
->handler
) & 0xfff);
5815 getPMRootDomain()->traceDetail( detail
);
5818 retCode
= context
->us
->messageClient(
5819 msgType
, object
, (void *) &msgArg
, sizeof(msgArg
));
5821 if ( kIOReturnSuccess
== retCode
)
5823 if ( 0 == msgArg
.maxWaitForReply
)
5825 // client doesn't want time to respond
5826 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, (uintptr_t) object
);
5830 replied
= kOSBooleanFalse
;
5831 if ( msgArg
.maxWaitForReply
> context
->maxTimeRequested
)
5833 if (msgArg
.maxWaitForReply
> kCapabilityClientMaxWait
)
5835 context
->maxTimeRequested
= kCapabilityClientMaxWait
;
5836 PM_ERROR("%s: client %p returned %u for %s\n",
5837 context
->us
->getName(),
5838 notifier
? (void *) notifier
->handler
: object
,
5839 msgArg
.maxWaitForReply
,
5840 getIOMessageString(msgType
));
5843 context
->maxTimeRequested
= msgArg
.maxWaitForReply
;
5849 // not a client of ours
5850 // so we won't be waiting for response
5851 OUR_PMLog(kPMLogClientAcknowledge
, msgRef
, 0);
5854 context
->responseArray
->setObject(msgIndex
, replied
);
5857 //*********************************************************************************
5858 // [public] tellNoChangeDown
5860 // Notify registered applications and kernel clients that we are not
5863 // Subclass can override this to send a different message type. Parameter is
5864 // the aborted destination state number.
5865 //*********************************************************************************
5867 void IOService::tellNoChangeDown ( unsigned long )
5869 return tellClients( kIOMessageDeviceWillNotPowerOff
);
5872 //*********************************************************************************
5873 // [public] tellChangeUp
5875 // Notify registered applications and kernel clients that we are raising power.
5877 // Subclass can override this to send a different message type. Parameter is
5878 // the aborted destination state number.
5879 //*********************************************************************************
5881 void IOService::tellChangeUp ( unsigned long )
5883 return tellClients( kIOMessageDeviceHasPoweredOn
);
5886 //*********************************************************************************
5887 // [protected] tellClients
5889 // Notify registered applications and kernel clients of something.
5890 //*********************************************************************************
5892 void IOService::tellClients ( int messageType
)
5894 IOPMInterestContext context
;
5896 RD_LOG("tellClients( %s )\n", getIOMessageString(messageType
));
5898 memset(&context
, 0, sizeof(context
));
5899 context
.messageType
= messageType
;
5900 context
.isPreChange
= fIsPreChange
;
5902 context
.stateNumber
= fHeadNotePowerState
;
5903 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
5904 context
.changeFlags
= fHeadNoteChangeFlags
;
5905 context
.messageFilter
= (IS_ROOT_DOMAIN
) ?
5906 OSMemberFunctionCast(
5909 &IOPMrootDomain::systemMessageFilter
) : 0;
5911 context
.notifyType
= kNotifyPriority
;
5912 applyToInterested( gIOPriorityPowerStateInterest
,
5913 tellKernelClientApplier
, (void *) &context
);
5915 context
.notifyType
= kNotifyApps
;
5916 applyToInterested( gIOAppPowerStateInterest
,
5917 tellAppClientApplier
, (void *) &context
);
5919 applyToInterested( gIOGeneralInterest
,
5920 tellKernelClientApplier
, (void *) &context
);
5923 //*********************************************************************************
5924 // [private] tellKernelClientApplier
5926 // Message a kernel client.
5927 //*********************************************************************************
5929 static void tellKernelClientApplier ( OSObject
* object
, void * arg
)
5931 IOPowerStateChangeNotification notify
;
5932 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5934 if (context
->messageFilter
&&
5935 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
5937 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5938 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5940 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5941 PM_LOG("%s DROP Client %s, notifier %p, handler %p\n",
5942 context
->us
->getName(),
5943 IOService::getIOMessageString(context
->messageType
),
5944 object
, n
->handler
);
5949 notify
.powerRef
= (void *) 0;
5950 notify
.returnValue
= 0;
5951 notify
.stateNumber
= context
->stateNumber
;
5952 notify
.stateFlags
= context
->stateFlags
;
5954 context
->us
->messageClient(context
->messageType
, object
, ¬ify
, sizeof(notify
));
5956 if ((kIOLogDebugPower
& gIOKitDebug
) &&
5957 (OSDynamicCast(_IOServiceInterestNotifier
, object
)))
5959 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
5960 PM_LOG("%s MESG Client %s, notifier %p, handler %p\n",
5961 context
->us
->getName(),
5962 IOService::getIOMessageString(context
->messageType
),
5963 object
, n
->handler
);
5967 static OSNumber
* copyClientIDForNotification(
5969 IOPMInterestContext
*context
)
5971 OSNumber
*clientID
= NULL
;
5972 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
5976 static void logClientIDForNotification(
5978 IOPMInterestContext
*context
,
5979 const char *logString
)
5981 OSString
*logClientID
= NULL
;
5982 OSNumber
*clientID
= copyClientIDForNotification(object
, context
);
5987 logClientID
= IOCopyLogNameForPID(clientID
->unsigned32BitValue());
5989 PM_LOG("%s %s %s, %s\n",
5990 context
->us
->getName(), logString
,
5991 IOService::getIOMessageString(context
->messageType
),
5992 logClientID
? logClientID
->getCStringNoCopy() : "");
5995 logClientID
->release();
5999 clientID
->release();
6005 static void tellAppClientApplier ( OSObject
* object
, void * arg
)
6007 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
6008 OSNumber
* clientID
= NULL
;
6010 boolean_t proc_suspended
= FALSE
;
6012 if (context
->us
== IOService::getPMRootDomain())
6014 if ((clientID
= copyClientIDForNotification(object
, context
)))
6016 uint32_t clientPID
= clientID
->unsigned32BitValue();
6017 clientID
->release();
6018 proc
= proc_find(clientPID
);
6022 proc_suspended
= get_task_pidsuspended((task_t
) proc
->task
);
6027 logClientIDForNotification(object
, context
, "tellAppClientApplier - Suspended");
6034 if (context
->messageFilter
&&
6035 !context
->messageFilter(context
->us
, object
, context
, 0, 0))
6037 if (kIOLogDebugPower
& gIOKitDebug
)
6039 logClientIDForNotification(object
, context
, "DROP App");
6044 if (kIOLogDebugPower
& gIOKitDebug
)
6046 logClientIDForNotification(object
, context
, "MESG App");
6049 context
->us
->messageClient(context
->messageType
, object
, 0);
6052 //*********************************************************************************
6053 // [private] checkForDone
6054 //*********************************************************************************
6056 bool IOService::checkForDone ( void )
6061 if (fResponseArray
== NULL
) {
6065 for (i
= 0; ; i
++) {
6066 theFlag
= fResponseArray
->getObject(i
);
6068 if (NULL
== theFlag
) {
6072 if (kOSBooleanTrue
!= theFlag
) {
6079 //*********************************************************************************
6080 // [public] responseValid
6081 //*********************************************************************************
6083 bool IOService::responseValid ( uint32_t refcon
, int pid
)
6085 UInt16 serialComponent
;
6086 UInt16 ordinalComponent
;
6089 serialComponent
= (refcon
>> 16) & 0xFFFF;
6090 ordinalComponent
= (refcon
& 0xFFFF);
6092 if ( serialComponent
!= fSerialNumber
)
6097 if ( fResponseArray
== NULL
)
6102 theFlag
= fResponseArray
->getObject(ordinalComponent
);
6110 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
6112 #if LOG_APP_RESPONSE_TIMES
6116 OSString
*name
= IOCopyLogNameForPID(pid
);
6118 clock_get_uptime(&now
);
6119 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
6120 SUB_ABSOLUTETIME(&now
, &start
);
6121 absolutetime_to_nanoseconds(now
, &nsec
);
6123 PMEventDetails
*details
= PMEventDetails::eventDetails(
6124 kIOPMEventTypeAppResponse
, // type
6125 name
? name
->getCStringNoCopy() : "", // who
6126 (uintptr_t)pid
, // owner unique
6127 NULL
, // interest name
6131 NS_TO_US(nsec
)); // usec completion time
6133 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6135 if (kIOLogDebugPower
& gIOKitDebug
)
6137 PM_LOG("Ack(%u) %u ms\n",
6138 (uint32_t) ordinalComponent
,
6143 if (nsec
> LOG_APP_RESPONSE_TIMES
)
6145 PM_LOG("PM response took %d ms (%s)\n", NS_TO_MS(nsec
),
6146 name
? name
->getCStringNoCopy() : "");
6148 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
6150 // TODO: populate the messageType argument
6151 getPMRootDomain()->pmStatsRecordApplicationResponse(
6152 gIOPMStatsApplicationResponseSlow
,
6153 name
? name
->getCStringNoCopy() : "", 0,
6154 NS_TO_MS(nsec
), pid
);
6161 theFlag
= kOSBooleanFalse
;
6164 if ( kOSBooleanFalse
== theFlag
)
6166 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
6172 //*********************************************************************************
6173 // [public] allowPowerChange
6175 // Our power state is about to lower, and we have notified applications
6176 // and kernel clients, and one of them has acknowledged. If this is the last to do
6177 // so, and all acknowledgements are positive, we continue with the power change.
6178 //*********************************************************************************
6180 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
6182 IOPMRequest
* request
;
6187 return kIOReturnSuccess
;
6190 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
6192 return kIOReturnNoMemory
;
6194 request
->fArg0
= (void *) refcon
;
6195 request
->fArg1
= (void *) proc_selfpid();
6196 request
->fArg2
= (void *) 0;
6197 submitPMRequest( request
);
6199 return kIOReturnSuccess
;
6203 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
6205 // [deprecated] public
6206 return kIOReturnUnsupported
;
6208 #endif /* !__LP64__ */
6210 //*********************************************************************************
6211 // [public] cancelPowerChange
6213 // Our power state is about to lower, and we have notified applications
6214 // and kernel clients, and one of them has vetoed the change. If this is the last
6215 // client to respond, we abandon the power change.
6216 //*********************************************************************************
6218 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
6220 IOPMRequest
* request
;
6226 return kIOReturnSuccess
;
6229 name
= IOCopyLogNameForPID(proc_selfpid());
6230 PM_ERROR("PM notification cancel (%s)\n", name
? name
->getCStringNoCopy() : "");
6232 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
6237 return kIOReturnNoMemory
;
6240 request
->fArg0
= (void *) refcon
;
6241 request
->fArg1
= (void *) proc_selfpid();
6242 request
->fArg2
= (void *) name
;
6243 submitPMRequest( request
);
6245 return kIOReturnSuccess
;
6249 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
6251 // [deprecated] public
6252 return kIOReturnUnsupported
;
6255 //*********************************************************************************
6256 // PM_Clamp_Timer_Expired
6258 // called when clamp timer expires...set power state to 0.
6259 //*********************************************************************************
6261 void IOService::PM_Clamp_Timer_Expired ( void )
6265 //*********************************************************************************
6268 // Set to highest available power state for a minimum of duration milliseconds
6269 //*********************************************************************************
6271 void IOService::clampPowerOn ( unsigned long duration
)
6274 #endif /* !__LP64__ */
6277 // MARK: Driver Overrides
6279 //*********************************************************************************
6280 // [public] setPowerState
6282 // Does nothing here. This should be implemented in a subclass driver.
6283 //*********************************************************************************
6285 IOReturn
IOService::setPowerState (
6286 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
6291 //*********************************************************************************
6292 // [public] maxCapabilityForDomainState
6294 // Finds the highest power state in the array whose input power
6295 // requirement is equal to the input parameter. Where a more intelligent
6296 // decision is possible, override this in the subclassed driver.
6297 //*********************************************************************************
6299 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
6303 if (fNumberOfPowerStates
== 0 )
6307 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
6309 if ( (domainState
& fPowerStates
[i
].inputPowerFlags
) ==
6310 fPowerStates
[i
].inputPowerFlags
)
6318 //*********************************************************************************
6319 // [public] initialPowerStateForDomainState
6321 // Finds the highest power state in the array whose input power
6322 // requirement is equal to the input parameter. Where a more intelligent
6323 // decision is possible, override this in the subclassed driver.
6324 //*********************************************************************************
6326 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
6330 if (fNumberOfPowerStates
== 0 )
6334 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
6336 if ( (domainState
& fPowerStates
[i
].inputPowerFlags
) ==
6337 fPowerStates
[i
].inputPowerFlags
)
6345 //*********************************************************************************
6346 // [public] powerStateForDomainState
6348 // Finds the highest power state in the array whose input power
6349 // requirement is equal to the input parameter. Where a more intelligent
6350 // decision is possible, override this in the subclassed driver.
6351 //*********************************************************************************
6353 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
6357 if (fNumberOfPowerStates
== 0 )
6361 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
6363 if ( (domainState
& fPowerStates
[i
].inputPowerFlags
) ==
6364 fPowerStates
[i
].inputPowerFlags
)
6373 //*********************************************************************************
6374 // [deprecated] didYouWakeSystem
6376 // Does nothing here. This should be implemented in a subclass driver.
6377 //*********************************************************************************
6379 bool IOService::didYouWakeSystem ( void )
6383 #endif /* !__LP64__ */
6385 //*********************************************************************************
6386 // [public] powerStateWillChangeTo
6388 // Does nothing here. This should be implemented in a subclass driver.
6389 //*********************************************************************************
6391 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
6393 return kIOPMAckImplied
;
6396 //*********************************************************************************
6397 // [public] powerStateDidChangeTo
6399 // Does nothing here. This should be implemented in a subclass driver.
6400 //*********************************************************************************
6402 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
6404 return kIOPMAckImplied
;
6407 //*********************************************************************************
6408 // [protected] powerChangeDone
6410 // Called from PM work loop thread.
6411 // Does nothing here. This should be implemented in a subclass policy-maker.
6412 //*********************************************************************************
6414 void IOService::powerChangeDone ( unsigned long )
6419 //*********************************************************************************
6420 // [deprecated] newTemperature
6422 // Does nothing here. This should be implemented in a subclass driver.
6423 //*********************************************************************************
6425 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
6429 #endif /* !__LP64__ */
6431 //*********************************************************************************
6432 // [public] systemWillShutdown
6434 // System shutdown and restart notification.
6435 //*********************************************************************************
6437 void IOService::systemWillShutdown( IOOptionBits specifier
)
6439 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
6441 rootDomain
->acknowledgeSystemWillShutdown( this );
6445 // MARK: PM State Machine
6447 //*********************************************************************************
6448 // [private static] acquirePMRequest
6449 //*********************************************************************************
6452 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
6453 IOPMRequest
* active
)
6455 IOPMRequest
* request
;
6459 request
= IOPMRequest::create();
6462 request
->init( target
, requestType
);
6465 IOPMRequest
* root
= active
->getRootRequest();
6466 if (root
) request
->attachRootRequest(root
);
6471 PM_ERROR("%s: No memory for PM request type 0x%x\n",
6472 target
->getName(), (uint32_t) requestType
);
6477 //*********************************************************************************
6478 // [private static] releasePMRequest
6479 //*********************************************************************************
6481 void IOService::releasePMRequest( IOPMRequest
* request
)
6490 //*********************************************************************************
6491 // [private] submitPMRequest
6492 //*********************************************************************************
6494 void IOService::submitPMRequest( IOPMRequest
* request
)
6497 assert( gIOPMReplyQueue
);
6498 assert( gIOPMRequestQueue
);
6500 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6501 (long)request
->getType(), request
,
6502 request
->getTarget(), request
->getTarget()->getName(),
6503 request
->fArg0
, request
->fArg1
, request
->fArg2
);
6505 if (request
->isReplyType())
6506 gIOPMReplyQueue
->queuePMRequest( request
);
6508 gIOPMRequestQueue
->queuePMRequest( request
);
6511 void IOService::submitPMRequest( IOPMRequest
** requests
, IOItemCount count
)
6514 assert( count
> 0 );
6515 assert( gIOPMRequestQueue
);
6517 for (IOItemCount i
= 0; i
< count
; i
++)
6519 IOPMRequest
* req
= requests
[i
];
6520 PM_LOG1("[+ %02lx] %p [%p %s] %p %p %p\n",
6521 (long)req
->getType(), req
,
6522 req
->getTarget(), req
->getTarget()->getName(),
6523 req
->fArg0
, req
->fArg1
, req
->fArg2
);
6526 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
6529 //*********************************************************************************
6530 // [private] servicePMRequestQueue
6532 // Called from IOPMRequestQueue::checkForWork().
6533 //*********************************************************************************
6535 bool IOService::servicePMRequestQueue(
6536 IOPMRequest
* request
,
6537 IOPMRequestQueue
* queue
)
6543 // Work queue will immediately execute the queue'd request if possible.
6544 // If execution blocks, the work queue will wait for a producer signal.
6545 // Only need to signal more when completing attached requests.
6547 more
= gIOPMWorkQueue
->queuePMRequest(request
, pwrMgt
);
6551 // Calling PM without PMinit() is not allowed, fail the request.
6553 PM_LOG("%s: PM not initialized\n", getName());
6554 fAdjustPowerScheduled
= false;
6555 more
= gIOPMFreeQueue
->queuePMRequest(request
);
6556 if (more
) gIOPMWorkQueue
->incrementProducerCount();
6560 //*********************************************************************************
6561 // [private] servicePMFreeQueue
6563 // Called from IOPMCompletionQueue::checkForWork().
6564 //*********************************************************************************
6566 bool IOService::servicePMFreeQueue(
6567 IOPMRequest
* request
,
6568 IOPMCompletionQueue
* queue
)
6570 bool more
= request
->getNextRequest();
6571 IOPMRequest
* root
= request
->getRootRequest();
6573 if (root
&& (root
!= request
))
6576 gIOPMWorkQueue
->incrementProducerCount();
6578 releasePMRequest( request
);
6582 //*********************************************************************************
6583 // [private] retirePMRequest
6585 // Called by IOPMWorkQueue to retire a completed request.
6586 //*********************************************************************************
6588 bool IOService::retirePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
6590 assert(request
&& queue
);
6592 PM_LOG1("[- %02x] %p [%p %s] state %d, busy %d\n",
6593 request
->getType(), request
, this, getName(),
6594 fMachineState
, gIOPMBusyCount
);
6596 // Catch requests created by idleTimerExpired().
6598 if ((request
->getType() == kIOPMRequestTypeActivityTickle
) &&
6599 (request
->fArg1
== (void *) false))
6601 // Idle timer expiration - power drop request completed.
6602 // Restart the idle timer if deviceDesire can go lower, otherwise set
6603 // a flag so we know to restart idle timer when fDeviceDesire > 0.
6605 if (fDeviceDesire
> 0)
6607 fActivityTickleCount
= 0;
6608 clock_get_uptime(&fIdleTimerStartTime
);
6609 start_PM_idle_timer();
6611 else if (fHasAdvisoryDesire
)
6613 start_PM_idle_timer();
6617 fIdleTimerStopped
= true;
6621 // If the request is linked, then Work queue has already incremented its
6624 return (gIOPMFreeQueue
->queuePMRequest( request
));
6627 //*********************************************************************************
6628 // [private] isPMBlocked
6630 // Check if machine state transition is blocked.
6631 //*********************************************************************************
6633 bool IOService::isPMBlocked ( IOPMRequest
* request
, int count
)
6638 if (kIOPM_Finished
== fMachineState
)
6641 if (kIOPM_DriverThreadCallDone
== fMachineState
)
6643 // 5 = kDriverCallInformPreChange
6644 // 6 = kDriverCallInformPostChange
6645 // 7 = kDriverCallSetPowerState
6646 if (fDriverCallBusy
)
6647 reason
= 5 + fDriverCallReason
;
6651 // Waiting on driver's setPowerState() timeout.
6657 // Child or interested driver acks pending.
6658 if (fHeadNotePendingAcks
)
6663 // Waiting on apps or priority power interest clients.
6669 // Waiting on settle timer expiration.
6676 fWaitReason
= reason
;
6682 PM_LOG1("[B %02x] %p [%p %s] state %d, reason %d\n",
6683 request
->getType(), request
, this, getName(),
6684 fMachineState
, reason
);
6693 //*********************************************************************************
6694 // [private] servicePMRequest
6696 // Service a request from our work queue.
6697 //*********************************************************************************
6699 bool IOService::servicePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
6704 assert(request
&& queue
);
6706 while (isPMBlocked(request
, loop
++) == false)
6708 PM_LOG1("[W %02x] %p [%p %s] state %d\n",
6709 request
->getType(), request
, this, getName(), fMachineState
);
6711 gIOPMRequest
= request
;
6714 // Every PM machine states must be handled in one of the cases below.
6716 switch ( fMachineState
)
6718 case kIOPM_Finished
:
6719 executePMRequest( request
);
6722 case kIOPM_OurChangeTellClientsPowerDown
:
6723 // Root domain might self cancel due to assertions.
6726 bool cancel
= (bool) fDoNotPowerDown
;
6727 getPMRootDomain()->askChangeDownDone(
6728 &fHeadNoteChangeFlags
, &cancel
);
6729 fDoNotPowerDown
= cancel
;
6732 // askChangeDown() done, was it vetoed?
6733 if (!fDoNotPowerDown
)
6735 if (IS_ROOT_DOMAIN
) {
6736 PMEventDetails
*details
= PMEventDetails::eventDetails(
6737 kIOPMEventTypeAppNotificationsFinished
,
6742 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6745 // no, we can continue
6746 OurChangeTellClientsPowerDown();
6750 if (IS_ROOT_DOMAIN
) {
6751 PMEventDetails
*details
= PMEventDetails::eventDetails(
6752 kIOPMEventTypeSleepDone
,
6754 1, /* reason: 1 == Ask clients succeeded */
6755 kIOReturnAborted
); /* result */
6757 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6760 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
6761 PM_ERROR("%s: idle cancel\n", fName
);
6762 // yes, rescind the warning
6763 tellNoChangeDown(fHeadNotePowerState
);
6764 // mark the change note un-actioned
6765 fHeadNoteChangeFlags
|= kIOPMNotDone
;
6771 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
6772 // tellChangeDown(kNotifyApps) done, was it cancelled?
6773 if (fDoNotPowerDown
)
6775 if (IS_ROOT_DOMAIN
) {
6776 PMEventDetails
*details
= PMEventDetails::eventDetails(
6777 kIOPMEventTypeSleepDone
,
6779 2, /* reason: 2 == Client cancelled wake */
6780 kIOReturnAborted
); /* result */
6782 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6784 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
6785 PM_ERROR("%s: idle revert\n", fName
);
6786 // no, tell clients we're back in the old state
6787 tellChangeUp(fCurrentPowerState
);
6788 // mark the change note un-actioned
6789 fHeadNoteChangeFlags
|= kIOPMNotDone
;
6795 if (IS_ROOT_DOMAIN
) {
6796 PMEventDetails
*details
= PMEventDetails::eventDetails(
6797 kIOPMEventTypeAppNotificationsFinished
,
6799 2, /* reason: 2 == TellPriorityClientsDone */
6800 kIOReturnSuccess
); /* result */
6802 getPMRootDomain()->recordAndReleasePMEventGated( details
);
6804 // yes, we can continue
6805 OurChangeTellPriorityClientsPowerDown();
6809 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
6810 OurChangeNotifyInterestedDriversWillChange();
6813 case kIOPM_OurChangeSetPowerState
:
6814 OurChangeSetPowerState();
6817 case kIOPM_OurChangeWaitForPowerSettle
:
6818 OurChangeWaitForPowerSettle();
6821 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
6822 OurChangeNotifyInterestedDriversDidChange();
6825 case kIOPM_OurChangeTellCapabilityDidChange
:
6826 OurChangeTellCapabilityDidChange();
6829 case kIOPM_OurChangeFinish
:
6833 case kIOPM_ParentChangeTellPriorityClientsPowerDown
:
6834 ParentChangeTellPriorityClientsPowerDown();
6837 case kIOPM_ParentChangeNotifyInterestedDriversWillChange
:
6838 ParentChangeNotifyInterestedDriversWillChange();
6841 case kIOPM_ParentChangeSetPowerState
:
6842 ParentChangeSetPowerState();
6845 case kIOPM_ParentChangeWaitForPowerSettle
:
6846 ParentChangeWaitForPowerSettle();
6849 case kIOPM_ParentChangeNotifyInterestedDriversDidChange
:
6850 ParentChangeNotifyInterestedDriversDidChange();
6853 case kIOPM_ParentChangeTellCapabilityDidChange
:
6854 ParentChangeTellCapabilityDidChange();
6857 case kIOPM_ParentChangeAcknowledgePowerChange
:
6858 ParentChangeAcknowledgePowerChange();
6861 case kIOPM_DriverThreadCallDone
:
6862 if (fDriverCallReason
== kDriverCallSetPowerState
)
6863 notifyControllingDriverDone();
6865 notifyInterestedDriversDone();
6868 case kIOPM_NotifyChildrenOrdered
:
6869 notifyChildrenOrdered();
6872 case kIOPM_NotifyChildrenDelayed
:
6873 notifyChildrenDelayed();
6876 case kIOPM_NotifyChildrenStart
:
6877 PM_LOG2("%s: kIOPM_NotifyChildrenStart done\n", getName());
6878 MS_POP(); // from notifyInterestedDriversDone()
6882 case kIOPM_SyncTellClientsPowerDown
:
6883 // Root domain might self cancel due to assertions.
6886 bool cancel
= (bool) fDoNotPowerDown
;
6887 getPMRootDomain()->askChangeDownDone(
6888 &fHeadNoteChangeFlags
, &cancel
);
6889 fDoNotPowerDown
= cancel
;
6891 if (!fDoNotPowerDown
)
6893 fMachineState
= kIOPM_SyncTellPriorityClientsPowerDown
;
6894 fOutOfBandParameter
= kNotifyApps
;
6895 tellChangeDown(fHeadNotePowerState
);
6899 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
6900 PM_ERROR("%s: idle cancel\n", fName
);
6901 tellNoChangeDown(fHeadNotePowerState
);
6902 fHeadNoteChangeFlags
|= kIOPMNotDone
;
6907 case kIOPM_SyncTellPriorityClientsPowerDown
:
6908 if (!fDoNotPowerDown
)
6910 fMachineState
= kIOPM_SyncNotifyWillChange
;
6911 fOutOfBandParameter
= kNotifyPriority
;
6912 tellChangeDown(fHeadNotePowerState
);
6916 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
6917 PM_ERROR("%s: idle revert\n", fName
);
6918 tellChangeUp(fCurrentPowerState
);
6919 fHeadNoteChangeFlags
|= kIOPMNotDone
;
6924 case kIOPM_SyncNotifyWillChange
:
6925 if (kIOPMSyncNoChildNotify
& fHeadNoteChangeFlags
)
6927 fMachineState
= kIOPM_SyncFinish
;
6930 fMachineState
= kIOPM_SyncNotifyDidChange
;
6931 fDriverCallReason
= kDriverCallInformPreChange
;
6935 case kIOPM_SyncNotifyDidChange
:
6936 fIsPreChange
= false;
6938 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
6939 fMachineState
= kIOPM_SyncFinish
;
6941 fMachineState
= kIOPM_SyncTellCapabilityDidChange
;
6943 fDriverCallReason
= kDriverCallInformPostChange
;
6947 case kIOPM_SyncTellCapabilityDidChange
:
6948 tellSystemCapabilityChange( kIOPM_SyncFinish
);
6951 case kIOPM_SyncFinish
:
6952 if (fHeadNoteChangeFlags
& kIOPMParentInitiated
)
6953 ParentChangeAcknowledgePowerChange();
6958 case kIOPM_TellCapabilityChangeDone
:
6961 if (fOutOfBandParameter
== kNotifyCapabilityChangePriority
)
6963 MS_POP(); // tellSystemCapabilityChange()
6966 fOutOfBandParameter
= kNotifyCapabilityChangePriority
;
6970 if (fOutOfBandParameter
== kNotifyCapabilityChangeApps
)
6972 MS_POP(); // tellSystemCapabilityChange()
6975 fOutOfBandParameter
= kNotifyCapabilityChangeApps
;
6977 tellClientsWithResponse( fOutOfBandMessage
);
6981 panic("servicePMWorkQueue: unknown machine state %x",
6987 if (fMachineState
== kIOPM_Finished
)
6997 //*********************************************************************************
6998 // [private] executePMRequest
6999 //*********************************************************************************
7001 void IOService::executePMRequest( IOPMRequest
* request
)
7003 assert( kIOPM_Finished
== fMachineState
);
7005 switch (request
->getType())
7007 case kIOPMRequestTypePMStop
:
7008 handlePMstop( request
);
7011 case kIOPMRequestTypeAddPowerChild1
:
7012 addPowerChild1( request
);
7015 case kIOPMRequestTypeAddPowerChild2
:
7016 addPowerChild2( request
);
7019 case kIOPMRequestTypeAddPowerChild3
:
7020 addPowerChild3( request
);
7023 case kIOPMRequestTypeRegisterPowerDriver
:
7024 handleRegisterPowerDriver( request
);
7027 case kIOPMRequestTypeAdjustPowerState
:
7028 fAdjustPowerScheduled
= false;
7032 case kIOPMRequestTypePowerDomainWillChange
:
7033 handlePowerDomainWillChangeTo( request
);
7036 case kIOPMRequestTypePowerDomainDidChange
:
7037 handlePowerDomainDidChangeTo( request
);
7040 case kIOPMRequestTypeRequestPowerState
:
7041 case kIOPMRequestTypeRequestPowerStateOverride
:
7042 handleRequestPowerState( request
);
7045 case kIOPMRequestTypePowerOverrideOnPriv
:
7046 case kIOPMRequestTypePowerOverrideOffPriv
:
7047 handlePowerOverrideChanged( request
);
7050 case kIOPMRequestTypeActivityTickle
:
7051 handleActivityTickle( request
);
7054 case kIOPMRequestTypeSynchronizePowerTree
:
7055 handleSynchronizePowerTree( request
);
7058 case kIOPMRequestTypeSetIdleTimerPeriod
:
7060 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
7062 if ((false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
7064 fActivityTickleCount
= 0;
7065 clock_get_uptime(&fIdleTimerStartTime
);
7066 start_PM_idle_timer();
7071 case kIOPMRequestTypeIgnoreIdleTimer
:
7072 fIdleTimerIgnored
= request
->fArg0
? 1 : 0;
7076 panic("executePMRequest: unknown request type %x", request
->getType());
7080 //*********************************************************************************
7081 // [private] servicePMReplyQueue
7082 //*********************************************************************************
7084 bool IOService::servicePMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
7088 assert( request
&& queue
);
7089 assert( request
->isReplyType() );
7091 PM_LOG1("[A %02x] %p [%p %s] state %d\n",
7092 request
->getType(), request
, this, getName(), fMachineState
);
7094 switch ( request
->getType() )
7096 case kIOPMRequestTypeAllowPowerChange
:
7097 case kIOPMRequestTypeCancelPowerChange
:
7098 // Check if we are expecting this response.
7099 if (responseValid((uint32_t)(uintptr_t) request
->fArg0
,
7100 (int)(uintptr_t) request
->fArg1
))
7102 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
7104 // Clients are not allowed to cancel when kIOPMSkipAskPowerDown
7105 // flag is set. Only root domain will set this flag.
7107 if ((fHeadNoteChangeFlags
& kIOPMSkipAskPowerDown
) == 0)
7109 fDoNotPowerDown
= true;
7111 OSString
* name
= (OSString
*) request
->fArg2
;
7112 getPMRootDomain()->pmStatsRecordApplicationResponse(
7113 gIOPMStatsApplicationResponseCancel
,
7114 name
? name
->getCStringNoCopy() : "", 0,
7115 0, (int)(uintptr_t) request
->fArg1
);
7122 cleanClientResponses(false);
7126 // OSString containing app name in Arg2 must be released.
7127 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
7129 OSObject
* obj
= (OSObject
*) request
->fArg2
;
7130 if (obj
) obj
->release();
7134 case kIOPMRequestTypeAckPowerChange
:
7135 more
= handleAcknowledgePowerChange( request
);
7138 case kIOPMRequestTypeAckSetPowerState
:
7139 if (fDriverTimer
== -1)
7141 // driver acked while setPowerState() call is in-flight.
7142 // take this ack, return value from setPowerState() is irrelevant.
7143 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
7144 (uintptr_t) this, fDriverTimer
);
7147 else if (fDriverTimer
> 0)
7149 // expected ack, stop the timer
7152 #if LOG_SETPOWER_TIMES
7153 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
7154 if (nsec
> LOG_SETPOWER_TIMES
)
7155 PM_LOG("%s::setPowerState(%p, %lu -> %lu) async took %d ms\n",
7156 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
7158 PMEventDetails
*details
= PMEventDetails::eventDetails(
7159 kIOPMEventTypeSetPowerStateDelayed
, // type
7161 (uintptr_t)this, // owner unique
7162 NULL
, // interest name
7163 (uint8_t)getPowerState(), // old
7164 (uint8_t)fHeadNotePowerState
, // new
7166 NS_TO_US(nsec
)); // usec completion time
7168 getPMRootDomain()->recordAndReleasePMEventGated( details
);
7170 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
7177 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
7181 case kIOPMRequestTypeInterestChanged
:
7182 handleInterestChanged( request
);
7186 case kIOPMRequestTypeIdleCancel
:
7187 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
7188 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
7189 || (fMachineState
== kIOPM_SyncTellClientsPowerDown
)
7190 || (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
7192 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
7193 PM_LOG2("%s: cancel from machine state %d\n",
7194 getName(), fMachineState
);
7195 fDoNotPowerDown
= true;
7196 // Stop waiting for app replys.
7197 if ((fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
) ||
7198 (fMachineState
== kIOPM_SyncTellPriorityClientsPowerDown
))
7199 cleanClientResponses(false);
7204 case kIOPMRequestTypeChildNotifyDelayCancel
:
7205 if (fMachineState
== kIOPM_NotifyChildrenDelayed
)
7207 PM_LOG2("%s: delay notify cancelled\n", getName());
7208 notifyChildrenDelayed();
7213 panic("servicePMReplyQueue: unknown reply type %x",
7214 request
->getType());
7217 more
|= gIOPMFreeQueue
->queuePMRequest(request
);
7219 gIOPMWorkQueue
->incrementProducerCount();
7224 //*********************************************************************************
7225 // [private] assertPMDriverCall / deassertPMDriverCall
7226 //*********************************************************************************
7228 bool IOService::assertPMDriverCall(
7229 IOPMDriverCallEntry
* entry
,
7230 IOOptionBits options
,
7231 IOPMinformee
* inform
)
7233 IOService
* target
= 0;
7241 if (fLockedFlags
.PMStop
)
7246 if (((options
& kIOPMADC_NoInactiveCheck
) == 0) && isInactive())
7253 if (!inform
->active
)
7257 target
= inform
->whatObject
;
7258 if (target
->isInactive())
7264 entry
->thread
= current_thread();
7265 entry
->target
= target
;
7266 queue_enter(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7275 void IOService::deassertPMDriverCall( IOPMDriverCallEntry
* entry
)
7277 bool wakeup
= false;
7281 assert( !queue_empty(&fPMDriverCallQueue
) );
7282 queue_remove(&fPMDriverCallQueue
, entry
, IOPMDriverCallEntry
*, link
);
7283 if (fLockedFlags
.PMDriverCallWait
)
7291 PM_LOCK_WAKEUP(&fPMDriverCallQueue
);
7294 void IOService::waitForPMDriverCall( IOService
* target
)
7296 const IOPMDriverCallEntry
* entry
;
7297 thread_t thread
= current_thread();
7298 AbsoluteTime deadline
;
7305 queue_iterate(&fPMDriverCallQueue
, entry
, const IOPMDriverCallEntry
*, link
)
7307 // Target of interested driver call
7308 if (target
&& (target
!= entry
->target
))
7311 if (entry
->thread
== thread
)
7315 PM_LOG("%s: %s(%s) on PM thread\n",
7316 fName
, __FUNCTION__
, target
? target
->getName() : "");
7317 OSReportWithBacktrace("%s: %s(%s) on PM thread\n",
7318 fName
, __FUNCTION__
, target
? target
->getName() : "");
7330 fLockedFlags
.PMDriverCallWait
= true;
7331 clock_interval_to_deadline(15, kSecondScale
, &deadline
);
7332 waitResult
= PM_LOCK_SLEEP(&fPMDriverCallQueue
, deadline
);
7333 fLockedFlags
.PMDriverCallWait
= false;
7334 if (THREAD_TIMED_OUT
== waitResult
)
7336 PM_ERROR("%s: waitForPMDriverCall timeout\n", fName
);
7343 //*********************************************************************************
7344 // [private] Debug helpers
7345 //*********************************************************************************
7347 const char * IOService::getIOMessageString( uint32_t msg
)
7349 #define MSG_ENTRY(x) {x, #x}
7351 static const IONamedValue msgNames
[] = {
7352 MSG_ENTRY( kIOMessageCanDevicePowerOff
),
7353 MSG_ENTRY( kIOMessageDeviceWillPowerOff
),
7354 MSG_ENTRY( kIOMessageDeviceWillNotPowerOff
),
7355 MSG_ENTRY( kIOMessageDeviceHasPoweredOn
),
7356 MSG_ENTRY( kIOMessageCanSystemPowerOff
),
7357 MSG_ENTRY( kIOMessageSystemWillPowerOff
),
7358 MSG_ENTRY( kIOMessageSystemWillNotPowerOff
),
7359 MSG_ENTRY( kIOMessageCanSystemSleep
),
7360 MSG_ENTRY( kIOMessageSystemWillSleep
),
7361 MSG_ENTRY( kIOMessageSystemWillNotSleep
),
7362 MSG_ENTRY( kIOMessageSystemHasPoweredOn
),
7363 MSG_ENTRY( kIOMessageSystemWillRestart
),
7364 MSG_ENTRY( kIOMessageSystemWillPowerOn
),
7365 MSG_ENTRY( kIOMessageSystemCapabilityChange
)
7368 return IOFindNameForValue(msg
, msgNames
);
7372 // MARK: IOPMRequest
7374 //*********************************************************************************
7375 // IOPMRequest Class
7377 // Requests from PM clients, and also used for inter-object messaging within PM.
7378 //*********************************************************************************
7380 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
7382 IOPMRequest
* IOPMRequest::create( void )
7384 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
7385 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
7393 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
7395 if (!IOCommand::init())
7400 fCompletionStatus
= kIOReturnSuccess
;
7408 void IOPMRequest::reset( void )
7410 assert( fWorkWaitCount
== 0 );
7411 assert( fFreeWaitCount
== 0 );
7413 detachNextRequest();
7414 detachRootRequest();
7416 fType
= kIOPMRequestTypeInvalid
;
7418 if (fCompletionAction
)
7420 fCompletionAction(fCompletionTarget
, fCompletionParam
, fCompletionStatus
);
7430 bool IOPMRequest::attachNextRequest( IOPMRequest
* next
)
7436 // Postpone the execution of the next request after
7438 fRequestNext
= next
;
7439 fRequestNext
->fWorkWaitCount
++;
7440 #if LOG_REQUEST_ATTACH
7441 kprintf("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7442 this, (uint32_t) fType
, fRequestNext
,
7443 (uint32_t) fRequestNext
->fType
,
7444 (uint32_t) fRequestNext
->fWorkWaitCount
,
7445 fTarget
->getName());
7452 bool IOPMRequest::detachNextRequest( void )
7458 assert(fRequestNext
->fWorkWaitCount
);
7459 if (fRequestNext
->fWorkWaitCount
)
7460 fRequestNext
->fWorkWaitCount
--;
7461 #if LOG_REQUEST_ATTACH
7462 kprintf("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
7463 this, (uint32_t) fType
, fRequestNext
,
7464 (uint32_t) fRequestNext
->fType
,
7465 (uint32_t) fRequestNext
->fWorkWaitCount
,
7466 fTarget
->getName());
7474 bool IOPMRequest::attachRootRequest( IOPMRequest
* root
)
7480 // Delay the completion of the root request after
7482 fRequestRoot
= root
;
7483 fRequestRoot
->fFreeWaitCount
++;
7484 #if LOG_REQUEST_ATTACH
7485 kprintf("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7486 this, (uint32_t) fType
, fRequestRoot
,
7487 (uint32_t) fRequestRoot
->fType
,
7488 (uint32_t) fRequestRoot
->fFreeWaitCount
,
7489 fTarget
->getName());
7496 bool IOPMRequest::detachRootRequest( void )
7502 assert(fRequestRoot
->fFreeWaitCount
);
7503 if (fRequestRoot
->fFreeWaitCount
)
7504 fRequestRoot
->fFreeWaitCount
--;
7505 #if LOG_REQUEST_ATTACH
7506 kprintf("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
7507 this, (uint32_t) fType
, fRequestRoot
,
7508 (uint32_t) fRequestRoot
->fType
,
7509 (uint32_t) fRequestRoot
->fFreeWaitCount
,
7510 fTarget
->getName());
7519 // MARK: IOPMRequestQueue
7521 //*********************************************************************************
7522 // IOPMRequestQueue Class
7524 // Global queues. Queues are created once and never released.
7525 //*********************************************************************************
7527 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
7529 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
7531 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
7532 if (me
&& !me
->init(inOwner
, inAction
))
7540 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
7542 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
7545 queue_init(&fQueue
);
7546 fLock
= IOLockAlloc();
7547 return (fLock
!= 0);
7550 void IOPMRequestQueue::free( void )
7557 return IOEventSource::free();
7560 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
7564 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
7565 IOLockUnlock(fLock
);
7566 if (workLoop
) signalWorkAvailable();
7570 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
7574 assert(requests
&& count
);
7580 queue_enter(&fQueue
, next
, IOPMRequest
*, fCommandChain
);
7582 IOLockUnlock(fLock
);
7583 if (workLoop
) signalWorkAvailable();
7586 bool IOPMRequestQueue::checkForWork( void )
7588 Action dqAction
= (Action
) action
;
7589 IOPMRequest
* request
;
7593 IOLockLock( fLock
);
7595 while (!queue_empty(&fQueue
))
7597 queue_remove_first( &fQueue
, request
, IOPMRequest
*, fCommandChain
);
7598 IOLockUnlock( fLock
);
7599 target
= request
->getTarget();
7601 more
|= (*dqAction
)( target
, request
, this );
7602 IOLockLock( fLock
);
7605 IOLockUnlock( fLock
);
7610 // MARK: IOPMWorkQueue
7612 //*********************************************************************************
7613 // IOPMWorkQueue Class
7615 // Queue of IOServicePM objects with busy IOPMRequest(s).
7616 //*********************************************************************************
7618 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
7621 IOPMWorkQueue::create( IOService
* inOwner
, Action work
, Action retire
)
7623 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
7624 if (me
&& !me
->init(inOwner
, work
, retire
))
7632 bool IOPMWorkQueue::init( IOService
* inOwner
, Action work
, Action retire
)
7634 if (!work
|| !retire
||
7635 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
7638 queue_init(&fWorkQueue
);
7641 fRetireAction
= retire
;
7642 fConsumerCount
= fProducerCount
= 0;
7647 bool IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
, IOServicePM
* pwrMgt
)
7654 assert( onThread() );
7655 assert( queue_next(&request
->fCommandChain
) ==
7656 queue_prev(&request
->fCommandChain
) );
7660 // Add new request to the tail of the per-service request queue.
7661 // Then immediately check the request queue to minimize latency
7662 // if the queue was empty.
7664 empty
= queue_empty(&pwrMgt
->RequestHead
);
7665 queue_enter(&pwrMgt
->RequestHead
, request
, IOPMRequest
*, fCommandChain
);
7668 more
= checkRequestQueue(&pwrMgt
->RequestHead
, &empty
);
7671 // New Request is blocked, add IOServicePM to work queue.
7672 assert( queue_next(&pwrMgt
->WorkChain
) ==
7673 queue_prev(&pwrMgt
->WorkChain
) );
7675 queue_enter(&fWorkQueue
, pwrMgt
, IOServicePM
*, WorkChain
);
7677 PM_LOG3("IOPMWorkQueue: [%u] added %s@%p to queue\n",
7678 fQueueLength
, pwrMgt
->Name
, pwrMgt
);
7685 bool IOPMWorkQueue::checkRequestQueue( queue_head_t
* queue
, bool * empty
)
7687 IOPMRequest
* request
;
7692 assert(!queue_empty(queue
));
7694 request
= (IOPMRequest
*) queue_first(queue
);
7695 if (request
->isWorkBlocked())
7696 break; // cannot start, blocked on attached request
7698 target
= request
->getTarget();
7699 done
= (*fWorkAction
)( target
, request
, this );
7701 break; // work started, blocked on PM state machine
7703 assert(gIOPMBusyCount
> 0);
7707 queue_remove_first(queue
, request
, IOPMRequest
*, fCommandChain
);
7708 more
|= (*fRetireAction
)( target
, request
, this );
7709 done
= queue_empty(queue
);
7716 // Retired request blocks another request, since the
7717 // blocked request may reside in the work queue, we
7718 // must bump the producer count to avoid work stall.
7725 bool IOPMWorkQueue::checkForWork( void )
7727 IOServicePM
* entry
;
7732 #if WORK_QUEUE_STATS
7733 fStatCheckForWork
++;
7736 // Each producer signal triggers a full iteration over
7737 // all IOServicePM entries in the work queue.
7739 while (fConsumerCount
!= fProducerCount
)
7741 PM_LOG3("IOPMWorkQueue: checkForWork %u %u\n",
7742 fProducerCount
, fConsumerCount
);
7744 fConsumerCount
= fProducerCount
;
7746 #if WORK_QUEUE_STATS
7747 if (queue_empty(&fWorkQueue
))
7753 uint32_t cachedWorkCount
= gIOPMWorkCount
;
7756 entry
= (IOServicePM
*) queue_first(&fWorkQueue
);
7757 while (!queue_end(&fWorkQueue
, (queue_entry_t
) entry
))
7759 more
|= checkRequestQueue(&entry
->RequestHead
, &empty
);
7761 // Get next entry, points to head if current entry is last.
7762 next
= (IOServicePM
*) queue_next(&entry
->WorkChain
);
7764 // if request queue is empty, remove IOServicePM from queue.
7767 assert(fQueueLength
);
7768 if (fQueueLength
) fQueueLength
--;
7769 PM_LOG3("IOPMWorkQueue: [%u] removed %s@%p from queue\n",
7770 fQueueLength
, entry
->Name
, entry
);
7771 queue_remove(&fWorkQueue
, entry
, IOServicePM
*, WorkChain
);
7776 #if WORK_QUEUE_STATS
7777 if (cachedWorkCount
== gIOPMWorkCount
)
7785 void IOPMWorkQueue::signalWorkAvailable( void )
7788 IOEventSource::signalWorkAvailable();
7791 void IOPMWorkQueue::incrementProducerCount( void )
7797 // MARK: IOPMCompletionQueue
7799 //*********************************************************************************
7800 // IOPMCompletionQueue Class
7801 //*********************************************************************************
7803 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
7805 IOPMCompletionQueue
*
7806 IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
7808 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
7809 if (me
&& !me
->init(inOwner
, inAction
))
7817 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
7819 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
7822 queue_init(&fQueue
);
7826 bool IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
7831 // unblock dependent request
7832 more
= request
->detachNextRequest();
7833 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
7837 bool IOPMCompletionQueue::checkForWork( void )
7839 Action dqAction
= (Action
) action
;
7840 IOPMRequest
* request
;
7845 request
= (IOPMRequest
*) queue_first(&fQueue
);
7846 while (!queue_end(&fQueue
, (queue_entry_t
) request
))
7848 next
= (IOPMRequest
*) queue_next(&request
->fCommandChain
);
7849 if (!request
->isFreeBlocked())
7851 queue_remove(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
7852 target
= request
->getTarget();
7854 more
|= (*dqAction
)( target
, request
, this );
7863 // MARK: IOServicePM
7865 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
7867 //*********************************************************************************
7870 // Serialize IOServicePM for debugging.
7871 //*********************************************************************************
7874 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
7876 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
7879 dict
->setObject(key
, num
);
7884 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
)
7886 OSDictionary
* dict
;
7890 if (IdleTimerPeriod
)
7893 #if WORK_QUEUE_STATS
7894 if (gIOPMRootNode
== ControllingDriver
)
7899 dict
= OSDictionary::withDictionary(
7900 PowerClients
, PowerClients
->getCount() + dictSize
);
7902 dict
= OSDictionary::withCapacity(dictSize
);
7906 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
7907 if (NumberOfPowerStates
)
7908 setPMProperty(dict
, "MaxPowerState", NumberOfPowerStates
-1);
7909 if (DesiredPowerState
!= CurrentPowerState
)
7910 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
7911 if (kIOPM_Finished
!= MachineState
)
7912 setPMProperty(dict
, "MachineState", MachineState
);
7913 if (DeviceOverrideEnabled
)
7914 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
7916 if (IdleTimerPeriod
)
7922 clock_get_uptime(&now
);
7924 // The idle timer period in milliseconds.
7925 setPMProperty(dict
, "IdleTimerPeriod", IdleTimerPeriod
* 1000ULL);
7927 // The number of activity tickles recorded since device idle
7928 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
7930 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
7932 // The number of milliseconds since the last activity tickle.
7934 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
7935 absolutetime_to_nanoseconds(delta
, &nsecs
);
7936 setPMProperty(dict
, "TimeSinceLastTickle", NS_TO_MS(nsecs
));
7939 if (AbsoluteTime_to_scalar(&IdleTimerStartTime
))
7941 // The number of milliseconds since the last device idle.
7943 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
7944 absolutetime_to_nanoseconds(delta
, &nsecs
);
7945 setPMProperty(dict
, "TimeSinceDeviceIdle", NS_TO_MS(nsecs
));
7949 #if WORK_QUEUE_STATS
7950 if (gIOPMRootNode
== Owner
)
7952 setPMProperty(dict
, "WQ-CheckForWork",
7953 gIOPMWorkQueue
->fStatCheckForWork
);
7954 setPMProperty(dict
, "WQ-ScanEntries",
7955 gIOPMWorkQueue
->fStatScanEntries
);
7956 setPMProperty(dict
, "WQ-QueueEmpty",
7957 gIOPMWorkQueue
->fStatQueueEmpty
);
7958 setPMProperty(dict
, "WQ-NoWorkDone",
7959 gIOPMWorkQueue
->fStatNoWorkDone
);
7963 if (HasAdvisoryDesire
&& !gIOPMAdvisoryTickleEnabled
)
7965 // Don't report advisory tickle when it has no influence
7966 dict
->removeObject(gIOPMPowerClientAdvisoryTickle
);
7969 ok
= dict
->serialize(s
);
7973 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
7976 bool IOServicePM::serialize( OSSerialize
* s
) const
7978 IOReturn ret
= kIOReturnNotReady
;
7982 ret
= gIOPMWorkLoop
->runAction(
7983 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
7984 (OSObject
*) this, (void *) s
);
7987 return (kIOReturnSuccess
== ret
);
7990 PMEventDetails
* PMEventDetails::eventDetails(uint32_t type
,
7991 const char *ownerName
,
7992 uintptr_t ownerUnique
,
7993 const char *interestName
,
7997 uint32_t elapsedTimeUS
) {
7999 PMEventDetails
*myself
;
8000 myself
= new PMEventDetails
;
8003 myself
->eventType
= type
;
8004 myself
->ownerName
= ownerName
;
8005 myself
->ownerUnique
= ownerUnique
;
8006 myself
->interestName
= interestName
;
8007 myself
->oldState
= oldState
;
8008 myself
->newState
= newState
;
8009 myself
->result
= result
;
8010 myself
->elapsedTimeUS
= elapsedTimeUS
;
8012 myself
->eventClassifier
= kIOPMEventClassDriverEvent
;
8019 PMEventDetails
* PMEventDetails::eventDetails(uint32_t type
,
8024 PMEventDetails
*myself
;
8025 myself
= new PMEventDetails
;
8028 myself
->eventType
= type
;
8029 myself
->uuid
= uuid
;
8030 myself
->reason
= reason
;
8031 myself
->result
= result
;
8033 myself
->eventClassifier
= kIOPMEventClassSystemEvent
;