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@
30 #include <IOKit/assert.h>
31 #include <IOKit/IOKitDebug.h>
32 #include <IOKit/IOLib.h>
33 #include <IOKit/IOMessage.h>
34 #include <IOKit/IOPlatformExpert.h>
35 #include <IOKit/IOService.h>
36 #include <IOKit/IOTimerEventSource.h>
37 #include <IOKit/IOWorkLoop.h>
38 #include <IOKit/IOCommand.h>
40 #include <IOKit/pwr_mgt/IOPMlog.h>
41 #include <IOKit/pwr_mgt/IOPMinformee.h>
42 #include <IOKit/pwr_mgt/IOPMinformeeList.h>
43 #include <IOKit/pwr_mgt/IOPowerConnection.h>
44 #include <IOKit/pwr_mgt/RootDomain.h>
48 // Required for notification instrumentation
49 #include "IOServicePrivate.h"
50 #include "IOServicePMPrivate.h"
51 #include "IOKitKernelInternal.h"
53 static void settle_timer_expired(thread_call_param_t
, thread_call_param_t
);
54 static void tellKernelClientApplier(OSObject
* object
, void * arg
);
55 static void tellAppClientApplier(OSObject
* object
, void * arg
);
57 static uint64_t computeTimeDeltaNS( const AbsoluteTime
* start
)
62 clock_get_uptime(&now
);
63 SUB_ABSOLUTETIME(&now
, start
);
64 absolutetime_to_nanoseconds(now
, &nsec
);
69 OSDefineMetaClassAndStructors(IOPMprot
, OSObject
)
72 //*********************************************************************************
74 //*********************************************************************************
76 static bool gIOPMInitialized
= false;
77 static uint32_t gIOPMBusyCount
= 0;
78 static IOWorkLoop
* gIOPMWorkLoop
= 0;
79 static IOPMRequestQueue
* gIOPMRequestQueue
= 0;
80 static IOPMRequestQueue
* gIOPMReplyQueue
= 0;
81 static IOPMCompletionQueue
* gIOPMFreeQueue
= 0;
82 static IOPMRequest
* gIOPMRequest
= 0;
83 static IOPlatformExpert
* gPlatform
= 0;
84 static IOService
* gIOPMRootNode
= 0;
86 static const OSSymbol
* gIOPMPowerClientDevice
= 0;
87 static const OSSymbol
* gIOPMPowerClientDriver
= 0;
88 static const OSSymbol
* gIOPMPowerClientChildProxy
= 0;
89 static const OSSymbol
* gIOPMPowerClientChildren
= 0;
91 static uint32_t getPMRequestType( void )
93 uint32_t type
= kIOPMRequestTypeInvalid
;
95 type
= gIOPMRequest
->getType();
99 //*********************************************************************************
101 //*********************************************************************************
103 #define PM_ERROR(x...) do { kprintf(x); IOLog(x); } while (false)
104 #define PM_DEBUG(x...) do { kprintf(x); } while (false)
105 #define PM_TRACE(x...) do { \
106 if (kIOLogDebugPower & gIOKitDebug) kprintf(x); } while (false)
108 #define PM_CONNECT(x...)
110 #define PM_ASSERT_IN_GATE(x) \
112 assert(gIOPMWorkLoop->inGate()); \
115 #define PM_LOCK() IOLockLock(fPMLock)
116 #define PM_UNLOCK() IOLockUnlock(fPMLock)
117 #define PM_LOCK_SLEEP(event) IOLockSleep(fPMLock, event, THREAD_UNINT)
118 #define PM_LOCK_WAKEUP(event) IOLockWakeup(fPMLock, event, false)
120 #define ns_per_us 1000
121 #define k30seconds (30*1000000)
122 #define kMinAckTimeoutTicks (10*1000000)
123 #define kIOPMTardyAckSPSKey "IOPMTardyAckSetPowerState"
124 #define kIOPMTardyAckPSCKey "IOPMTardyAckPowerStateChange"
125 #define kPwrMgtKey "IOPowerManagement"
127 #define OUR_PMLog(t, a, b) \
128 do { gPlatform->PMLog( fName, t, a, b); } while(0)
130 #define NS_TO_MS(nsec) ((int)((nsec) / 1000000ULL))
133 #define SUPPORT_IDLE_CANCEL 1
136 #define kNotifyWillChange (true)
137 #define kNotifyDidChange (false)
139 #define kIOPMPowerStateMax 0xFFFFFFFF
141 #define IS_PM_ROOT() (this == gIOPMRootNode)
142 #define IS_POWER_DROP (fHeadNotePowerState < fCurrentPowerState)
143 #define IS_POWER_RISE (fHeadNotePowerState > fCurrentPowerState)
145 // log setPowerStates longer than (ns):
146 #define LOG_SETPOWER_TIMES (50ULL * 1000ULL * 1000ULL)
147 // log app responses longer than (ns):
148 #define LOG_APP_RESPONSE_TIMES (100ULL * 1000ULL * 1000ULL)
149 // use message tracer to log messages longer than (ns):
150 #define LOG_APP_RESPONSE_MSG_TRACER (3 * 1000ULL * 1000ULL * 1000ULL)
152 #define RESERVE_DOMAIN_POWER 1
155 kReserveDomainPower
= 1
158 //*********************************************************************************
160 //*********************************************************************************
163 kIOPM_OurChangeTellClientsPowerDown
= 1,
164 kIOPM_OurChangeTellPriorityClientsPowerDown
= 2,
165 kIOPM_OurChangeNotifyInterestedDriversWillChange
= 3,
166 kIOPM_OurChangeSetPowerState
= 4,
167 kIOPM_OurChangeWaitForPowerSettle
= 5,
168 kIOPM_OurChangeNotifyInterestedDriversDidChange
= 6,
169 kIOPM_OurChangeFinish
= 7,
170 kIOPM_ParentDownTellPriorityClientsPowerDown
= 8,
171 kIOPM_ParentDownNotifyInterestedDriversWillChange
= 9,
173 kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange
= 11,
174 kIOPM_ParentDownSetPowerState
= 12,
175 kIOPM_ParentDownWaitForPowerSettle
= 13,
176 kIOPM_ParentAcknowledgePowerChange
= 14,
177 kIOPM_ParentUpSetPowerState
= 15,
179 kIOPM_ParentUpWaitForSettleTime
= 17,
180 kIOPM_ParentUpNotifyInterestedDriversDidChange
= 18,
183 kIOPM_DriverThreadCallDone
= 21,
184 kIOPM_NotifyChildrenDone
= 22,
185 kIOPM_SyncNotifyDidChange
= 23,
186 kIOPM_SyncFinish
= 24
191 Power Management defines a few roles that drivers can play in their own,
192 and other drivers', power management. We briefly define those here.
194 Many drivers implement their policy maker and power controller within the same
195 IOService object, but that is not required.
198 * Virtual IOService PM methods a "policy maker" may implement
199 * maxCapabilityForDomainState()
200 * initialPowerStateForDomainState()
201 * powerStateForDomainState()
203 * Virtual IOService PM methods a "policy maker" may CALL
206 == Power Controller ==
207 * Virtual IOService PM methods a "power controller" may implement
210 * Virtual IOService PM methods a "power controller" may CALL
212 * registerPowerDriver()
214 =======================
215 There are two different kinds of power state changes.
216 * One is initiated by a subclassed device object which has either decided
217 to change power state, or its controlling driver has suggested it, or
218 some other driver wants to use the idle device and has asked it to become
220 * The second kind of power state change is initiated by the power domain
222 The two are handled through different code paths.
224 We maintain a queue of "change notifications," or change notes.
225 * Usually the queue is empty.
226 * When it isn't, usually there is one change note in it
227 * It's possible to have more than one power state change pending at one
228 time, so a queue is implemented.
230 * The subclass device decides it's idle and initiates a change to a lower
231 power state. This causes interested parties to be notified, but they
232 don't all acknowledge right away. This causes the change note to sit
233 in the queue until all the acks are received. During this time, the
234 device decides it isn't idle anymore and wants to raise power back up
235 again. This change can't be started, however, because the previous one
236 isn't complete yet, so the second one waits in the queue. During this
237 time, the parent decides to lower or raise the power state of the entire
238 power domain and notifies the device, and that notification goes into
239 the queue, too, and can't be actioned until the others are.
242 This is how a power change initiated by the subclass device is handled:
243 -> First, all interested parties are notified of the change via their
244 powerStateWillChangeTo method. If they all don't acknowledge via return
245 code, then we have to wait. If they do, or when they finally all
246 acknowledge via our acknowledgePowerChange method, then we can continue.
247 -> We call the controlling driver, instructing it to change to the new state
248 -> Then we wait for power to settle. If there is no settling-time, or after
250 -> we notify interested parties again, this time via their
251 powerStateDidChangeTo methods.
252 -> When they have all acked, we're done.
253 If we lowered power and don't need the power domain to be in its current power
254 state, we suggest to the parent that it lower the power domain state.
256 == PowerDomainDownInitiated ==
257 How a change to a lower power domain state initiated by the parent is handled:
258 -> First, we figure out what power state we will be in when the new domain
260 -> Then all interested parties are notified that we are moving to that new
262 -> When they have acknowledged, we call the controlling driver to assume
263 that state and we wait for power to settle.
264 -> Then we acknowledge our preparedness to our parent. When all its
265 interested parties have acknowledged,
266 -> it lowers power and then notifies its interested parties again.
267 -> When we get this call, we notify our interested parties that the power
268 state has changed, and when they have all acknowledged, we're done.
270 == PowerDomainUpInitiated ==
271 How a change to a higher power domain state initiated by the parent is handled:
272 -> We figure out what power state we will be in when the new domain state is
274 -> If it is different from our current state we acknowledge the parent.
275 -> When all the parent's interested parties have acknowledged, it raises
276 power in the domain and waits for power to settle.
277 -> Then it notifies everyone that the new state has been reached.
278 -> When we get this call, we call the controlling driver, instructing it to
279 assume the new state, and wait for power to settle.
280 -> Then we notify our interested parties. When they all acknowledge we are
283 In either of the two power domain state cases above, it is possible that we
284 will not be changing state even though the domain is.
286 * A change to a lower domain state may not affect us because we are already
287 in a low enough state,
288 * We will not take advantage of a change to a higher domain state, because
289 we have no need of the higher power. In such cases, there is nothing to
290 do but acknowledge the parent. So when the parent calls our
291 powerDomainWillChange method, and we decide that we will not be changing
292 state, we merely acknowledge the parent, via return code, and wait.
293 When the parent subsequently calls powerStateDidChange, we acknowledge again
294 via return code, and the change is complete.
296 == 4 Paths Through State Machine ==
297 Power state changes are processed in a state machine, and since there are four
298 varieties of power state changes, there are four major paths through the state
301 == 5. No Need To change ==
302 The fourth is nearly trivial. In this path, the parent is changing the domain
303 state, but we are not changing the device state. The change starts when the
304 parent calls powerDomainWillChange. All we do is acknowledge the parent. When
305 the parent calls powerStateDidChange, we acknowledge the parent again, and
308 == 1. OurChange Down == XXX gvdl
309 The first is fairly simple. It starts:
310 * when a power domain child calls requestPowerDomainState and we decide to
311 change power states to accomodate the child,
312 * or if our power-controlling driver calls changePowerStateTo,
313 * or if some other driver which is using our device calls makeUsable,
314 * or if a subclassed object calls changePowerStateToPriv.
315 These are all power changes initiated by us, not forced upon us by the parent.
317 -> We start by notifying interested parties.
318 -> If they all acknowledge via return code, we can go on to state
320 -> Otherwise, we start the ack timer and wait for the stragglers to
321 acknowlege by calling acknowledgePowerChange.
322 -> We move on to state "msSetPowerState" when all the
323 stragglers have acknowledged, or when the ack timer expires on
324 all those which didn't acknowledge.
325 In "msSetPowerState" we call the power-controlling driver to change the
326 power state of the hardware.
327 -> If it returns saying it has done so, we go on to state
328 "msWaitForPowerSettle".
329 -> Otherwise, we have to wait for it, so we set the ack timer and wait.
330 -> When it calls acknowledgeSetPowerState, or when the ack timer
332 In "msWaitForPowerSettle", we look in the power state array to see if
333 there is any settle time required when changing from our current state to the
335 -> If not, we go right away to "msNotifyInterestedDriversDidChange".
336 -> Otherwise, we set the settle timer and wait. When it expires, we move on.
337 In "msNotifyInterestedDriversDidChange" state, we notify all our
338 interested parties via their powerStateDidChange methods that we have finished
339 changing power state.
340 -> If they all acknowledge via return code, we move on to "msFinish".
341 -> Otherwise we set the ack timer and wait. When they have all
342 acknowledged, or when the ack timer has expired for those that didn't,
343 we move on to "msFinish".
344 In "msFinish" we remove the used change note from the head of the queue
345 and start the next one if one exists.
347 == 2. Parent Change Down ==
348 Start at Stage 2 of OurChange Down XXX gvdl
351 Start at Stage 4 of OurChange Down XXX gvdl
353 Note all parent requested changes need to acknowledge the power has changed to the parent when done.
356 //*********************************************************************************
359 // Initialize power management.
360 //*********************************************************************************
362 void IOService::PMinit ( void )
366 if ( !gIOPMInitialized
)
368 gPlatform
= getPlatform();
369 gIOPMWorkLoop
= IOWorkLoop::workLoop();
372 gIOPMRequestQueue
= IOPMRequestQueue::create(
373 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
374 this, &IOService::servicePMRequestQueue
));
376 gIOPMReplyQueue
= IOPMRequestQueue::create(
377 this, OSMemberFunctionCast(IOPMRequestQueue::Action
,
378 this, &IOService::servicePMReplyQueue
));
380 gIOPMFreeQueue
= IOPMCompletionQueue::create(
381 this, OSMemberFunctionCast(IOPMCompletionQueue::Action
,
382 this, &IOService::servicePMFreeQueue
));
384 if (gIOPMWorkLoop
->addEventSource(gIOPMRequestQueue
) !=
387 gIOPMRequestQueue
->release();
388 gIOPMRequestQueue
= 0;
391 if (gIOPMWorkLoop
->addEventSource(gIOPMReplyQueue
) !=
394 gIOPMReplyQueue
->release();
398 if (gIOPMWorkLoop
->addEventSource(gIOPMFreeQueue
) !=
401 gIOPMFreeQueue
->release();
405 gIOPMPowerClientDevice
= OSSymbol::withCStringNoCopy( "DevicePowerState" );
406 gIOPMPowerClientDriver
= OSSymbol::withCStringNoCopy( "DriverPowerState" );
407 gIOPMPowerClientChildProxy
= OSSymbol::withCStringNoCopy( "ChildProxyPowerState" );
408 gIOPMPowerClientChildren
= OSSymbol::withCStringNoCopy( "ChildrenPowerState" );
411 if (gIOPMRequestQueue
&& gIOPMReplyQueue
&& gIOPMFreeQueue
)
412 gIOPMInitialized
= true;
414 if (!gIOPMInitialized
)
417 pwrMgt
= new IOServicePM
;
419 setProperty(kPwrMgtKey
, pwrMgt
);
421 fPMLock
= IOLockAlloc();
422 fInterestedDrivers
= new IOPMinformeeList
;
423 fInterestedDrivers
->initialize();
424 fDesiredPowerState
= 0;
426 fInitialChange
= true;
427 fPreviousRequest
= 0;
428 fDeviceOverrides
= false;
429 fMachineState
= kIOPM_Finished
;
430 fIdleTimerEventSource
= NULL
;
431 fIdleTimerMinPowerState
= 0;
432 fActivityLock
= IOLockAlloc();
433 fStrictTreeOrder
= false;
434 fActivityTicklePowerState
= -1;
435 fControllingDriver
= NULL
;
437 fNumberOfPowerStates
= 0;
438 fCurrentPowerState
= 0;
439 fParentsCurrentPowerFlags
= 0;
442 fParentsKnowState
= false;
444 fResponseArray
= NULL
;
445 fNotifyClientArray
= NULL
;
446 fDoNotPowerDown
= true;
447 fCurrentPowerConsumption
= kIOPMUnknown
;
448 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
450 if (!gIOPMRootNode
&& (getParentEntry(gIOPowerPlane
) == getRegistryRoot()))
452 gIOPMRootNode
= this;
453 fParentsKnowState
= true;
456 fAckTimer
= thread_call_allocate(
457 &IOService::ack_timer_expired
, (thread_call_param_t
)this);
458 fSettleTimer
= thread_call_allocate(
459 &settle_timer_expired
, (thread_call_param_t
)this);
460 fDriverCallEntry
= thread_call_allocate(
461 (thread_call_func_t
) &IOService::pmDriverCallout
, this);
462 assert(fDriverCallEntry
);
465 IOPMprot
* prot
= new IOPMprot
;
469 prot
->ourName
= fName
;
470 prot
->thePlatform
= gPlatform
;
475 pm_vars
= (void *) true;
482 //*********************************************************************************
485 // Free the data created by PMinit. Only called from IOService::free().
486 //*********************************************************************************
488 void IOService::PMfree ( void )
495 assert(fMachineState
== kIOPM_Finished
);
496 assert(fInsertInterestSet
== NULL
);
497 assert(fRemoveInterestSet
== NULL
);
498 assert(fNotifyChildArray
== NULL
);
500 if ( fIdleTimerEventSource
!= NULL
) {
501 fIdleTimerEventSource
->disable();
502 gIOPMWorkLoop
->removeEventSource(fIdleTimerEventSource
);
503 fIdleTimerEventSource
->release();
504 fIdleTimerEventSource
= NULL
;
506 if ( fSettleTimer
) {
507 thread_call_cancel(fSettleTimer
);
508 thread_call_free(fSettleTimer
);
512 thread_call_cancel(fAckTimer
);
513 thread_call_free(fAckTimer
);
516 if ( fDriverCallEntry
) {
517 thread_call_free(fDriverCallEntry
);
518 fDriverCallEntry
= NULL
;
524 if ( fActivityLock
) {
525 IOLockFree(fActivityLock
);
526 fActivityLock
= NULL
;
528 if ( fInterestedDrivers
) {
529 fInterestedDrivers
->release();
530 fInterestedDrivers
= NULL
;
532 if ( fPMWorkQueue
) {
533 gIOPMWorkLoop
->removeEventSource(fPMWorkQueue
);
534 fPMWorkQueue
->release();
537 if (fDriverCallParamSlots
&& fDriverCallParamPtr
) {
538 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
539 fDriverCallParamPtr
= 0;
540 fDriverCallParamSlots
= 0;
542 if ( fResponseArray
) {
543 fResponseArray
->release();
544 fResponseArray
= NULL
;
546 if ( fNotifyClientArray
) {
547 fNotifyClientArray
->release();
548 fNotifyClientArray
= NULL
;
550 if (fPowerStates
&& fNumberOfPowerStates
) {
551 IODelete(fPowerStates
, IOPMPowerState
, fNumberOfPowerStates
);
552 fNumberOfPowerStates
= 0;
556 fPowerClients
->release();
573 //*********************************************************************************
574 // [public] joinPMtree
576 // A policy-maker calls its nub here when initializing, to be attached into
577 // the power management hierarchy. The default function is to call the
578 // platform expert, which knows how to do it. This method is overridden
579 // by a nub subclass which may either know how to do it, or may need to
580 // take other action.
582 // This may be the only "power management" method used in a nub,
583 // meaning it may not be initialized for power management.
584 //*********************************************************************************
586 void IOService::joinPMtree ( IOService
* driver
)
588 IOPlatformExpert
* platform
;
590 platform
= getPlatform();
591 assert(platform
!= 0);
592 platform
->PMRegisterDevice(this, driver
);
596 //*********************************************************************************
597 // [deprecated] youAreRoot
599 // Power Managment is informing us that we are the root power domain.
600 //*********************************************************************************
602 IOReturn
IOService::youAreRoot ( void )
606 #endif /* !__LP64__ */
608 //*********************************************************************************
611 // Immediately stop driver callouts. Schedule an async stop request to detach
613 //*********************************************************************************
615 void IOService::PMstop ( void )
617 IOPMRequest
* request
;
622 // Schedule an async PMstop request, but immediately stop any further
623 // calls to the controlling or interested drivers. This device will
624 // continue to exist in the power plane and participate in power state
625 // changes until the PMstop async request is processed.
628 fLockedFlags
.PMStop
= true;
629 if (fLockedFlags
.DriverCallBusy
)
631 PM_DEBUG("%s: PMstop() driver call busy\n", getName());
633 while (fThreadAssertionCount
!= 0)
635 if (current_thread() == fThreadAssertionThread
)
637 PM_ERROR("%s: PMstop() called from PM thread call\n", getName());
640 // Wait for thread assertions to drop to zero.
641 PM_DEBUG("%s: PMstop() wait for %u thread assertion(s)\n",
642 getName(), fThreadAssertionCount
);
643 PM_LOCK_SLEEP(&fThreadAssertionCount
);
647 request
= acquirePMRequest( this, kIOPMRequestTypePMStop
);
650 PM_TRACE("%s: %p PMstop\n", getName(), this);
651 submitPMRequest( request
);
655 //*********************************************************************************
656 // [private] handlePMstop
658 // Disconnect the node from all parents and children in the power plane.
659 //*********************************************************************************
661 void IOService::handlePMstop ( IOPMRequest
* request
)
665 IOPowerConnection
* connection
;
666 IOService
* theChild
;
667 IOService
* theParent
;
670 PM_TRACE("%s: %p %s start\n", getName(), this, __FUNCTION__
);
672 // remove the property
673 removeProperty(kPwrMgtKey
);
676 iter
= getParentIterator(gIOPowerPlane
);
679 while ( (next
= iter
->getNextObject()) )
681 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
683 theParent
= (IOService
*)connection
->copyParentEntry(gIOPowerPlane
);
686 theParent
->removePowerChild(connection
);
687 theParent
->release();
694 // detach IOConnections
695 detachAbove( gIOPowerPlane
);
697 // no more power state changes
698 fParentsKnowState
= false;
701 iter
= getChildIterator(gIOPowerPlane
);
704 while ( (next
= iter
->getNextObject()) )
706 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
708 theChild
= ((IOService
*)(connection
->copyChildEntry(gIOPowerPlane
)));
711 // detach nub from child
712 connection
->detachFromChild(theChild
, gIOPowerPlane
);
715 // detach us from nub
716 detachFromChild(connection
, gIOPowerPlane
);
722 // Remove all interested drivers from the list, including the power
723 // controlling driver.
725 // Usually, the controlling driver and the policy-maker functionality
726 // are implemented by the same object, and without the deregistration,
727 // the object will be holding an extra retain on itself, and cannot
730 if ( fInterestedDrivers
)
732 IOPMinformeeList
* list
= fInterestedDrivers
;
736 while ((item
= list
->firstInList()))
738 list
->removeFromList(item
->whatObject
);
743 // Tell idleTimerExpired() to ignore idle timer.
744 fIdleTimerPeriod
= 0;
745 if (fIdleTimerEventSource
)
746 fIdleTimerEventSource
->disable();
748 PM_TRACE("%s: %p %s done\n", getName(), this, __FUNCTION__
);
751 //*********************************************************************************
752 // [public] addPowerChild
754 // Power Management is informing us who our children are.
755 //*********************************************************************************
757 IOReturn
IOService::addPowerChild ( IOService
* child
)
759 IOPowerConnection
* connection
= 0;
760 IOPMRequest
* requests
[3] = {0, 0, 0};
765 return kIOReturnBadArgument
;
767 if (!initialized
|| !child
->initialized
)
768 return IOPMNotYetInitialized
;
770 OUR_PMLog( kPMLogAddChild
, (uintptr_t) child
, 0 );
773 // Is this child already one of our children?
775 iter
= child
->getParentIterator( gIOPowerPlane
);
778 IORegistryEntry
* entry
;
781 while ((next
= iter
->getNextObject()))
783 if ((entry
= OSDynamicCast(IORegistryEntry
, next
)) &&
784 isChild(entry
, gIOPowerPlane
))
794 PM_DEBUG("%s: %s (%p) is already a child\n",
795 getName(), child
->getName(), child
);
799 // Add the child to the power plane immediately, but the
800 // joining connection is marked as not ready.
801 // We want the child to appear in the power plane before
802 // returning to the caller, but don't want the caller to
803 // block on the PM work loop.
805 connection
= new IOPowerConnection
;
809 // Create a chain of PM requests to perform the bottom-half
810 // work from the PM work loop.
812 requests
[0] = acquirePMRequest(
814 /* type */ kIOPMRequestTypeAddPowerChild1
);
816 requests
[1] = acquirePMRequest(
818 /* type */ kIOPMRequestTypeAddPowerChild2
);
820 requests
[2] = acquirePMRequest(
822 /* type */ kIOPMRequestTypeAddPowerChild3
);
824 if (!requests
[0] || !requests
[1] || !requests
[2])
827 requests
[0]->attachNextRequest( requests
[1] );
828 requests
[1]->attachNextRequest( requests
[2] );
831 connection
->start(this);
832 connection
->setAwaitingAck(false);
833 connection
->setReadyFlag(false);
835 attachToChild( connection
, gIOPowerPlane
);
836 connection
->attachToChild( child
, gIOPowerPlane
);
838 // connection needs to be released
839 requests
[0]->fArg0
= connection
;
840 requests
[1]->fArg0
= connection
;
841 requests
[2]->fArg0
= connection
;
843 submitPMRequest( requests
, 3 );
844 return kIOReturnSuccess
;
848 if (connection
) connection
->release();
849 if (requests
[0]) releasePMRequest(requests
[0]);
850 if (requests
[1]) releasePMRequest(requests
[1]);
851 if (requests
[2]) releasePMRequest(requests
[2]);
853 // Silent failure, to prevent platform drivers from adding the child
854 // to the root domain.
856 return kIOReturnSuccess
;
859 //*********************************************************************************
860 // [private] addPowerChild1
862 // Step 1/3 of adding a power child. Called on the power parent.
863 //*********************************************************************************
865 void IOService::addPowerChild1 ( IOPMRequest
* request
)
867 unsigned long tempDesire
= 0;
869 // Make us temporary usable before adding the child.
872 OUR_PMLog( kPMLogMakeUsable
, kPMLogMakeUsable
, 0 );
874 if (fControllingDriver
&& inPlane(gIOPowerPlane
) && fParentsKnowState
)
876 tempDesire
= fNumberOfPowerStates
- 1;
879 if (tempDesire
&& (IS_PM_ROOT() || (fMaxCapability
>= tempDesire
)))
881 adjustPowerState(tempDesire
);
885 //*********************************************************************************
886 // [private] addPowerChild2
888 // Step 2/3 of adding a power child. Called on the joining child.
889 // Execution blocked behind addPowerChild1.
890 //*********************************************************************************
892 void IOService::addPowerChild2 ( IOPMRequest
* request
)
894 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
896 IOPMPowerFlags powerFlags
;
898 unsigned long powerState
;
899 unsigned long tempDesire
;
902 parent
= (IOService
*) connection
->getParentEntry(gIOPowerPlane
);
904 if (!parent
|| !inPlane(gIOPowerPlane
))
906 PM_DEBUG("%s: addPowerChild2 not in power plane\n", getName());
910 // Parent will be waiting for us to complete this stage.
911 // It is safe to directly access parent's vars.
913 knowsState
= (parent
->fPowerStates
) && (parent
->fParentsKnowState
);
914 powerState
= parent
->fCurrentPowerState
;
917 powerFlags
= parent
->fPowerStates
[powerState
].outputPowerCharacter
;
921 // Set our power parent.
923 OUR_PMLog(kPMLogSetParent
, knowsState
, powerFlags
);
925 setParentInfo( powerFlags
, connection
, knowsState
);
927 connection
->setReadyFlag(true);
929 if ( fControllingDriver
&& fParentsKnowState
)
931 fMaxCapability
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
932 // initially change into the state we are already in
933 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
934 fPreviousRequest
= 0xffffffff;
935 adjustPowerState(tempDesire
);
938 #if ROOT_DOMAIN_RUN_STATES
939 getPMRootDomain()->tagPowerPlaneService(this, &fRootDomainState
);
943 //*********************************************************************************
944 // [private] addPowerChild3
946 // Step 3/3 of adding a power child. Called on the parent.
947 // Execution blocked behind addPowerChild2.
948 //*********************************************************************************
950 void IOService::addPowerChild3 ( IOPMRequest
* request
)
952 IOPowerConnection
* connection
= (IOPowerConnection
*) request
->fArg0
;
954 IOPMrootDomain
* rootDomain
= getPMRootDomain();
957 child
= (IOService
*) connection
->getChildEntry(gIOPowerPlane
);
959 if (child
&& inPlane(gIOPowerPlane
))
961 if (child
->getProperty("IOPMStrictTreeOrder"))
963 PM_DEBUG("%s: strict PM order enforced\n", getName());
964 fStrictTreeOrder
= true;
968 rootDomain
->joinAggressiveness( child
);
972 PM_DEBUG("%s: addPowerChild3 not in power plane\n", getName());
975 connection
->release();
979 //*********************************************************************************
980 // [deprecated] setPowerParent
982 // Power Management is informing us who our parent is.
983 // If we have a controlling driver, find out, given our newly-informed
984 // power domain state, what state it would be in, and then tell it
985 // to assume that state.
986 //*********************************************************************************
988 IOReturn
IOService::setPowerParent (
989 IOPowerConnection
* theParent
, bool stateKnown
, IOPMPowerFlags powerFlags
)
991 return kIOReturnUnsupported
;
993 #endif /* !__LP64__ */
995 //*********************************************************************************
996 // [public] removePowerChild
998 // Called on a parent whose child is being removed by PMstop().
999 //*********************************************************************************
1001 IOReturn
IOService::removePowerChild ( IOPowerConnection
* theNub
)
1003 IORegistryEntry
* theChild
;
1005 PM_ASSERT_IN_GATE();
1006 OUR_PMLog( kPMLogRemoveChild
, 0, 0 );
1010 // detach nub from child
1011 theChild
= theNub
->copyChildEntry(gIOPowerPlane
);
1014 theNub
->detachFromChild(theChild
, gIOPowerPlane
);
1015 theChild
->release();
1017 // detach from the nub
1018 detachFromChild(theNub
, gIOPowerPlane
);
1020 // Are we awaiting an ack from this child?
1021 if ( theNub
->getAwaitingAck() )
1023 // yes, pretend we got one
1024 theNub
->setAwaitingAck(false);
1025 if (fHeadNotePendingAcks
!= 0 )
1027 // that's one fewer ack to worry about
1028 fHeadNotePendingAcks
--;
1030 // is that the last?
1031 if ( fHeadNotePendingAcks
== 0 )
1040 // A child has gone away, re-scan children desires and clamp bits.
1041 // The fPendingAdjustPowerRequest helps to reduce redundant parent work.
1043 if (!fAdjustPowerScheduled
)
1045 IOPMRequest
* request
;
1046 request
= acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState
);
1049 submitPMRequest( request
);
1050 fAdjustPowerScheduled
= true;
1057 //*********************************************************************************
1058 // [public] registerPowerDriver
1060 // A driver has called us volunteering to control power to our device.
1061 //*********************************************************************************
1063 IOReturn
IOService::registerPowerDriver (
1064 IOService
* powerDriver
,
1065 IOPMPowerState
* powerStates
,
1066 unsigned long numberOfStates
)
1068 IOPMRequest
* request
;
1069 IOPMPowerState
* powerStatesCopy
= 0;
1072 return IOPMNotYetInitialized
;
1074 // Validate arguments.
1075 if (!powerStates
|| (numberOfStates
< 2))
1077 OUR_PMLog(kPMLogControllingDriverErr5
, numberOfStates
, 0);
1078 return kIOReturnBadArgument
;
1081 if (!powerDriver
|| !powerDriver
->initialized
)
1083 OUR_PMLog(kPMLogControllingDriverErr4
, 0, 0);
1084 return kIOReturnBadArgument
;
1087 if (powerStates
[0].version
!= kIOPMPowerStateVersion1
)
1089 OUR_PMLog(kPMLogControllingDriverErr1
, powerStates
[0].version
, 0);
1090 return kIOReturnBadArgument
;
1094 // Make a copy of the supplied power state array.
1095 powerStatesCopy
= IONew(IOPMPowerState
, numberOfStates
);
1096 if (!powerStatesCopy
)
1099 bcopy( powerStates
, powerStatesCopy
,
1100 sizeof(IOPMPowerState
) * numberOfStates
);
1102 request
= acquirePMRequest( this, kIOPMRequestTypeRegisterPowerDriver
);
1106 powerDriver
->retain();
1107 request
->fArg0
= (void *) powerDriver
;
1108 request
->fArg1
= (void *) powerStatesCopy
;
1109 request
->fArg2
= (void *) numberOfStates
;
1111 submitPMRequest( request
);
1112 return kIOReturnSuccess
;
1116 if (powerStatesCopy
)
1117 IODelete(powerStatesCopy
, IOPMPowerState
, numberOfStates
);
1118 return kIOReturnNoMemory
;
1121 //*********************************************************************************
1122 // [private] handleRegisterPowerDriver
1123 //*********************************************************************************
1125 void IOService::handleRegisterPowerDriver ( IOPMRequest
* request
)
1127 IOService
* powerDriver
= (IOService
*) request
->fArg0
;
1128 IOPMPowerState
* powerStates
= (IOPMPowerState
*) request
->fArg1
;
1129 unsigned long numberOfStates
= (unsigned long) request
->fArg2
;
1134 PM_ASSERT_IN_GATE();
1135 assert(powerStates
);
1136 assert(powerDriver
);
1137 assert(numberOfStates
> 1);
1139 if ( !fNumberOfPowerStates
)
1141 OUR_PMLog(kPMLogControllingDriver
,
1142 (unsigned long) numberOfStates
,
1143 (unsigned long) powerStates
[0].version
);
1145 fPowerStates
= powerStates
;
1146 fNumberOfPowerStates
= numberOfStates
;
1147 fControllingDriver
= powerDriver
;
1148 fCurrentCapabilityFlags
= fPowerStates
[0].capabilityFlags
;
1150 // make a mask of all the character bits we know about
1151 fOutputPowerCharacterFlags
= 0;
1152 for ( i
= 0; i
< numberOfStates
; i
++ ) {
1153 fOutputPowerCharacterFlags
|= fPowerStates
[i
].outputPowerCharacter
;
1156 // Register powerDriver as interested, unless already done.
1157 // We don't want to register the default implementation since
1158 // it does nothing. One ramification of not always registering
1159 // is the one fewer retain count held.
1161 root
= getPlatform()->getProvider();
1164 ((OSMemberFunctionCast(void (*)(void),
1165 root
, &IOService::powerStateDidChangeTo
)) !=
1166 ((OSMemberFunctionCast(void (*)(void),
1167 this, &IOService::powerStateDidChangeTo
)))) ||
1168 ((OSMemberFunctionCast(void (*)(void),
1169 root
, &IOService::powerStateWillChangeTo
)) !=
1170 ((OSMemberFunctionCast(void (*)(void),
1171 this, &IOService::powerStateWillChangeTo
)))))
1173 if (fInterestedDrivers
->findItem(powerDriver
) == NULL
)
1176 fInterestedDrivers
->appendNewInformee(powerDriver
);
1181 // Examine all existing power clients and perform limit check.
1185 iter
= OSCollectionIterator::withCollection(fPowerClients
);
1188 const OSSymbol
* client
;
1189 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
1191 uint32_t powerState
= getPowerStateForClient(client
);
1192 if (powerState
>= numberOfStates
)
1194 updatePowerClient(client
, numberOfStates
- 1);
1201 if ( inPlane(gIOPowerPlane
) && fParentsKnowState
)
1203 unsigned long tempDesire
;
1204 fMaxCapability
= fControllingDriver
->maxCapabilityForDomainState(fParentsCurrentPowerFlags
);
1205 // initially change into the state we are already in
1206 tempDesire
= fControllingDriver
->initialPowerStateForDomainState(fParentsCurrentPowerFlags
);
1207 adjustPowerState(tempDesire
);
1212 OUR_PMLog(kPMLogControllingDriverErr2
, numberOfStates
, 0);
1213 IODelete(powerStates
, IOPMPowerState
, numberOfStates
);
1216 powerDriver
->release();
1219 //*********************************************************************************
1220 // [public] registerInterestedDriver
1222 // Add the caller to our list of interested drivers and return our current
1223 // power state. If we don't have a power-controlling driver yet, we will
1224 // call this interested driver again later when we do get a driver and find
1225 // out what the current power state of the device is.
1226 //*********************************************************************************
1228 IOPMPowerFlags
IOService::registerInterestedDriver ( IOService
* driver
)
1230 IOPMRequest
* request
;
1233 if (!initialized
|| !fInterestedDrivers
)
1234 return IOPMNotPowerManaged
;
1237 signal
= (!fInsertInterestSet
&& !fRemoveInterestSet
);
1238 if (fInsertInterestSet
== NULL
)
1239 fInsertInterestSet
= OSSet::withCapacity(4);
1240 if (fInsertInterestSet
)
1241 fInsertInterestSet
->setObject(driver
);
1246 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1248 submitPMRequest( request
);
1251 // This return value cannot be trusted, but return a value
1252 // for those clients that care.
1254 OUR_PMLog(kPMLogInterestedDriver
, kIOPMDeviceUsable
, 2);
1255 return kIOPMDeviceUsable
;
1258 //*********************************************************************************
1259 // [public] deRegisterInterestedDriver
1260 //*********************************************************************************
1262 IOReturn
IOService::deRegisterInterestedDriver ( IOService
* driver
)
1264 IOPMinformeeList
* list
;
1265 IOPMinformee
* item
;
1266 IOPMRequest
* request
;
1269 if (!initialized
|| !fInterestedDrivers
)
1270 return IOPMNotPowerManaged
;
1273 signal
= (!fRemoveInterestSet
&& !fInsertInterestSet
);
1274 if (fRemoveInterestSet
== NULL
)
1275 fRemoveInterestSet
= OSSet::withCapacity(4);
1276 if (fRemoveInterestSet
)
1278 fRemoveInterestSet
->setObject(driver
);
1280 list
= fInterestedDrivers
;
1281 item
= list
->findItem(driver
);
1282 if (item
&& item
->active
)
1284 item
->active
= false;
1286 if (fLockedFlags
.DriverCallBusy
)
1287 PM_DEBUG("%s::deRegisterInterestedDriver() driver call busy\n", getName());
1293 request
= acquirePMRequest( this, kIOPMRequestTypeInterestChanged
);
1295 submitPMRequest( request
);
1301 //*********************************************************************************
1302 // [private] handleInterestChanged
1304 // Handle interest added or removed.
1305 //*********************************************************************************
1307 void IOService::handleInterestChanged( IOPMRequest
* request
)
1310 IOPMinformee
* informee
;
1311 IOPMinformeeList
* list
= fInterestedDrivers
;
1315 if (fInsertInterestSet
)
1317 while ((driver
= (IOService
*) fInsertInterestSet
->getAnyObject()))
1319 if ((list
->findItem(driver
) == NULL
) &&
1320 (!fRemoveInterestSet
||
1321 !fRemoveInterestSet
->containsObject(driver
)))
1323 informee
= list
->appendNewInformee(driver
);
1325 fInsertInterestSet
->removeObject(driver
);
1327 fInsertInterestSet
->release();
1328 fInsertInterestSet
= 0;
1331 if (fRemoveInterestSet
)
1333 while ((driver
= (IOService
*) fRemoveInterestSet
->getAnyObject()))
1335 informee
= list
->findItem(driver
);
1338 if (fHeadNotePendingAcks
&& informee
->timer
)
1340 informee
->timer
= 0;
1341 fHeadNotePendingAcks
--;
1343 list
->removeFromList(driver
);
1345 fRemoveInterestSet
->removeObject(driver
);
1347 fRemoveInterestSet
->release();
1348 fRemoveInterestSet
= 0;
1354 //*********************************************************************************
1355 // [public] acknowledgePowerChange
1357 // After we notified one of the interested drivers or a power-domain child
1358 // of an impending change in power, it has called to say it is now
1359 // prepared for the change. If this object is the last to
1360 // acknowledge this change, we take whatever action we have been waiting
1362 // That may include acknowledging to our parent. In this case, we do it
1363 // last of all to insure that this doesn't cause the parent to call us some-
1364 // where else and alter data we are relying on here (like the very existance
1365 // of a "current change note".)
1366 //*********************************************************************************
1368 IOReturn
IOService::acknowledgePowerChange ( IOService
* whichObject
)
1370 IOPMRequest
* request
;
1373 return IOPMNotYetInitialized
;
1375 return kIOReturnBadArgument
;
1377 request
= acquirePMRequest( this, kIOPMRequestTypeAckPowerChange
);
1379 return kIOReturnNoMemory
;
1381 whichObject
->retain();
1382 request
->fArg0
= whichObject
;
1384 submitPMRequest( request
);
1388 //*********************************************************************************
1389 // [private] handleAcknowledgePowerChange
1390 //*********************************************************************************
1392 bool IOService::handleAcknowledgePowerChange ( IOPMRequest
* request
)
1394 IOPMinformee
* informee
;
1395 unsigned long childPower
= kIOPMUnknown
;
1396 IOService
* theChild
;
1397 IOService
* whichObject
;
1398 bool all_acked
= false;
1400 PM_ASSERT_IN_GATE();
1401 whichObject
= (IOService
*) request
->fArg0
;
1402 assert(whichObject
);
1404 // one of our interested drivers?
1405 informee
= fInterestedDrivers
->findItem( whichObject
);
1406 if ( informee
== NULL
)
1408 if ( !isChild(whichObject
, gIOPowerPlane
) )
1410 OUR_PMLog(kPMLogAcknowledgeErr1
, 0, 0);
1413 OUR_PMLog(kPMLogChildAcknowledge
, fHeadNotePendingAcks
, 0);
1416 OUR_PMLog(kPMLogDriverAcknowledge
, fHeadNotePendingAcks
, 0);
1419 if ( fHeadNotePendingAcks
!= 0 )
1421 assert(fPowerStates
!= NULL
);
1423 // yes, make sure we're expecting acks
1424 if ( informee
!= NULL
)
1426 // it's an interested driver
1427 // make sure we're expecting this ack
1428 if ( informee
->timer
!= 0 )
1430 #if LOG_SETPOWER_TIMES
1431 if (informee
->timer
> 0)
1433 uint64_t nsec
= computeTimeDeltaNS(&informee
->startTime
);
1434 if (nsec
> LOG_SETPOWER_TIMES
)
1435 PM_DEBUG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) async took %d ms\n",
1436 informee
->whatObject
->getName(),
1437 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
1438 informee
->whatObject
,
1439 fName
, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
1443 informee
->timer
= 0;
1444 // that's one fewer to worry about
1445 fHeadNotePendingAcks
--;
1447 // this driver has already acked
1448 OUR_PMLog(kPMLogAcknowledgeErr2
, 0, 0);
1452 // make sure we're expecting this ack
1453 if ( ((IOPowerConnection
*)whichObject
)->getAwaitingAck() )
1455 // that's one fewer to worry about
1456 fHeadNotePendingAcks
--;
1457 ((IOPowerConnection
*)whichObject
)->setAwaitingAck(false);
1458 theChild
= (IOService
*)whichObject
->copyChildEntry(gIOPowerPlane
);
1461 childPower
= theChild
->currentPowerConsumption();
1462 theChild
->release();
1464 if ( childPower
== kIOPMUnknown
)
1466 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
1468 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
1470 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
1476 if ( fHeadNotePendingAcks
== 0 ) {
1477 // yes, stop the timer
1479 // and now we can continue
1483 OUR_PMLog(kPMLogAcknowledgeErr3
, 0, 0); // not expecting anybody to ack
1488 whichObject
->release();
1493 //*********************************************************************************
1494 // [public] acknowledgeSetPowerState
1496 // After we instructed our controlling driver to change power states,
1497 // it has called to say it has finished doing so.
1498 // We continue to process the power state change.
1499 //*********************************************************************************
1501 IOReturn
IOService::acknowledgeSetPowerState ( void )
1503 IOPMRequest
* request
;
1506 return IOPMNotYetInitialized
;
1508 request
= acquirePMRequest( this, kIOPMRequestTypeAckSetPowerState
);
1510 return kIOReturnNoMemory
;
1512 submitPMRequest( request
);
1513 return kIOReturnSuccess
;
1516 //*********************************************************************************
1517 // [private] adjustPowerState
1518 //*********************************************************************************
1520 void IOService::adjustPowerState ( uint32_t clamp
)
1522 PM_ASSERT_IN_GATE();
1523 computeDesiredState(clamp
);
1524 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
))
1527 /* flags */ kIOPMWeInitiated
,
1528 /* power state */ fDesiredPowerState
,
1529 /* domain flags */ 0,
1531 /* parent flags */ 0);
1535 //*********************************************************************************
1536 // [public] synchronizePowerTree
1537 //*********************************************************************************
1539 IOReturn
IOService::synchronizePowerTree ( void )
1541 IOPMRequest
* request_c
;
1542 IOPMRequest
* request_s
;
1544 if (this != getPMRootDomain())
1545 return kIOReturnBadArgument
;
1547 return kIOPMNotYetInitialized
;
1549 request_c
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
1550 request_s
= acquirePMRequest( this, kIOPMRequestTypeSynchronizePowerTree
);
1552 if (!request_c
|| !request_s
)
1553 goto error_no_memory
;
1555 request_c
->attachNextRequest( request_s
);
1557 submitPMRequest(request_c
);
1558 submitPMRequest(request_s
);
1560 return kIOReturnSuccess
;
1563 if (request_c
) releasePMRequest(request_c
);
1564 if (request_s
) releasePMRequest(request_s
);
1565 return kIOReturnNoMemory
;
1568 //*********************************************************************************
1569 // [private] handleSynchronizePowerTree
1570 //*********************************************************************************
1572 void IOService::handleSynchronizePowerTree ( IOPMRequest
* /*request*/ )
1574 PM_ASSERT_IN_GATE();
1575 if (fControllingDriver
&& fParentsKnowState
&& inPlane(gIOPowerPlane
) &&
1576 (fCurrentPowerState
== fNumberOfPowerStates
- 1))
1579 /* flags */ kIOPMWeInitiated
| kIOPMSynchronize
,
1580 /* power state */ fCurrentPowerState
,
1581 /* domain flags */ 0,
1583 /* parent flags */ 0);
1588 //*********************************************************************************
1589 // [deprecated] powerDomainWillChangeTo
1591 // Called by the power-hierarchy parent notifying of a new power state
1592 // in the power domain.
1593 // We enqueue a parent power-change to our queue of power changes.
1594 // This may or may not cause us to change power, depending on what
1595 // kind of change is occuring in the domain.
1596 //*********************************************************************************
1598 IOReturn
IOService::powerDomainWillChangeTo (
1599 IOPMPowerFlags newPowerFlags
,
1600 IOPowerConnection
* whichParent
)
1603 return kIOReturnUnsupported
;
1605 #endif /* !__LP64__ */
1607 //*********************************************************************************
1608 // [private] handlePowerDomainWillChangeTo
1609 //*********************************************************************************
1611 void IOService::handlePowerDomainWillChangeTo ( IOPMRequest
* request
)
1613 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1614 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1615 unsigned long parentChangeFlags
= (unsigned long) request
->fArg2
;
1618 IOPowerConnection
* connection
;
1619 unsigned long newPowerState
;
1620 unsigned long myChangeFlags
;
1621 IOPMPowerFlags combinedPowerFlags
;
1622 bool savedParentsKnowState
;
1623 IOReturn result
= IOPMAckImplied
;
1625 PM_ASSERT_IN_GATE();
1626 OUR_PMLog(kPMLogWillChange
, parentPowerFlags
, 0);
1628 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1630 PM_DEBUG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1634 savedParentsKnowState
= fParentsKnowState
;
1636 // Combine parents' output power flags.
1638 combinedPowerFlags
= 0;
1640 iter
= getParentIterator(gIOPowerPlane
);
1643 while ( (next
= iter
->getNextObject()) )
1645 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1647 if ( connection
== whichParent
)
1648 combinedPowerFlags
|= parentPowerFlags
;
1650 combinedPowerFlags
|= connection
->parentCurrentPowerFlags();
1656 // If our initial change has yet to occur, then defer the power change
1657 // until after the power domain has completed its power transition.
1659 if ( fControllingDriver
&& !fInitialChange
)
1661 newPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1662 combinedPowerFlags
);
1664 // Absorb parent's kIOPMSynchronize flag.
1665 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainWillChange
|
1666 (parentChangeFlags
& kIOPMSynchronize
);
1668 result
= startPowerChange(
1669 /* flags */ myChangeFlags
,
1670 /* power state */ newPowerState
,
1671 /* domain flags */ combinedPowerFlags
,
1672 /* connection */ whichParent
,
1673 /* parent flags */ parentPowerFlags
);
1676 // If parent is dropping power, immediately update the parent's
1677 // capability flags. Any future merging of parent(s) combined
1678 // power flags should account for this power drop.
1680 if (parentChangeFlags
& kIOPMDomainPowerDrop
)
1682 setParentInfo(parentPowerFlags
, whichParent
, true);
1685 // Parent is expecting an ACK from us. If we did not embark on a state
1686 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1687 // still required to issue an ACK to our parent.
1689 if (IOPMAckImplied
== result
)
1692 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1696 parent
->acknowledgePowerChange( whichParent
);
1702 // Drop the retain from notifyChild().
1703 if (whichParent
) whichParent
->release();
1707 //*********************************************************************************
1708 // [deprecated] powerDomainDidChangeTo
1710 // Called by the power-hierarchy parent after the power state of the power domain
1711 // has settled at a new level.
1712 // We enqueue a parent power-change to our queue of power changes.
1713 // This may or may not cause us to change power, depending on what
1714 // kind of change is occuring in the domain.
1715 //*********************************************************************************
1717 IOReturn
IOService::powerDomainDidChangeTo (
1718 IOPMPowerFlags newPowerFlags
,
1719 IOPowerConnection
* whichParent
)
1722 return kIOReturnUnsupported
;
1724 #endif /* !__LP64__ */
1726 //*********************************************************************************
1727 // [private] handlePowerDomainDidChangeTo
1728 //*********************************************************************************
1730 void IOService::handlePowerDomainDidChangeTo ( IOPMRequest
* request
)
1732 IOPMPowerFlags parentPowerFlags
= (IOPMPowerFlags
) request
->fArg0
;
1733 IOPowerConnection
* whichParent
= (IOPowerConnection
*) request
->fArg1
;
1734 unsigned long parentChangeFlags
= (unsigned long) request
->fArg2
;
1735 unsigned long newPowerState
;
1736 unsigned long myChangeFlags
;
1737 unsigned long initialDesire
;
1738 bool savedParentsKnowState
;
1739 IOReturn result
= IOPMAckImplied
;
1741 PM_ASSERT_IN_GATE();
1742 OUR_PMLog(kPMLogDidChange
, parentPowerFlags
, 0);
1744 if (!inPlane(gIOPowerPlane
) || !whichParent
|| !whichParent
->getAwaitingAck())
1746 PM_DEBUG("%s::%s not in power tree\n", getName(), __FUNCTION__
);
1750 savedParentsKnowState
= fParentsKnowState
;
1752 setParentInfo(parentPowerFlags
, whichParent
, true);
1754 if ( fControllingDriver
)
1756 newPowerState
= fControllingDriver
->maxCapabilityForDomainState(
1757 fParentsCurrentPowerFlags
);
1761 initialDesire
= fControllingDriver
->initialPowerStateForDomainState(
1762 fParentsCurrentPowerFlags
);
1763 computeDesiredState(initialDesire
);
1766 // Absorb parent's kIOPMSynchronize flag.
1767 myChangeFlags
= kIOPMParentInitiated
| kIOPMDomainDidChange
|
1768 (parentChangeFlags
& kIOPMSynchronize
);
1770 result
= startPowerChange(
1771 /* flags */ myChangeFlags
,
1772 /* power state */ newPowerState
,
1773 /* domain flags */ fParentsCurrentPowerFlags
,
1774 /* connection */ whichParent
,
1775 /* parent flags */ 0);
1778 // Parent is expecting an ACK from us. If we did not embark on a state
1779 // transition, i.e. startPowerChange() returned IOPMAckImplied. We are
1780 // still required to issue an ACK to our parent.
1782 if (IOPMAckImplied
== result
)
1785 parent
= (IOService
*) whichParent
->copyParentEntry(gIOPowerPlane
);
1789 parent
->acknowledgePowerChange( whichParent
);
1794 // If the parent registers its power driver late, then this is the
1795 // first opportunity to tell our parent about our desire.
1797 if (!savedParentsKnowState
&& fParentsKnowState
)
1799 PM_TRACE("%s::powerDomainDidChangeTo parentsKnowState = true\n",
1801 requestDomainPower( fDesiredPowerState
);
1805 // Drop the retain from notifyChild().
1806 if (whichParent
) whichParent
->release();
1809 //*********************************************************************************
1810 // [private] setParentInfo
1812 // Set our connection data for one specific parent, and then combine all the parent
1814 //*********************************************************************************
1816 void IOService::setParentInfo (
1817 IOPMPowerFlags newPowerFlags
,
1818 IOPowerConnection
* whichParent
,
1823 IOPowerConnection
* conn
;
1825 PM_ASSERT_IN_GATE();
1827 // set our connection data
1828 whichParent
->setParentCurrentPowerFlags(newPowerFlags
);
1829 whichParent
->setParentKnowsState(knowsState
);
1831 // recompute our parent info
1832 fParentsCurrentPowerFlags
= 0;
1833 fParentsKnowState
= true;
1835 iter
= getParentIterator(gIOPowerPlane
);
1838 while ( (next
= iter
->getNextObject()) )
1840 if ( (conn
= OSDynamicCast(IOPowerConnection
, next
)) )
1842 fParentsKnowState
&= conn
->parentKnowsState();
1843 fParentsCurrentPowerFlags
|= conn
->parentCurrentPowerFlags();
1850 //*********************************************************************************
1851 // [private] rebuildChildClampBits
1853 // The ChildClamp bits (kIOPMChildClamp & kIOPMChildClamp2) in our capabilityFlags
1854 // indicate that one of our children (or grandchildren or great-grandchildren ...)
1855 // doesn't support idle or system sleep in its current state. Since we don't track
1856 // the origin of each bit, every time any child changes state we have to clear
1857 // these bits and rebuild them.
1858 //*********************************************************************************
1860 void IOService::rebuildChildClampBits ( void )
1865 IOPowerConnection
* connection
;
1866 unsigned long powerState
;
1868 // A child's desires has changed. We need to rebuild the child-clamp bits in
1869 // our power state array. Start by clearing the bits in each power state.
1871 for ( i
= 0; i
< fNumberOfPowerStates
; i
++ )
1873 fPowerStates
[i
].capabilityFlags
&= ~(kIOPMChildClamp
| kIOPMChildClamp2
);
1876 if (!inPlane(gIOPowerPlane
))
1879 // Loop through the children. When we encounter the calling child, save the
1880 // computed state as this child's desire. And set the ChildClamp bits in any
1881 // of our states that some child has clamp on.
1883 iter
= getChildIterator(gIOPowerPlane
);
1886 while ( (next
= iter
->getNextObject()) )
1888 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
1890 if (connection
->getReadyFlag() == false)
1892 PM_CONNECT("[%s] %s: connection not ready\n",
1893 getName(), __FUNCTION__
);
1897 powerState
= connection
->getDesiredDomainState();
1898 if (powerState
< fNumberOfPowerStates
)
1900 if ( connection
->getPreventIdleSleepFlag() )
1901 fPowerStates
[powerState
].capabilityFlags
|= kIOPMChildClamp
;
1902 if ( connection
->getPreventSystemSleepFlag() )
1903 fPowerStates
[powerState
].capabilityFlags
|= kIOPMChildClamp2
;
1911 //*********************************************************************************
1912 // [public] requestPowerDomainState
1914 // Called on a power parent when a child's power requirement changes.
1915 //*********************************************************************************
1917 IOReturn
IOService::requestPowerDomainState(
1918 IOPMPowerFlags childRequestPowerFlags
,
1919 IOPowerConnection
* childConnection
,
1920 unsigned long specification
)
1923 IOPMPowerFlags outputPowerFlags
;
1925 IOPMRequest
* subRequest
;
1926 bool preventIdle
, preventSleep
;
1927 bool adjustPower
= false;
1930 return IOPMNotYetInitialized
;
1932 if (gIOPMWorkLoop
->onThread() == false)
1934 PM_DEBUG("%s::requestPowerDomainState\n", getName());
1935 return kIOReturnSuccess
;
1938 OUR_PMLog(kPMLogRequestDomain
, childRequestPowerFlags
, specification
);
1940 if (!isChild(childConnection
, gIOPowerPlane
))
1941 return kIOReturnNotAttached
;
1943 if (!fControllingDriver
|| !fNumberOfPowerStates
)
1944 return IOPMNotYetInitialized
;
1946 child
= (IOService
*) childConnection
->getChildEntry(gIOPowerPlane
);
1949 preventIdle
= ((childRequestPowerFlags
& kIOPMPreventIdleSleep
) != 0);
1950 preventSleep
= ((childRequestPowerFlags
& kIOPMPreventSystemSleep
) != 0);
1951 childRequestPowerFlags
&= ~(kIOPMPreventIdleSleep
| kIOPMPreventSystemSleep
);
1953 // Merge in the power flags contributed by this power parent
1954 // at its current or impending power state.
1956 outputPowerFlags
= fPowerStates
[fCurrentPowerState
].outputPowerCharacter
;
1957 if ((fMachineState
!= kIOPM_Finished
) && (getPMRootDomain() != this))
1961 // Use the lower power state when dropping power.
1962 // Must be careful since a power drop can be canceled
1963 // from the following states:
1964 // - kIOPM_OurChangeTellClientsPowerDown
1965 // - kIOPM_OurChangeTellPriorityClientsPowerDown
1967 // The child must not wait for this parent to raise power
1968 // if the power drop was cancelled. The solution is to cancel
1969 // the power drop if possible, then schedule an adjustment to
1970 // re-evaluate our correct power state.
1972 // Root domain is excluded to avoid idle sleep issues. And permit
1973 // root domain children to pop up when system is going to sleep.
1975 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
) ||
1976 (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
1978 fDoNotPowerDown
= true; // cancel power drop
1979 adjustPower
= true; // schedule an adjustment
1980 PM_TRACE("%s: power drop cancelled in state %u by %s\n",
1981 getName(), fMachineState
, child
->getName());
1985 // Beyond cancellation point, report the impending state.
1987 fPowerStates
[fHeadNotePowerState
].outputPowerCharacter
;
1992 // When raising power, must report the output power flags from
1993 // child's perspective. A child power request may arrive while
1994 // parent is transitioning upwards. If a request arrives after
1995 // setParentInfo() has already recorded the output power flags
1996 // for the next power state, then using the power supplied by
1997 // fCurrentPowerState is incorrect, and might cause the child
1998 // to wait when it should not.
2000 outputPowerFlags
= childConnection
->parentCurrentPowerFlags();
2003 child
->fHeadNoteDomainTargetFlags
|= outputPowerFlags
;
2005 // Map child's requested power flags to one of our power state.
2007 for (ps
= 0; ps
< fNumberOfPowerStates
; ps
++)
2009 if ((fPowerStates
[ps
].outputPowerCharacter
& childRequestPowerFlags
) ==
2010 (fOutputPowerCharacterFlags
& childRequestPowerFlags
))
2013 if (ps
>= fNumberOfPowerStates
)
2015 ps
= 0; // should never happen
2018 // Conditions that warrants a power adjustment on this parent.
2019 // Adjust power will also propagate any changes to the child's
2020 // prevent idle/sleep flags towards the root domain.
2022 if (!childConnection
->childHasRequestedPower() ||
2023 (ps
!= childConnection
->getDesiredDomainState()) ||
2024 (childConnection
->getPreventIdleSleepFlag() != preventIdle
) ||
2025 (childConnection
->getPreventSystemSleepFlag() != preventSleep
))
2028 #if ENABLE_DEBUG_LOGS
2031 PM_DEBUG("requestPowerDomainState[%s]: %s, init %d, %u->%u\n",
2032 getName(), child
->getName(),
2033 !childConnection
->childHasRequestedPower(),
2034 (uint32_t) childConnection
->getDesiredDomainState(),
2039 // Record the child's desires on the connection.
2040 #if SUPPORT_IDLE_CANCEL
2041 bool attemptCancel
= (preventIdle
&& !childConnection
->getPreventIdleSleepFlag());
2043 childConnection
->setChildHasRequestedPower();
2044 childConnection
->setDesiredDomainState( ps
);
2045 childConnection
->setPreventIdleSleepFlag( preventIdle
);
2046 childConnection
->setPreventSystemSleepFlag( preventSleep
);
2048 // Schedule a request to re-evaluate all children desires and
2049 // adjust power state. Submit a request if one wasn't pending,
2050 // or if the current request is part of a call tree.
2052 if (adjustPower
&& !fDeviceOverrides
&&
2053 (!fAdjustPowerScheduled
|| gIOPMRequest
->getRootRequest()))
2055 subRequest
= acquirePMRequest(
2056 this, kIOPMRequestTypeAdjustPowerState
, gIOPMRequest
);
2059 submitPMRequest( subRequest
);
2060 fAdjustPowerScheduled
= true;
2064 #if SUPPORT_IDLE_CANCEL
2067 subRequest
= acquirePMRequest( this, kIOPMRequestTypeIdleCancel
);
2070 submitPMRequest( subRequest
);
2075 return kIOReturnSuccess
;
2078 //*********************************************************************************
2079 // [public] temporaryPowerClampOn
2081 // A power domain wants to clamp its power on till it has children which
2082 // will thendetermine the power domain state.
2084 // We enter the highest state until addPowerChild is called.
2085 //*********************************************************************************
2087 IOReturn
IOService::temporaryPowerClampOn ( void )
2089 return requestPowerState( gIOPMPowerClientChildProxy
, kIOPMPowerStateMax
);
2092 //*********************************************************************************
2093 // [public] makeUsable
2095 // Some client of our device is asking that we become usable. Although
2096 // this has not come from a subclassed device object, treat it exactly
2097 // as if it had. In this way, subsequent requests for lower power from
2098 // a subclassed device object will pre-empt this request.
2100 // We treat this as a subclass object request to switch to the
2101 // highest power state.
2102 //*********************************************************************************
2104 IOReturn
IOService::makeUsable ( void )
2106 OUR_PMLog(kPMLogMakeUsable
, 0, 0);
2107 return requestPowerState( gIOPMPowerClientDevice
, kIOPMPowerStateMax
);
2110 //*********************************************************************************
2111 // [public] currentCapability
2112 //*********************************************************************************
2114 IOPMPowerFlags
IOService::currentCapability ( void )
2117 return IOPMNotPowerManaged
;
2119 return fCurrentCapabilityFlags
;
2122 //*********************************************************************************
2123 // [public] changePowerStateTo
2125 // Called by our power-controlling driver to change power state. The new desired
2126 // power state is computed and compared against the current power state. If those
2127 // power states differ, then a power state change is initiated.
2128 //*********************************************************************************
2130 IOReturn
IOService::changePowerStateTo ( unsigned long ordinal
)
2132 OUR_PMLog(kPMLogChangeStateTo
, ordinal
, 0);
2133 return requestPowerState( gIOPMPowerClientDriver
, ordinal
);
2136 //*********************************************************************************
2137 // [protected] changePowerStateToPriv
2139 // Called by our driver subclass to change power state. The new desired power
2140 // state is computed and compared against the current power state. If those
2141 // power states differ, then a power state change is initiated.
2142 //*********************************************************************************
2144 IOReturn
IOService::changePowerStateToPriv ( unsigned long ordinal
)
2146 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2147 return requestPowerState( gIOPMPowerClientDevice
, ordinal
);
2150 //*********************************************************************************
2151 // [protected] changePowerStateWithOverrideTo
2153 // Called by our driver subclass to change power state. The new desired power
2154 // state is computed and compared against the current power state. If those
2155 // power states differ, then a power state change is initiated.
2156 // Override enforced - Children and Driver desires are ignored.
2157 //*********************************************************************************
2159 IOReturn
IOService::changePowerStateWithOverrideTo ( unsigned long ordinal
)
2161 IOPMRequest
* request
;
2164 return kIOPMNotYetInitialized
;
2166 OUR_PMLog(kPMLogChangeStateToPriv
, ordinal
, 0);
2168 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerStateOverride
);
2170 return kIOReturnNoMemory
;
2172 gIOPMPowerClientDevice
->retain();
2173 request
->fArg0
= (void *) ordinal
;
2174 request
->fArg1
= (void *) gIOPMPowerClientDevice
;
2178 request
->installCompletionAction( action
, target
, param
);
2181 // Prevent needless downwards power transitions by clamping power
2182 // until the scheduled request is executed.
2184 if (gIOPMWorkLoop
->inGate() && (ordinal
< fNumberOfPowerStates
))
2186 fTempClampPowerState
= max(fTempClampPowerState
, ordinal
);
2188 fOverrideMaxPowerState
= ordinal
;
2189 request
->fArg2
= (void *) true;
2192 submitPMRequest( request
);
2196 //*********************************************************************************
2197 // [private] requestPowerState
2198 //*********************************************************************************
2200 IOReturn
IOService::requestPowerState (
2201 const OSSymbol
* client
,
2204 IOPMRequest
* request
;
2207 return kIOReturnBadArgument
;
2209 return kIOPMNotYetInitialized
;
2211 request
= acquirePMRequest( this, kIOPMRequestTypeRequestPowerState
);
2213 return kIOReturnNoMemory
;
2216 request
->fArg0
= (void *) state
;
2217 request
->fArg1
= (void *) client
;
2221 request
->installCompletionAction( action
, target
, param
);
2224 // Prevent needless downwards power transitions by clamping power
2225 // until the scheduled request is executed.
2227 if (gIOPMWorkLoop
->inGate() && (state
< fNumberOfPowerStates
))
2229 fTempClampPowerState
= max(fTempClampPowerState
, state
);
2231 request
->fArg2
= (void *) true;
2234 submitPMRequest( request
);
2238 //*********************************************************************************
2239 // [private] handleRequestPowerState
2240 //*********************************************************************************
2242 void IOService::handleRequestPowerState ( IOPMRequest
* request
)
2244 const OSSymbol
* client
= (const OSSymbol
*) request
->fArg1
;
2245 uint32_t state
= (uint32_t)(uintptr_t) request
->fArg0
;
2247 PM_ASSERT_IN_GATE();
2250 assert(fTempClampCount
!= 0);
2251 if (fTempClampCount
) fTempClampCount
--;
2252 if (!fTempClampCount
) fTempClampPowerState
= 0;
2255 if (fNumberOfPowerStates
&& (state
>= fNumberOfPowerStates
))
2256 state
= fNumberOfPowerStates
- 1;
2258 // Override from changePowerStateWithOverrideTo() persists until
2259 // the next "device" power request, such as changePowerStateToPriv().
2261 if ((getPMRequestType() != kIOPMRequestTypeRequestPowerStateOverride
) &&
2262 (client
== gIOPMPowerClientDevice
))
2263 fOverrideMaxPowerState
= kIOPMPowerStateMax
;
2266 (client
!= gIOPMPowerClientDevice
) &&
2267 (client
!= gIOPMPowerClientDriver
) &&
2268 (client
!= gIOPMPowerClientChildProxy
))
2269 removePowerClient(client
);
2271 updatePowerClient(client
, state
);
2277 //*********************************************************************************
2278 // [private] Helper functions to update/remove power clients.
2279 //*********************************************************************************
2281 void IOService::updatePowerClient( const OSSymbol
* client
, uint32_t powerState
)
2284 fPowerClients
= OSDictionary::withCapacity(4);
2285 if (fPowerClients
&& client
)
2287 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2289 num
->setValue(powerState
);
2292 num
= OSNumber::withNumber(powerState
, 32);
2295 fPowerClients
->setObject(client
, num
);
2302 void IOService::removePowerClient( const OSSymbol
* client
)
2304 if (fPowerClients
&& client
)
2305 fPowerClients
->removeObject(client
);
2308 uint32_t IOService::getPowerStateForClient( const OSSymbol
* client
)
2310 uint32_t powerState
= 0;
2312 if (fPowerClients
&& client
)
2314 OSNumber
* num
= (OSNumber
*) fPowerClients
->getObject(client
);
2315 if (num
) powerState
= num
->unsigned32BitValue();
2320 //*********************************************************************************
2321 // [private] computeDesiredState
2322 //*********************************************************************************
2324 void IOService::computeDesiredState ( unsigned long localClamp
)
2328 IOPowerConnection
* connection
;
2329 uint32_t desiredState
= 0;
2330 uint32_t newPowerState
= 0;
2331 bool hasChildren
= false;
2333 // Desired power state is always 0 without a controlling driver.
2335 if (!fNumberOfPowerStates
)
2337 fDesiredPowerState
= 0;
2338 //PM_DEBUG("%s::%s no controlling driver\n", getName(), __FUNCTION__);
2342 // Examine the children's desired power state.
2344 iter
= getChildIterator(gIOPowerPlane
);
2347 while ((next
= iter
->getNextObject()))
2349 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
2351 if (connection
->getReadyFlag() == false)
2353 PM_CONNECT("[%s] %s: connection not ready\n",
2354 getName(), __FUNCTION__
);
2357 if (connection
->childHasRequestedPower())
2359 if (connection
->getDesiredDomainState() > desiredState
)
2360 desiredState
= connection
->getDesiredDomainState();
2366 updatePowerClient(gIOPMPowerClientChildren
, desiredState
);
2368 removePowerClient(gIOPMPowerClientChildren
);
2370 // Iterate through all power clients to determine the min power state.
2372 iter
= OSCollectionIterator::withCollection(fPowerClients
);
2375 const OSSymbol
* client
;
2376 while ((client
= (const OSSymbol
*) iter
->getNextObject()))
2378 // Ignore child and driver when override is in effect.
2379 if ((fDeviceOverrides
||
2380 (getPMRequestType() == kIOPMRequestTypeRequestPowerStateOverride
)) &&
2381 ((client
== gIOPMPowerClientChildren
) ||
2382 (client
== gIOPMPowerClientDriver
)))
2385 // Ignore child proxy when children are present.
2386 if (hasChildren
&& (client
== gIOPMPowerClientChildProxy
))
2389 desiredState
= getPowerStateForClient(client
);
2390 assert(desiredState
< fNumberOfPowerStates
);
2391 PM_TRACE(" %u %s\n",
2392 desiredState
, client
->getCStringNoCopy());
2394 newPowerState
= max(newPowerState
, desiredState
);
2396 if (client
== gIOPMPowerClientDevice
)
2397 fDeviceDesire
= desiredState
;
2402 // Factor in the temporary power desires.
2404 newPowerState
= max(newPowerState
, localClamp
);
2405 newPowerState
= max(newPowerState
, fTempClampPowerState
);
2407 // Limit check against max power override.
2409 newPowerState
= min(newPowerState
, fOverrideMaxPowerState
);
2411 // Limit check against number of power states.
2413 if (newPowerState
>= fNumberOfPowerStates
)
2414 newPowerState
= fNumberOfPowerStates
- 1;
2416 fDesiredPowerState
= newPowerState
;
2418 PM_TRACE(" temp %u, clamp %u, current %u, new %u\n",
2419 (uint32_t) localClamp
, (uint32_t) fTempClampPowerState
,
2420 (uint32_t) fCurrentPowerState
, newPowerState
);
2422 // Restart idle timer if stopped and device desire has increased.
2424 if (fDeviceDesire
&& fIdleTimerStopped
)
2426 fIdleTimerStopped
= false;
2427 fActivityTickleCount
= 0;
2428 clock_get_uptime(&fIdleTimerStartTime
);
2429 start_PM_idle_timer();
2432 // Invalidate cached tickle power state when desires change, and not
2433 // due to a tickle request. This invalidation must occur before the
2434 // power state change to minimize races. We want to err on the side
2435 // of servicing more activity tickles rather than dropping one when
2436 // the device is in a low power state.
2438 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2439 (fActivityTicklePowerState
!= -1))
2441 IOLockLock(fActivityLock
);
2442 fActivityTicklePowerState
= -1;
2443 IOLockUnlock(fActivityLock
);
2447 //*********************************************************************************
2448 // [public] currentPowerConsumption
2450 //*********************************************************************************
2452 unsigned long IOService::currentPowerConsumption ( void )
2455 return kIOPMUnknown
;
2457 return fCurrentPowerConsumption
;
2460 //*********************************************************************************
2461 // [deprecated] getPMworkloop
2462 //*********************************************************************************
2464 IOWorkLoop
* IOService::getPMworkloop ( void )
2466 return gIOPMWorkLoop
;
2469 //*********************************************************************************
2470 // [public] activityTickle
2472 // The tickle with parameter kIOPMSuperclassPolicy1 causes the activity
2473 // flag to be set, and the device state checked. If the device has been
2474 // powered down, it is powered up again.
2475 // The tickle with parameter kIOPMSubclassPolicy is ignored here and
2476 // should be intercepted by a subclass.
2477 //*********************************************************************************
2479 bool IOService::activityTickle ( unsigned long type
, unsigned long stateNumber
)
2481 IOPMRequest
* request
;
2482 bool noPowerChange
= true;
2484 if ( initialized
&& stateNumber
&& (type
== kIOPMSuperclassPolicy1
) )
2486 IOLockLock(fActivityLock
);
2488 // Record device activity for the idle timer handler.
2490 fDeviceActive
= true;
2491 fActivityTickleCount
++;
2492 clock_get_uptime(&fDeviceActiveTimestamp
);
2494 #if ROOT_DOMAIN_RUN_STATES
2495 getPMRootDomain()->handleActivityTickleForService(this, type
,
2496 fCurrentPowerState
, fActivityTickleCount
);
2499 // Record the last tickle power state.
2500 // This helps to filter out redundant tickles as
2501 // this function may be called from the data path.
2503 if (fActivityTicklePowerState
< (long)stateNumber
)
2505 fActivityTicklePowerState
= stateNumber
;
2506 noPowerChange
= false;
2508 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2511 request
->fArg0
= (void *) stateNumber
; // power state
2512 request
->fArg1
= (void *) true; // power rise
2513 submitPMRequest(request
);
2517 IOLockUnlock(fActivityLock
);
2520 // Returns false if the activityTickle might cause a transition to a
2521 // higher powered state, true otherwise.
2523 return noPowerChange
;
2526 //*********************************************************************************
2527 // [private] handleActivityTickle
2528 //*********************************************************************************
2530 void IOService::handleActivityTickle ( IOPMRequest
* request
)
2532 uint32_t ticklePowerState
= (uint32_t)(uintptr_t) request
->fArg0
;
2533 bool adjustPower
= false;
2535 PM_ASSERT_IN_GATE();
2538 // Power rise from activity tickle.
2539 if ((ticklePowerState
> fDeviceDesire
) &&
2540 (ticklePowerState
< fNumberOfPowerStates
))
2542 fIdleTimerMinPowerState
= ticklePowerState
;
2546 else if (fDeviceDesire
> fIdleTimerMinPowerState
)
2548 // Power drop due to idle timer expiration.
2549 // Do not allow idle timer to reduce power below tickle power.
2550 ticklePowerState
= fDeviceDesire
- 1;
2556 updatePowerClient(gIOPMPowerClientDevice
, ticklePowerState
);
2561 //*********************************************************************************
2562 // [public] setIdleTimerPeriod
2564 // A subclass policy-maker is going to use our standard idleness
2565 // detection service. Make a command queue and an idle timer and
2566 // connect them to the power management workloop. Finally,
2568 //*********************************************************************************
2570 IOReturn
IOService::setIdleTimerPeriod ( unsigned long period
)
2573 return IOPMNotYetInitialized
;
2575 OUR_PMLog(kPMLogSetIdleTimerPeriod
, period
, 0);
2577 IOPMRequest
* request
=
2578 acquirePMRequest( this, kIOPMRequestTypeSetIdleTimerPeriod
);
2580 return kIOReturnNoMemory
;
2582 request
->fArg0
= (void *) period
;
2583 submitPMRequest( request
);
2588 //******************************************************************************
2589 // [public] nextIdleTimeout
2591 // Returns how many "seconds from now" the device should idle into its
2592 // next lowest power state.
2593 //******************************************************************************
2595 SInt32
IOService::nextIdleTimeout(
2596 AbsoluteTime currentTime
,
2597 AbsoluteTime lastActivity
,
2598 unsigned int powerState
)
2605 // Calculate time difference using funky macro from clock.h.
2606 delta
= currentTime
;
2607 SUB_ABSOLUTETIME(&delta
, &lastActivity
);
2609 // Figure it in seconds.
2610 absolutetime_to_nanoseconds(delta
, &delta_ns
);
2611 delta_secs
= (SInt32
)(delta_ns
/ NSEC_PER_SEC
);
2613 // Be paranoid about delta somehow exceeding timer period.
2614 if (delta_secs
< (int) fIdleTimerPeriod
)
2615 delay_secs
= (int) fIdleTimerPeriod
- delta_secs
;
2617 delay_secs
= (int) fIdleTimerPeriod
;
2619 return (SInt32
)delay_secs
;
2622 //******************************************************************************
2623 // [public] start_PM_idle_timer
2625 // The parameter is a pointer to us. Use it to call our timeout method.
2626 //******************************************************************************
2628 void IOService::start_PM_idle_timer ( void )
2630 static const int maxTimeout
= 100000;
2631 static const int minTimeout
= 1;
2632 AbsoluteTime uptime
;
2635 if (!initialized
|| !fIdleTimerPeriod
|| !fIdleTimerEventSource
)
2638 IOLockLock(fActivityLock
);
2640 clock_get_uptime(&uptime
);
2642 // Subclasses may modify idle sleep algorithm
2643 idle_in
= nextIdleTimeout(uptime
, fDeviceActiveTimestamp
, fCurrentPowerState
);
2645 // Check for out-of range responses
2646 if (idle_in
> maxTimeout
)
2648 // use standard implementation
2649 idle_in
= IOService::nextIdleTimeout(uptime
,
2650 fDeviceActiveTimestamp
,
2651 fCurrentPowerState
);
2652 } else if (idle_in
< minTimeout
) {
2653 idle_in
= fIdleTimerPeriod
;
2656 IOLockUnlock(fActivityLock
);
2658 fIdleTimerEventSource
->setTimeout(idle_in
, NSEC_PER_SEC
);
2661 //*********************************************************************************
2662 // [private] idleTimerExpired
2664 // The idle timer has expired. If there has been activity since the last
2665 // expiration, just restart the timer and return. If there has not been
2666 // activity, switch to the next lower power state and restart the timer.
2667 //*********************************************************************************
2669 void IOService::idleTimerExpired( IOTimerEventSource
* )
2671 IOPMRequest
* request
;
2672 bool restartTimer
= true;
2674 if ( !initialized
|| !fIdleTimerPeriod
|| fLockedFlags
.PMStop
)
2677 IOLockLock(fActivityLock
);
2679 // Check for device activity (tickles) over last timer period.
2683 // Device was active - do not drop power, restart timer.
2684 fDeviceActive
= false;
2688 // No device activity - drop power state by one level.
2689 // Decrement the cached tickle power state when possible.
2690 // This value may be (-1) before activityTickle() is called,
2691 // but the power drop request must be issued regardless.
2693 if (fActivityTicklePowerState
> 0)
2695 fActivityTicklePowerState
--;
2698 request
= acquirePMRequest( this, kIOPMRequestTypeActivityTickle
);
2701 request
->fArg0
= (void *) 0; // power state (irrelevant)
2702 request
->fArg1
= (void *) false; // power drop
2703 submitPMRequest( request
);
2705 // Do not restart timer until after the tickle request has been
2708 restartTimer
= false;
2712 IOLockUnlock(fActivityLock
);
2715 start_PM_idle_timer();
2719 //*********************************************************************************
2720 // [deprecated] PM_idle_timer_expiration
2721 //*********************************************************************************
2723 void IOService::PM_idle_timer_expiration ( void )
2727 //*********************************************************************************
2728 // [deprecated] command_received
2729 //*********************************************************************************
2731 void IOService::command_received ( void *statePtr
, void *, void * , void * )
2734 #endif /* !__LP64__ */
2736 //*********************************************************************************
2737 // [public] setAggressiveness
2739 // Pass on the input parameters to all power domain children. All those which are
2740 // power domains will pass it on to their children, etc.
2741 //*********************************************************************************
2743 IOReturn
IOService::setAggressiveness ( unsigned long type
, unsigned long newLevel
)
2745 return kIOReturnSuccess
;
2748 //*********************************************************************************
2749 // [public] getAggressiveness
2751 // Called by the user client.
2752 //*********************************************************************************
2754 IOReturn
IOService::getAggressiveness ( unsigned long type
, unsigned long * currentLevel
)
2756 IOPMrootDomain
* rootDomain
= getPMRootDomain();
2759 return kIOReturnNotReady
;
2761 return rootDomain
->getAggressiveness( type
, currentLevel
);
2764 //*********************************************************************************
2765 // [public] getPowerState
2767 //*********************************************************************************
2769 UInt32
IOService::getPowerState ( void )
2774 return fCurrentPowerState
;
2778 //*********************************************************************************
2779 // [deprecated] systemWake
2781 // Pass this to all power domain children. All those which are
2782 // power domains will pass it on to their children, etc.
2783 //*********************************************************************************
2785 IOReturn
IOService::systemWake ( void )
2789 IOPowerConnection
* connection
;
2790 IOService
* theChild
;
2792 iter
= getChildIterator(gIOPowerPlane
);
2795 while ( (next
= iter
->getNextObject()) )
2797 if ( (connection
= OSDynamicCast(IOPowerConnection
, next
)) )
2799 if (connection
->getReadyFlag() == false)
2801 PM_CONNECT("[%s] %s: connection not ready\n",
2802 getName(), __FUNCTION__
);
2806 theChild
= (IOService
*)connection
->copyChildEntry(gIOPowerPlane
);
2809 theChild
->systemWake();
2810 theChild
->release();
2817 if ( fControllingDriver
!= NULL
)
2819 if ( fControllingDriver
->didYouWakeSystem() )
2828 //*********************************************************************************
2829 // [deprecated] temperatureCriticalForZone
2830 //*********************************************************************************
2832 IOReturn
IOService::temperatureCriticalForZone ( IOService
* whichZone
)
2834 IOService
* theParent
;
2837 OUR_PMLog(kPMLogCriticalTemp
, 0, 0);
2839 if ( inPlane(gIOPowerPlane
) && !IS_PM_ROOT() )
2841 theNub
= (IOService
*)copyParentEntry(gIOPowerPlane
);
2844 theParent
= (IOService
*)theNub
->copyParentEntry(gIOPowerPlane
);
2848 theParent
->temperatureCriticalForZone(whichZone
);
2849 theParent
->release();
2855 #endif /* !__LP64__ */
2857 //*********************************************************************************
2858 // [protected] powerOverrideOnPriv
2859 //*********************************************************************************
2861 IOReturn
IOService::powerOverrideOnPriv ( void )
2863 IOPMRequest
* request
;
2866 return IOPMNotYetInitialized
;
2868 if (gIOPMWorkLoop
->inGate())
2870 fDeviceOverrides
= true;
2874 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOnPriv
);
2876 return kIOReturnNoMemory
;
2878 submitPMRequest( request
);
2882 //*********************************************************************************
2883 // [protected] powerOverrideOffPriv
2884 //*********************************************************************************
2886 IOReturn
IOService::powerOverrideOffPriv ( void )
2888 IOPMRequest
* request
;
2891 return IOPMNotYetInitialized
;
2893 if (gIOPMWorkLoop
->inGate())
2895 fDeviceOverrides
= false;
2899 request
= acquirePMRequest( this, kIOPMRequestTypePowerOverrideOffPriv
);
2901 return kIOReturnNoMemory
;
2903 submitPMRequest( request
);
2907 //*********************************************************************************
2908 // [private] handlePowerOverrideChanged
2909 //*********************************************************************************
2911 void IOService::handlePowerOverrideChanged ( IOPMRequest
* request
)
2913 PM_ASSERT_IN_GATE();
2914 if (request
->getType() == kIOPMRequestTypePowerOverrideOnPriv
)
2916 OUR_PMLog(kPMLogOverrideOn
, 0, 0);
2917 fDeviceOverrides
= true;
2921 OUR_PMLog(kPMLogOverrideOff
, 0, 0);
2922 fDeviceOverrides
= false;
2928 //*********************************************************************************
2929 // [private] startPowerChange
2930 //*********************************************************************************
2932 IOReturn
IOService::startPowerChange (
2933 unsigned long changeFlags
,
2934 unsigned long powerState
,
2935 unsigned long domainFlags
,
2936 IOPowerConnection
* parentConnection
,
2937 unsigned long parentFlags
)
2939 PM_ASSERT_IN_GATE();
2940 assert( fMachineState
== kIOPM_Finished
);
2941 assert( powerState
< fNumberOfPowerStates
);
2943 if (powerState
>= fNumberOfPowerStates
)
2944 return IOPMAckImplied
;
2946 #if ROOT_DOMAIN_RUN_STATES
2947 // Root domain can override chosen power state to a lower state.
2948 getPMRootDomain()->overridePowerStateForService(
2949 this, &fRootDomainState
,
2950 &powerState
, changeFlags
);
2953 // Invalidate the last recorded tickle power state when a power transition
2954 // is about to occur, and not as a result of a tickle request.
2956 if ((getPMRequestType() != kIOPMRequestTypeActivityTickle
) &&
2957 (fActivityTicklePowerState
!= -1))
2959 IOLockLock(fActivityLock
);
2960 fActivityTicklePowerState
= -1;
2961 IOLockUnlock(fActivityLock
);
2964 // Initialize the change note.
2966 fHeadNoteFlags
= changeFlags
;
2967 fHeadNotePowerState
= powerState
;
2968 fHeadNotePowerArrayEntry
= &fPowerStates
[ powerState
];
2969 fHeadNoteParentConnection
= NULL
;
2971 if (changeFlags
& kIOPMWeInitiated
)
2973 if (changeFlags
& kIOPMSynchronize
)
2981 assert(changeFlags
& kIOPMParentInitiated
);
2982 fHeadNoteDomainFlags
= domainFlags
;
2983 fHeadNoteParentFlags
= parentFlags
;
2984 fHeadNoteParentConnection
= parentConnection
;
2985 return ParentChangeStart();
2989 //*********************************************************************************
2990 // [private] notifyInterestedDrivers
2991 //*********************************************************************************
2993 bool IOService::notifyInterestedDrivers ( void )
2995 IOPMinformee
* informee
;
2996 IOPMinformeeList
* list
= fInterestedDrivers
;
2997 DriverCallParam
* param
;
3000 PM_ASSERT_IN_GATE();
3001 assert( fDriverCallParamCount
== 0 );
3002 assert( fHeadNotePendingAcks
== 0 );
3004 fHeadNotePendingAcks
= 0;
3006 count
= list
->numberOfItems();
3008 goto done
; // no interested drivers
3010 // Allocate an array of interested drivers and their return values
3011 // for the callout thread. Everything else is still "owned" by the
3012 // PM work loop, which can run to process acknowledgePowerChange()
3015 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3016 if (count
> fDriverCallParamSlots
)
3018 if (fDriverCallParamSlots
)
3020 assert(fDriverCallParamPtr
);
3021 IODelete(fDriverCallParamPtr
, DriverCallParam
, fDriverCallParamSlots
);
3022 fDriverCallParamPtr
= 0;
3023 fDriverCallParamSlots
= 0;
3026 param
= IONew(DriverCallParam
, count
);
3028 goto done
; // no memory
3030 fDriverCallParamPtr
= (void *) param
;
3031 fDriverCallParamSlots
= count
;
3034 informee
= list
->firstInList();
3036 for (IOItemCount i
= 0; i
< count
; i
++)
3038 informee
->timer
= -1;
3039 param
[i
].Target
= informee
;
3041 informee
= list
->nextInList( informee
);
3044 fDriverCallParamCount
= count
;
3045 fHeadNotePendingAcks
= count
;
3047 // Machine state will be blocked pending callout thread completion.
3050 assert( fLockedFlags
.DriverCallBusy
== false );
3051 fLockedFlags
.DriverCallBusy
= true;
3053 thread_call_enter( fDriverCallEntry
);
3057 // no interested drivers or did not schedule callout thread due to error.
3061 //*********************************************************************************
3062 // [private] notifyInterestedDriversDone
3063 //*********************************************************************************
3065 void IOService::notifyInterestedDriversDone ( void )
3067 IOPMinformee
* informee
;
3069 DriverCallParam
* param
;
3072 PM_ASSERT_IN_GATE();
3073 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3074 count
= fDriverCallParamCount
;
3076 assert( fLockedFlags
.DriverCallBusy
== false );
3077 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
3081 for (IOItemCount i
= 0; i
< count
; i
++, param
++)
3083 informee
= (IOPMinformee
*) param
->Target
;
3084 result
= param
->Result
;
3086 if ((result
== IOPMAckImplied
) || (result
< 0))
3088 // Interested driver return IOPMAckImplied.
3089 // If informee timer is zero, it must have de-registered
3090 // interest during the thread callout. That also drops
3091 // the pending ack count.
3093 if (fHeadNotePendingAcks
&& informee
->timer
)
3094 fHeadNotePendingAcks
--;
3096 informee
->timer
= 0;
3098 else if (informee
->timer
)
3100 assert(informee
->timer
== -1);
3102 // Driver has not acked, and has returned a positive result.
3103 // Enforce a minimum permissible timeout value.
3104 // Make the min value large enough so timeout is less likely
3105 // to occur if a driver misinterpreted that the return value
3106 // should be in microsecond units. And make it large enough
3107 // to be noticeable if a driver neglects to ack.
3109 if (result
< kMinAckTimeoutTicks
)
3110 result
= kMinAckTimeoutTicks
;
3112 informee
->timer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
3114 // else, child has already acked or driver has removed interest,
3115 // and head_note_pendingAcks decremented.
3116 // informee may have been removed from the interested drivers list,
3117 // thus the informee must be retained across the callout.
3119 informee
->release();
3122 fDriverCallParamCount
= 0;
3124 if ( fHeadNotePendingAcks
)
3126 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
3131 // Hop back to original machine state path (from notifyAll)
3132 fMachineState
= fNextMachineState
;
3137 //*********************************************************************************
3138 // [private] notifyChildren
3139 //*********************************************************************************
3141 void IOService::notifyChildren ( void )
3145 IOPowerConnection
* connection
;
3146 OSArray
* children
= 0;
3148 if (fStrictTreeOrder
)
3149 children
= OSArray::withCapacity(8);
3151 // Sum child power consumption in notifyChild()
3152 fHeadNotePowerArrayEntry
->staticPower
= 0;
3154 iter
= getChildIterator(gIOPowerPlane
);
3157 while ((next
= iter
->getNextObject()))
3159 if ((connection
= OSDynamicCast(IOPowerConnection
, next
)))
3161 if (connection
->getReadyFlag() == false)
3163 PM_CONNECT("[%s] %s: connection not ready\n",
3164 getName(), __FUNCTION__
);
3169 children
->setObject( connection
);
3171 notifyChild( connection
,
3172 fDriverCallReason
== kDriverCallInformPreChange
);
3180 if (children
->getCount() == 0)
3182 children
->release();
3187 assert(fNotifyChildArray
== 0);
3188 fNotifyChildArray
= children
;
3189 fNextMachineState
= fMachineState
;
3190 fMachineState
= kIOPM_NotifyChildrenDone
;
3195 //*********************************************************************************
3196 // [private] notifyChildrenDone
3197 //*********************************************************************************
3199 void IOService::notifyChildrenDone ( void )
3201 PM_ASSERT_IN_GATE();
3202 assert(fNotifyChildArray
);
3203 assert(fMachineState
== kIOPM_NotifyChildrenDone
);
3205 // Interested drivers have all acked (if any), ack timer stopped.
3206 // Notify one child, wait for it to ack, then repeat for next child.
3207 // This is a workaround for some drivers with multiple instances at
3208 // the same branch in the power tree, but the driver is slow to power
3209 // up unless the tree ordering is observed. Problem observed only on
3210 // system wake, not on system sleep.
3212 // We have the ability to power off in reverse child index order.
3213 // That works nicely on some machines, but not on all HW configs.
3215 if (fNotifyChildArray
->getCount())
3217 IOPowerConnection
* connection
;
3218 connection
= (IOPowerConnection
*) fNotifyChildArray
->getObject(0);
3219 fNotifyChildArray
->removeObject(0);
3220 notifyChild( connection
, fDriverCallReason
== kDriverCallInformPreChange
);
3224 fNotifyChildArray
->release();
3225 fNotifyChildArray
= 0;
3226 fMachineState
= fNextMachineState
;
3230 //*********************************************************************************
3231 // [private] notifyAll
3232 //*********************************************************************************
3234 IOReturn
IOService::notifyAll ( int nextMachineState
, bool is_prechange
)
3236 // Save the next machine_state to be restored by notifyInterestedDriversDone()
3238 PM_ASSERT_IN_GATE();
3239 fNextMachineState
= nextMachineState
;
3240 fMachineState
= kIOPM_DriverThreadCallDone
;
3241 fDriverCallReason
= is_prechange
?
3242 kDriverCallInformPreChange
: kDriverCallInformPostChange
;
3244 if (!notifyInterestedDrivers())
3245 notifyInterestedDriversDone();
3247 return IOPMWillAckLater
;
3250 //*********************************************************************************
3251 // [private, static] pmDriverCallout
3253 // Thread call context
3254 //*********************************************************************************
3256 IOReturn
IOService::actionDriverCalloutDone (
3258 void * arg0
, void * arg1
,
3259 void * arg2
, void * arg3
)
3261 IOServicePM
* pwrMgt
= (IOServicePM
*) arg0
;
3264 fLockedFlags
.DriverCallBusy
= false;
3267 if (gIOPMReplyQueue
)
3268 gIOPMReplyQueue
->signalWorkAvailable();
3270 return kIOReturnSuccess
;
3273 void IOService::pmDriverCallout ( IOService
* from
)
3276 switch (from
->fDriverCallReason
)
3278 case kDriverCallSetPowerState
:
3279 from
->driverSetPowerState();
3282 case kDriverCallInformPreChange
:
3283 case kDriverCallInformPostChange
:
3284 from
->driverInformPowerChange();
3288 panic("IOService::pmDriverCallout bad machine state %x",
3289 from
->fDriverCallReason
);
3292 gIOPMWorkLoop
->runAction(actionDriverCalloutDone
,
3294 /* arg0 */ (void *) from
->pwrMgt
);
3297 //*********************************************************************************
3298 // [private] driverSetPowerState
3300 // Thread call context
3301 //*********************************************************************************
3303 void IOService::driverSetPowerState ( void )
3306 unsigned long powerState
;
3307 DriverCallParam
* param
;
3311 assert( fLockedFlags
.DriverCallBusy
== true );
3312 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3314 assert( fDriverCallParamCount
== 1 );
3316 driver
= fControllingDriver
;
3317 powerState
= fHeadNotePowerState
;
3319 if (fLockedFlags
.PMStop
== false)
3321 OUR_PMLog( kPMLogProgramHardware
, (uintptr_t) this, powerState
);
3322 clock_get_uptime(&fDriverCallStartTime
);
3323 result
= driver
->setPowerState( powerState
, this );
3324 clock_get_uptime(&end
);
3325 OUR_PMLog((UInt32
) -kPMLogProgramHardware
, (uintptr_t) this, (UInt32
) result
);
3327 #if LOG_SETPOWER_TIMES
3328 if ((result
== IOPMAckImplied
) || (result
< 0))
3332 SUB_ABSOLUTETIME(&end
, &fDriverCallStartTime
);
3333 absolutetime_to_nanoseconds(end
, &nsec
);
3334 if (nsec
> LOG_SETPOWER_TIMES
)
3335 PM_DEBUG("%s::setPowerState(%p, %lu -> %lu) took %d ms\n",
3336 fName
, this, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3341 result
= kIOPMAckImplied
;
3343 param
->Result
= result
;
3346 //*********************************************************************************
3347 // [private] driverInformPowerChange
3349 // Thread call context
3350 //*********************************************************************************
3352 void IOService::driverInformPowerChange ( void )
3355 IOPMinformee
* informee
;
3358 IOPMPowerFlags powerFlags
;
3359 unsigned long powerState
;
3360 DriverCallParam
* param
;
3363 assert( fLockedFlags
.DriverCallBusy
== true );
3364 param
= (DriverCallParam
*) fDriverCallParamPtr
;
3365 count
= fDriverCallParamCount
;
3366 assert( count
&& param
);
3368 powerFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
3369 powerState
= fHeadNotePowerState
;
3371 for (IOItemCount i
= 0; i
< count
; i
++)
3373 informee
= (IOPMinformee
*) param
->Target
;
3374 driver
= informee
->whatObject
;
3376 if ((fLockedFlags
.PMStop
== false) && informee
->active
)
3378 if (fDriverCallReason
== kDriverCallInformPreChange
)
3380 OUR_PMLog(kPMLogInformDriverPreChange
, (uintptr_t) this, powerState
);
3381 clock_get_uptime(&informee
->startTime
);
3382 result
= driver
->powerStateWillChangeTo(powerFlags
, powerState
, this);
3383 clock_get_uptime(&end
);
3384 OUR_PMLog((UInt32
)-kPMLogInformDriverPreChange
, (uintptr_t) this, result
);
3388 OUR_PMLog(kPMLogInformDriverPostChange
, (uintptr_t) this, powerState
);
3389 clock_get_uptime(&informee
->startTime
);
3390 result
= driver
->powerStateDidChangeTo(powerFlags
, powerState
, this);
3391 clock_get_uptime(&end
);
3392 OUR_PMLog((UInt32
)-kPMLogInformDriverPostChange
, (uintptr_t) this, result
);
3395 #if LOG_SETPOWER_TIMES
3396 if ((result
== IOPMAckImplied
) || (result
< 0))
3400 SUB_ABSOLUTETIME(&end
, &informee
->startTime
);
3401 absolutetime_to_nanoseconds(end
, &nsec
);
3402 if (nsec
> LOG_SETPOWER_TIMES
)
3403 PM_DEBUG("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) took %d ms\n",
3405 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
3406 driver
, fName
, fCurrentPowerState
, powerState
, NS_TO_MS(nsec
));
3411 result
= kIOPMAckImplied
;
3413 param
->Result
= result
;
3418 //*********************************************************************************
3419 // [private] notifyChild
3421 // Notify a power domain child of an upcoming power change.
3422 // If the object acknowledges the current change, we return TRUE.
3423 //*********************************************************************************
3425 bool IOService::notifyChild ( IOPowerConnection
* theNub
, bool is_prechange
)
3427 IOReturn ret
= IOPMAckImplied
;
3428 unsigned long childPower
;
3429 IOService
* theChild
;
3430 IOPMRequest
* childRequest
;
3431 uint32_t requestArg2
;
3434 PM_ASSERT_IN_GATE();
3435 theChild
= (IOService
*)(theNub
->copyChildEntry(gIOPowerPlane
));
3442 // Unless the child handles the notification immediately and returns
3443 // kIOPMAckImplied, we'll be awaiting their acknowledgement later.
3444 fHeadNotePendingAcks
++;
3445 theNub
->setAwaitingAck(true);
3447 requestArg2
= fHeadNoteFlags
;
3448 if (fHeadNotePowerState
< fCurrentPowerState
)
3449 requestArg2
|= kIOPMDomainPowerDrop
;
3451 requestType
= is_prechange
?
3452 kIOPMRequestTypePowerDomainWillChange
:
3453 kIOPMRequestTypePowerDomainDidChange
;
3455 childRequest
= acquirePMRequest( theChild
, requestType
);
3459 childRequest
->fArg0
= (void *) fHeadNotePowerArrayEntry
->outputPowerCharacter
;
3460 childRequest
->fArg1
= (void *) theNub
;
3461 childRequest
->fArg2
= (void *) requestArg2
;
3462 theChild
->submitPMRequest( childRequest
);
3463 ret
= IOPMWillAckLater
;
3467 ret
= IOPMAckImplied
;
3468 fHeadNotePendingAcks
--;
3469 theNub
->setAwaitingAck(false);
3470 childPower
= theChild
->currentPowerConsumption();
3471 if ( childPower
== kIOPMUnknown
)
3473 fHeadNotePowerArrayEntry
->staticPower
= kIOPMUnknown
;
3475 if (fHeadNotePowerArrayEntry
->staticPower
!= kIOPMUnknown
)
3476 fHeadNotePowerArrayEntry
->staticPower
+= childPower
;
3480 theChild
->release();
3481 return (IOPMAckImplied
== ret
);
3485 // MARK: Power Change Initiated by Driver
3487 //*********************************************************************************
3488 // [private] OurChangeStart
3490 // Begin the processing of a power change initiated by us.
3491 //*********************************************************************************
3493 void IOService::OurChangeStart ( void )
3495 PM_ASSERT_IN_GATE();
3496 OUR_PMLog( kPMLogStartDeviceChange
, fHeadNotePowerState
, fCurrentPowerState
);
3498 // fMaxCapability is our maximum possible power state based on the current
3499 // power state of our parents. If we are trying to raise power beyond the
3500 // maximum, send an async request for more power to all parents.
3502 if (!IS_PM_ROOT() && (fMaxCapability
< fHeadNotePowerState
))
3504 fHeadNoteFlags
|= kIOPMNotDone
;
3505 requestDomainPower(fHeadNotePowerState
);
3510 // Redundant power changes skips to the end of the state machine.
3512 if (!fInitialChange
&& (fHeadNotePowerState
== fCurrentPowerState
))
3517 fInitialChange
= false;
3519 #if ROOT_DOMAIN_RUN_STATES
3520 // Change started, but may not complete...
3521 // Can be canceled (power drop) or deferred (power rise).
3523 getPMRootDomain()->handlePowerChangeStartForService(
3525 /* RD flags */ &fRootDomainState
,
3526 /* new pwr state */ fHeadNotePowerState
,
3527 /* change flags */ fHeadNoteFlags
);
3530 // Two separate paths, depending if power is being raised or lowered.
3531 // Lowering power is subject to approval by clients of this service.
3535 // Next machine state for a power drop.
3536 fMachineState
= kIOPM_OurChangeTellClientsPowerDown
;
3537 fDoNotPowerDown
= false;
3539 // Ask apps and kernel clients permission to lower power.
3540 fOutOfBandParameter
= kNotifyApps
;
3541 askChangeDown(fHeadNotePowerState
);
3545 // This service is raising power and parents are able to support the
3546 // new power state. However a parent may have already committed to
3547 // drop power, which might force this object to temporarily drop power.
3548 // This results in "oscillations" before the state machines converge
3549 // to a steady state.
3551 // To prevent this, a child must make a power reservation against all
3552 // parents before raising power. If the reservation fails, indicating
3553 // that the child will be unable to sustain the higher power state,
3554 // then the child will signal the parent to adjust power, and the child
3555 // will defer its power change.
3557 #if RESERVE_DOMAIN_POWER
3560 // Reserve parent power necessary to achieve fHeadNotePowerState.
3561 ret
= requestDomainPower( fHeadNotePowerState
, kReserveDomainPower
);
3562 if (ret
!= kIOReturnSuccess
)
3564 // Reservation failed, defer power rise.
3565 fHeadNoteFlags
|= kIOPMNotDone
;
3570 // Notify interested drivers and children.
3571 notifyAll( kIOPM_OurChangeSetPowerState
, kNotifyWillChange
);
3575 //*********************************************************************************
3577 struct IOPMRequestDomainPowerContext
{
3578 IOService
* child
; // the requesting child
3579 IOPMPowerFlags requestPowerFlags
; // power flags requested by child
3583 requestDomainPowerApplier(
3584 IORegistryEntry
* entry
,
3587 IOPowerConnection
* connection
;
3589 IOPMRequestDomainPowerContext
* context
;
3591 if ((connection
= OSDynamicCast(IOPowerConnection
, entry
)) == 0)
3593 parent
= (IOService
*) connection
->copyParentEntry(gIOPowerPlane
);
3598 context
= (IOPMRequestDomainPowerContext
*) inContext
;
3600 if (connection
->parentKnowsState() && connection
->getReadyFlag())
3602 parent
->requestPowerDomainState(
3603 context
->requestPowerFlags
,
3611 //*********************************************************************************
3612 // [private] requestDomainPower
3613 //*********************************************************************************
3615 IOReturn
IOService::requestDomainPower(
3616 unsigned long ourPowerState
,
3617 IOOptionBits options
)
3619 const IOPMPowerState
* powerStateEntry
;
3620 IOPMPowerFlags requestPowerFlags
;
3621 unsigned long maxPowerState
;
3622 IOPMRequestDomainPowerContext context
;
3624 PM_ASSERT_IN_GATE();
3625 assert(ourPowerState
< fNumberOfPowerStates
);
3626 if (ourPowerState
>= fNumberOfPowerStates
)
3627 return kIOReturnBadArgument
;
3629 return kIOReturnSuccess
;
3631 // Fetch the input power flags for the requested power state.
3632 // Parent request is stated in terms of required power flags.
3634 powerStateEntry
= &fPowerStates
[ourPowerState
];
3635 requestPowerFlags
= powerStateEntry
->inputPowerRequirement
;
3637 if (powerStateEntry
->capabilityFlags
& (kIOPMChildClamp
| kIOPMPreventIdleSleep
))
3638 requestPowerFlags
|= kIOPMPreventIdleSleep
;
3639 if (powerStateEntry
->capabilityFlags
& (kIOPMChildClamp2
| kIOPMPreventSystemSleep
))
3640 requestPowerFlags
|= kIOPMPreventSystemSleep
;
3642 // Disregard the "previous request" for power reservation.
3644 if (((options
& kReserveDomainPower
) == 0) &&
3645 (fPreviousRequest
== requestPowerFlags
))
3647 // skip if domain already knows our requirements
3650 fPreviousRequest
= requestPowerFlags
;
3652 context
.child
= this;
3653 context
.requestPowerFlags
= requestPowerFlags
;
3654 fHeadNoteDomainTargetFlags
= 0;
3655 applyToParents(requestDomainPowerApplier
, &context
, gIOPowerPlane
);
3657 if (options
& kReserveDomainPower
)
3659 maxPowerState
= fControllingDriver
->maxCapabilityForDomainState(
3660 fHeadNoteDomainTargetFlags
);
3662 if (maxPowerState
< fHeadNotePowerState
)
3664 PM_TRACE("%s: power desired %u:0x%x got %u:0x%x\n",
3666 (uint32_t) ourPowerState
, (uint32_t) requestPowerFlags
,
3667 (uint32_t) maxPowerState
, (uint32_t) fHeadNoteDomainTargetFlags
);
3668 return kIOReturnNoPower
;
3673 return kIOReturnSuccess
;
3676 //*********************************************************************************
3677 // [private] OurSyncStart
3678 //*********************************************************************************
3680 void IOService::OurSyncStart ( void )
3682 PM_ASSERT_IN_GATE();
3687 #if ROOT_DOMAIN_RUN_STATES
3688 getPMRootDomain()->handlePowerChangeStartForService(
3690 /* RD flags */ &fRootDomainState
,
3691 /* new pwr state */ fHeadNotePowerState
,
3692 /* change flags */ fHeadNoteFlags
);
3695 fMachineState
= kIOPM_SyncNotifyDidChange
;
3696 fDriverCallReason
= kDriverCallInformPreChange
;
3701 //*********************************************************************************
3702 // [private] OurChangeTellClientsPowerDown
3704 // All registered applications and kernel clients have positively acknowledged our
3705 // intention of lowering power. Here we notify them all that we will definitely
3706 // lower the power. If we don't have to wait for any of them to acknowledge, we
3707 // carry on by notifying interested drivers. Otherwise, we do wait.
3708 //*********************************************************************************
3710 void IOService::OurChangeTellClientsPowerDown ( void )
3712 fMachineState
= kIOPM_OurChangeTellPriorityClientsPowerDown
;
3713 tellChangeDown1(fHeadNotePowerState
);
3716 //*********************************************************************************
3717 // [private] OurChangeTellPriorityClientsPowerDown
3719 // All registered applications and kernel clients have positively acknowledged our
3720 // intention of lowering power. Here we notify "priority" clients that we are
3721 // lowering power. If we don't have to wait for any of them to acknowledge, we
3722 // carry on by notifying interested drivers. Otherwise, we do wait.
3723 //*********************************************************************************
3725 void IOService::OurChangeTellPriorityClientsPowerDown ( void )
3727 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversWillChange
;
3728 tellChangeDown2(fHeadNotePowerState
);
3731 //*********************************************************************************
3732 // [private] OurChangeNotifyInterestedDriversWillChange
3734 // All registered applications and kernel clients have acknowledged our notification
3735 // that we are lowering power. Here we notify interested drivers. If we don't have
3736 // to wait for any of them to acknowledge, we instruct our power driver to make the
3737 // change. Otherwise, we do wait.
3738 //*********************************************************************************
3740 void IOService::OurChangeNotifyInterestedDriversWillChange ( void )
3742 IOPMrootDomain
*rootDomain
;
3743 if ((rootDomain
= getPMRootDomain()) == this)
3745 rootDomain
->tracePoint(kIOPMTracePointSystemSleepDriversPhase
);
3748 notifyAll( kIOPM_OurChangeSetPowerState
, kNotifyWillChange
);
3751 //*********************************************************************************
3752 // [private] OurChangeSetPowerState
3754 // All interested drivers have acknowledged our pre-change notification of a power
3755 // change we initiated. Here we instruct our controlling driver to make
3756 // the change to the hardware. If it does so, we continue processing
3757 // (waiting for settle and notifying interested parties post-change.)
3758 // If it doesn't, we have to wait for it to acknowledge and then continue.
3759 //*********************************************************************************
3761 void IOService::OurChangeSetPowerState ( void )
3763 fNextMachineState
= kIOPM_OurChangeWaitForPowerSettle
;
3764 fMachineState
= kIOPM_DriverThreadCallDone
;
3765 fDriverCallReason
= kDriverCallSetPowerState
;
3767 if (notifyControllingDriver() == false)
3768 notifyControllingDriverDone();
3771 //*********************************************************************************
3772 // [private] OurChangeWaitForPowerSettle
3774 // Our controlling driver has changed power state on the hardware
3775 // during a power change we initiated. Wait for the driver specified
3776 // settle time to expire, before notifying interested parties post-change.
3777 //*********************************************************************************
3779 void IOService::OurChangeWaitForPowerSettle( void )
3781 fMachineState
= kIOPM_OurChangeNotifyInterestedDriversDidChange
;
3785 //*********************************************************************************
3786 // [private] OurChangeNotifyInterestedDriversDidChange
3788 // Power has settled on a power change we initiated. Here we notify
3789 // all our interested parties post-change. If they all acknowledge, we're
3790 // done with this change note, and we can start on the next one.
3791 // Otherwise we have to wait for acknowledgements and finish up later.
3792 //*********************************************************************************
3794 void IOService::OurChangeNotifyInterestedDriversDidChange ( void )
3796 notifyAll( kIOPM_OurChangeFinish
, kNotifyDidChange
);
3799 //*********************************************************************************
3800 // [private] OurChangeFinish
3802 // Power has settled on a power change we initiated, and
3803 // all our interested parties have acknowledged. We're
3804 // done with this change note, and we can start on the next one.
3805 //*********************************************************************************
3807 void IOService::OurChangeFinish ( void )
3813 // MARK: Power Change Initiated by Parent
3815 //*********************************************************************************
3816 // [private] ParentChangeStart
3818 // Here we begin the processing of a power change initiated by our parent.
3819 //*********************************************************************************
3821 IOReturn
IOService::ParentChangeStart ( void )
3823 PM_ASSERT_IN_GATE();
3824 OUR_PMLog( kPMLogStartParentChange
, fHeadNotePowerState
, fCurrentPowerState
);
3826 // Power domain is lowering power
3827 if ( fHeadNotePowerState
< fCurrentPowerState
)
3829 // TODO: redundant? See handlePowerDomainWillChangeTo()
3830 setParentInfo( fHeadNoteParentFlags
, fHeadNoteParentConnection
, true );
3832 #if ROOT_DOMAIN_RUN_STATES
3833 getPMRootDomain()->handlePowerChangeStartForService(
3835 /* RD flags */ &fRootDomainState
,
3836 /* new pwr state */ fHeadNotePowerState
,
3837 /* change flags */ fHeadNoteFlags
);
3840 // tell apps and kernel clients
3841 fInitialChange
= false;
3842 fMachineState
= kIOPM_ParentDownTellPriorityClientsPowerDown
;
3843 tellChangeDown1(fHeadNotePowerState
);
3844 return IOPMWillAckLater
;
3847 // Power domain is raising power
3848 if ( fHeadNotePowerState
> fCurrentPowerState
)
3850 if ( fDesiredPowerState
> fCurrentPowerState
)
3852 if ( fDesiredPowerState
< fHeadNotePowerState
)
3854 // We power up, but not all the way
3855 fHeadNotePowerState
= fDesiredPowerState
;
3856 fHeadNotePowerArrayEntry
= &fPowerStates
[fDesiredPowerState
];
3857 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
3860 // We don't need to change
3861 fHeadNotePowerState
= fCurrentPowerState
;
3862 fHeadNotePowerArrayEntry
= &fPowerStates
[fCurrentPowerState
];
3863 OUR_PMLog(kPMLogAmendParentChange
, fHeadNotePowerState
, 0);
3867 if ( fHeadNoteFlags
& kIOPMDomainDidChange
)
3869 if ( fHeadNotePowerState
> fCurrentPowerState
)
3871 #if ROOT_DOMAIN_RUN_STATES
3872 getPMRootDomain()->handlePowerChangeStartForService(
3874 /* RD flags */ &fRootDomainState
,
3875 /* new pwr state */ fHeadNotePowerState
,
3876 /* change flags */ fHeadNoteFlags
);
3879 // Parent did change up - start our change up
3880 fInitialChange
= false;
3881 notifyAll( kIOPM_ParentUpSetPowerState
, kNotifyWillChange
);
3882 return IOPMWillAckLater
;
3884 else if (fHeadNoteFlags
& kIOPMSynchronize
)
3886 // We do not need to change power state, but notify
3887 // children to propagate tree synchronization.
3888 fMachineState
= kIOPM_SyncNotifyDidChange
;
3889 fDriverCallReason
= kDriverCallInformPreChange
;
3891 return IOPMWillAckLater
;
3896 return IOPMAckImplied
;
3899 //*********************************************************************************
3900 // [private] ParentDownTellPriorityClientsPowerDown
3902 // All applications and kernel clients have been notified of a power lowering
3903 // initiated by the parent and we had to wait for responses. Here
3904 // we notify any priority clients. If they all ack, we continue with the power change.
3905 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
3906 //*********************************************************************************
3908 void IOService::ParentDownTellPriorityClientsPowerDown ( void )
3910 fMachineState
= kIOPM_ParentDownNotifyInterestedDriversWillChange
;
3911 tellChangeDown2(fHeadNotePowerState
);
3914 //*********************************************************************************
3915 // [private] ParentDownNotifyInterestedDriversWillChange
3917 // All applications and kernel clients have been notified of a power lowering
3918 // initiated by the parent and we had to wait for their responses. Here we notify
3919 // any interested drivers and power domain children. If they all ack, we continue
3920 // with the power change.
3921 // If at least one doesn't, we have to wait for it to acknowledge and then continue.
3922 //*********************************************************************************
3924 void IOService::ParentDownNotifyInterestedDriversWillChange ( void )
3926 IOPMrootDomain
*rootDomain
;
3927 if ((rootDomain
= getPMRootDomain()) == this)
3929 rootDomain
->tracePoint(kIOPMTracePointSystemSleepDriversPhase
);
3932 notifyAll( kIOPM_ParentDownSetPowerState
, kNotifyWillChange
);
3935 //*********************************************************************************
3936 // [private] ParentDownSetPowerState
3938 // We had to wait for it, but all parties have acknowledged our pre-change
3939 // notification of a power lowering initiated by the parent.
3940 // Here we instruct our controlling driver
3941 // to put the hardware in the state it needs to be in when the domain is
3942 // lowered. If it does so, we continue processing
3943 // (waiting for settle and acknowledging the parent.)
3944 // If it doesn't, we have to wait for it to acknowledge and then continue.
3945 //*********************************************************************************
3947 void IOService::ParentDownSetPowerState ( void )
3949 fNextMachineState
= kIOPM_ParentDownWaitForPowerSettle
;
3950 fMachineState
= kIOPM_DriverThreadCallDone
;
3951 fDriverCallReason
= kDriverCallSetPowerState
;
3953 if (notifyControllingDriver() == false)
3954 notifyControllingDriverDone();
3957 //*********************************************************************************
3958 // [private] ParentDownWaitForPowerSettle
3960 // Our controlling driver has changed power state on the hardware
3961 // during a power change initiated by our parent. We have had to wait
3962 // for acknowledgement from interested parties, or we have had to wait
3963 // for the controlling driver to change the state. Here we see if we need
3964 // to wait for power to settle before continuing. If not, we continue
3965 // processing (acknowledging our preparedness to the parent).
3966 // If so, we wait and continue later.
3967 //*********************************************************************************
3969 void IOService::ParentDownWaitForPowerSettle ( void )
3971 fMachineState
= kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange
;
3975 //*********************************************************************************
3976 // [private] ParentDownNotifyDidChangeAndAcknowledgeChange
3978 // Power has settled on a power change initiated by our parent. Here we
3979 // notify interested parties.
3980 //*********************************************************************************
3982 void IOService::ParentDownNotifyDidChangeAndAcknowledgeChange ( void )
3984 notifyAll( kIOPM_ParentAcknowledgePowerChange
, kNotifyDidChange
);
3987 //*********************************************************************************
3988 // [private] ParentAcknowledgePowerChange
3990 // We had to wait for it, but all parties have acknowledged our post-change
3991 // notification of a power change (either Up or Down) initiated by the parent.
3992 // Here we acknowledge the parent.
3993 //*********************************************************************************
3995 void IOService::ParentAcknowledgePowerChange ( void )
3997 IORegistryEntry
* nub
;
4000 nub
= fHeadNoteParentConnection
;
4003 parent
= (IOService
*)nub
->copyParentEntry(gIOPowerPlane
);
4006 parent
->acknowledgePowerChange((IOService
*)nub
);
4012 //*********************************************************************************
4013 // [private] ParentUpSetPowerState
4015 // Our parent has informed us via powerStateDidChange that it has
4016 // raised the power in our power domain, and we have had to wait
4017 // for some interested party to acknowledge our notification.
4018 // Here we instruct our controlling
4019 // driver to program the hardware to take advantage of the higher domain
4020 // power. If it does so, we continue processing
4021 // (waiting for settle and notifying interested parties post-change.)
4022 // If it doesn't, we have to wait for it to acknowledge and then continue.
4023 //*********************************************************************************
4025 void IOService::ParentUpSetPowerState ( void )
4027 fNextMachineState
= kIOPM_ParentUpWaitForSettleTime
;
4028 fMachineState
= kIOPM_DriverThreadCallDone
;
4029 fDriverCallReason
= kDriverCallSetPowerState
;
4031 if (notifyControllingDriver() == false)
4032 notifyControllingDriverDone();
4035 //*********************************************************************************
4036 // [private] ParentUpWaitForSettleTime
4038 // Our controlling driver has changed power state on the hardware
4039 // during a power raise initiated by the parent, but we had to wait for it.
4040 // Here we see if we need to wait for power to settle before continuing.
4041 // If not, we continue processing (notifying interested parties post-change).
4042 // If so, we wait and continue later.
4043 //*********************************************************************************
4045 void IOService::ParentUpWaitForSettleTime ( void )
4047 fMachineState
= kIOPM_ParentUpNotifyInterestedDriversDidChange
;
4051 //*********************************************************************************
4052 // [private] ParentUpNotifyInterestedDriversDidChange
4054 // Power has settled on a power raise initiated by the parent.
4055 // Here we notify all our interested parties post-change. If they all acknowledge,
4056 // we're done with this change note, and we can start on the next one.
4057 // Otherwise we have to wait for acknowledgements and finish up later.
4058 //*********************************************************************************
4060 void IOService::ParentUpNotifyInterestedDriversDidChange ( void )
4062 notifyAll( kIOPM_ParentAcknowledgePowerChange
, kNotifyDidChange
);
4065 //*********************************************************************************
4066 // [private] all_done
4068 // A power change is complete, and the used post-change note is at
4069 // the head of the queue. Remove it and set myCurrentState to the result
4070 // of the change. Start up the next change in queue.
4071 //*********************************************************************************
4073 void IOService::all_done ( void )
4075 unsigned long previous_state
;
4077 #if ROOT_DOMAIN_RUN_STATES
4078 getPMRootDomain()->handlePowerChangeDoneForService(
4080 /* RD flags */ &fRootDomainState
,
4081 /* new pwr state */ fHeadNotePowerState
,
4082 /* change flags */ fHeadNoteFlags
);
4085 if ((fHeadNoteFlags
& kIOPMSynchronize
) &&
4086 ((fMachineState
== kIOPM_Finished
) || (fMachineState
== kIOPM_SyncFinish
)))
4088 // Sync operation and no power change occurred.
4089 // Do not inform driver and clients about this request completion,
4090 // except for the originator (root domain).
4092 if (getPMRequestType() == kIOPMRequestTypeSynchronizePowerTree
)
4094 powerChangeDone(fCurrentPowerState
);
4097 fMachineState
= kIOPM_Finished
;
4101 fMachineState
= kIOPM_Finished
;
4104 if ( fHeadNoteFlags
& kIOPMWeInitiated
)
4106 // could our driver switch to the new state?
4107 if ( !( fHeadNoteFlags
& kIOPMNotDone
) )
4109 // we changed, tell our parent
4110 requestDomainPower(fHeadNotePowerState
);
4112 // yes, did power raise?
4113 if ( fCurrentPowerState
< fHeadNotePowerState
)
4115 // yes, inform clients and apps
4116 tellChangeUp (fHeadNotePowerState
);
4118 previous_state
= fCurrentPowerState
;
4120 fCurrentPowerState
= fHeadNotePowerState
;
4122 fPMVars
->myCurrentState
= fCurrentPowerState
;
4124 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, 0);
4126 // inform subclass policy-maker
4127 if ((fLockedFlags
.PMStop
== false) && fParentsKnowState
)
4128 powerChangeDone(previous_state
);
4130 PM_DEBUG("%s::powerChangeDone() skipped\n", getName());
4134 // parent's power change
4135 if ( fHeadNoteFlags
& kIOPMParentInitiated
)
4137 if (((fHeadNoteFlags
& kIOPMDomainWillChange
) && (fCurrentPowerState
>= fHeadNotePowerState
)) ||
4138 ((fHeadNoteFlags
& kIOPMDomainDidChange
) && (fCurrentPowerState
< fHeadNotePowerState
)))
4141 if ( fCurrentPowerState
< fHeadNotePowerState
)
4143 // yes, inform clients and apps
4144 tellChangeUp (fHeadNotePowerState
);
4147 previous_state
= fCurrentPowerState
;
4148 fCurrentPowerState
= fHeadNotePowerState
;
4150 fPMVars
->myCurrentState
= fCurrentPowerState
;
4152 fMaxCapability
= fControllingDriver
->maxCapabilityForDomainState(fHeadNoteDomainFlags
);
4154 OUR_PMLog(kPMLogChangeDone
, fCurrentPowerState
, 0);
4156 // inform subclass policy-maker
4157 if ((fLockedFlags
.PMStop
== false) && fParentsKnowState
)
4158 powerChangeDone(previous_state
);
4160 PM_DEBUG("%s::powerChangeDone() skipped\n", getName());
4164 if (fCurrentPowerState
< fNumberOfPowerStates
)
4166 const IOPMPowerState
* powerStatePtr
= &fPowerStates
[fCurrentPowerState
];
4168 fCurrentCapabilityFlags
= powerStatePtr
->capabilityFlags
;
4169 if (fCurrentCapabilityFlags
& kIOPMStaticPowerValid
)
4170 fCurrentPowerConsumption
= powerStatePtr
->staticPower
;
4173 // When power rises enough to satisfy the tickle's desire for more power,
4174 // the condition preventing idle-timer from dropping power is removed.
4176 if (fCurrentPowerState
>= fIdleTimerMinPowerState
)
4178 fIdleTimerMinPowerState
= 0;
4182 //*********************************************************************************
4183 // [public] settleTimerExpired
4185 // Power has settled after our last change. Notify interested parties that
4186 // there is a new power state.
4187 //*********************************************************************************
4189 void IOService::settleTimerExpired ( void )
4194 //*********************************************************************************
4195 // settle_timer_expired
4197 // Holds a retain while the settle timer callout is in flight.
4198 //*********************************************************************************
4201 settle_timer_expired( thread_call_param_t arg0
, thread_call_param_t arg1
)
4203 IOService
* me
= (IOService
*) arg0
;
4205 if (gIOPMWorkLoop
&& gIOPMReplyQueue
)
4207 gIOPMWorkLoop
->runAction(
4208 OSMemberFunctionCast(IOWorkLoop::Action
, me
, &IOService::settleTimerExpired
),
4210 gIOPMReplyQueue
->signalWorkAvailable();
4215 //*********************************************************************************
4216 // [private] startSettleTimer
4218 // Calculate a power-settling delay in microseconds and start a timer.
4219 //*********************************************************************************
4221 void IOService::startSettleTimer( void )
4223 AbsoluteTime deadline
;
4225 uint32_t settleTime
= 0;
4228 PM_ASSERT_IN_GATE();
4230 i
= fCurrentPowerState
;
4233 if ( fHeadNotePowerState
< fCurrentPowerState
)
4235 while ( i
> fHeadNotePowerState
)
4237 settleTime
+= (uint32_t) fPowerStates
[i
].settleDownTime
;
4243 if ( fHeadNotePowerState
> fCurrentPowerState
)
4245 while ( i
< fHeadNotePowerState
)
4247 settleTime
+= (uint32_t) fPowerStates
[i
+1].settleUpTime
;
4255 clock_interval_to_deadline(settleTime
, kMicrosecondScale
, &deadline
);
4256 pending
= thread_call_enter_delayed(fSettleTimer
, deadline
);
4257 if (pending
) release();
4261 //*********************************************************************************
4262 // [private] ackTimerTick
4264 // The acknowledgement timeout periodic timer has ticked.
4265 // If we are awaiting acks for a power change notification,
4266 // we decrement the timer word of each interested driver which hasn't acked.
4267 // If a timer word becomes zero, we pretend the driver aknowledged.
4268 // If we are waiting for the controlling driver to change the power
4269 // state of the hardware, we decrement its timer word, and if it becomes
4270 // zero, we pretend the driver acknowledged.
4272 // Returns true if the timer tick made it possible to advance to the next
4273 // machine state, false otherwise.
4274 //*********************************************************************************
4277 void IOService::ack_timer_ticked ( void )
4281 #endif /* !__LP64__ */
4283 bool IOService::ackTimerTick( void )
4285 IOPMinformee
* nextObject
;
4288 PM_ASSERT_IN_GATE();
4289 switch (fMachineState
) {
4290 case kIOPM_OurChangeWaitForPowerSettle
:
4291 case kIOPM_ParentDownWaitForPowerSettle
:
4292 case kIOPM_ParentUpWaitForSettleTime
:
4293 // are we waiting for controlling driver to acknowledge?
4294 if ( fDriverTimer
> 0 )
4296 // yes, decrement timer tick
4298 if ( fDriverTimer
== 0 )
4300 // controlling driver is tardy
4301 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
4302 OUR_PMLog(kPMLogCtrlDriverTardy
, 0, 0);
4303 setProperty(kIOPMTardyAckSPSKey
, kOSBooleanTrue
);
4304 PM_ERROR("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms\n",
4305 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
4307 if (gIOKitDebug
& kIOLogDebugPower
)
4309 panic("%s::setPowerState(%p, %lu -> %lu) timed out after %d ms",
4310 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
4314 // Unblock state machine and pretend driver has acked.
4318 // still waiting, set timer again
4324 case kIOPM_OurChangeSetPowerState
:
4325 case kIOPM_OurChangeFinish
:
4326 case kIOPM_ParentDownSetPowerState
:
4327 case kIOPM_ParentAcknowledgePowerChange
:
4328 case kIOPM_ParentUpSetPowerState
:
4329 case kIOPM_NotifyChildrenDone
:
4330 // are we waiting for interested parties to acknowledge?
4331 if ( fHeadNotePendingAcks
!= 0 )
4333 // yes, go through the list of interested drivers
4334 nextObject
= fInterestedDrivers
->firstInList();
4335 // and check each one
4336 while ( nextObject
!= NULL
)
4338 if ( nextObject
->timer
> 0 )
4340 nextObject
->timer
--;
4341 // this one should have acked by now
4342 if ( nextObject
->timer
== 0 )
4344 uint64_t nsec
= computeTimeDeltaNS(&nextObject
->startTime
);
4345 OUR_PMLog(kPMLogIntDriverTardy
, 0, 0);
4346 nextObject
->whatObject
->setProperty(kIOPMTardyAckPSCKey
, kOSBooleanTrue
);
4347 PM_ERROR("%s::powerState%sChangeTo(%p, %s, %lu -> %lu) timed out after %d ms\n",
4348 nextObject
->whatObject
->getName(),
4349 (fDriverCallReason
== kDriverCallInformPreChange
) ? "Will" : "Did",
4350 nextObject
->whatObject
, fName
, fCurrentPowerState
, fHeadNotePowerState
,
4353 // Pretend driver has acked.
4354 fHeadNotePendingAcks
--;
4357 nextObject
= fInterestedDrivers
->nextInList(nextObject
);
4360 // is that the last?
4361 if ( fHeadNotePendingAcks
== 0 )
4363 // yes, we can continue
4366 // no, set timer again
4372 case kIOPM_ParentDownTellPriorityClientsPowerDown
:
4373 case kIOPM_ParentDownNotifyInterestedDriversWillChange
:
4374 case kIOPM_OurChangeTellClientsPowerDown
:
4375 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
4376 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
4377 // apps didn't respond in time
4378 cleanClientResponses(true);
4379 OUR_PMLog(kPMLogClientTardy
, 0, 1);
4380 // tardy equates to approval
4385 PM_TRACE("%s: unexpected ack timer tick (state = %d)\n",
4386 getName(), fMachineState
);
4392 //*********************************************************************************
4393 // [private] start_ack_timer
4394 //*********************************************************************************
4396 void IOService::start_ack_timer ( void )
4398 start_ack_timer( ACK_TIMER_PERIOD
, kNanosecondScale
);
4401 void IOService::start_ack_timer ( UInt32 interval
, UInt32 scale
)
4403 AbsoluteTime deadline
;
4406 clock_interval_to_deadline(interval
, scale
, &deadline
);
4409 pending
= thread_call_enter_delayed(fAckTimer
, deadline
);
4410 if (pending
) release();
4413 //*********************************************************************************
4414 // [private] stop_ack_timer
4415 //*********************************************************************************
4417 void IOService::stop_ack_timer ( void )
4421 pending
= thread_call_cancel(fAckTimer
);
4422 if (pending
) release();
4425 //*********************************************************************************
4426 // [static] actionAckTimerExpired
4428 // Inside PM work loop's gate.
4429 //*********************************************************************************
4432 IOService::actionAckTimerExpired (
4434 void * arg0
, void * arg1
,
4435 void * arg2
, void * arg3
)
4437 IOService
* me
= (IOService
*) target
;
4440 // done will be true if the timer tick unblocks the machine state,
4441 // otherwise no need to signal the work loop.
4443 done
= me
->ackTimerTick();
4444 if (done
&& gIOPMReplyQueue
)
4445 gIOPMReplyQueue
->signalWorkAvailable();
4447 return kIOReturnSuccess
;
4450 //*********************************************************************************
4451 // ack_timer_expired
4453 // Thread call function. Holds a retain while the callout is in flight.
4454 //*********************************************************************************
4457 IOService::ack_timer_expired ( thread_call_param_t arg0
, thread_call_param_t arg1
)
4459 IOService
* me
= (IOService
*) arg0
;
4463 gIOPMWorkLoop
->runAction(&actionAckTimerExpired
, me
);
4468 //*********************************************************************************
4469 // [private] notifyControllingDriver
4470 //*********************************************************************************
4472 bool IOService::notifyControllingDriver ( void )
4474 DriverCallParam
* param
;
4475 unsigned long powerState
;
4477 PM_ASSERT_IN_GATE();
4478 assert( fDriverCallParamCount
== 0 );
4479 assert( fControllingDriver
);
4481 powerState
= fHeadNotePowerState
;
4483 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4486 param
= IONew(DriverCallParam
, 1);
4488 return false; // no memory
4490 fDriverCallParamPtr
= (void *) param
;
4491 fDriverCallParamSlots
= 1;
4494 param
->Target
= fControllingDriver
;
4495 fDriverCallParamCount
= 1;
4499 // Machine state for this object will stall waiting for a reply
4500 // from the callout thread.
4503 assert( fLockedFlags
.DriverCallBusy
== false );
4504 fLockedFlags
.DriverCallBusy
= true;
4506 thread_call_enter( fDriverCallEntry
);
4510 //*********************************************************************************
4511 // [private] notifyControllingDriverDone
4512 //*********************************************************************************
4514 void IOService::notifyControllingDriverDone( void )
4516 DriverCallParam
* param
;
4519 PM_ASSERT_IN_GATE();
4520 param
= (DriverCallParam
*) fDriverCallParamPtr
;
4522 assert( fLockedFlags
.DriverCallBusy
== false );
4523 assert( fMachineState
== kIOPM_DriverThreadCallDone
);
4527 assert(fDriverCallParamCount
== 1);
4529 // the return value from setPowerState()
4530 result
= param
->Result
;
4532 if ((result
== IOPMAckImplied
) || (result
< 0))
4534 // child return IOPMAckImplied
4537 else if (fDriverTimer
)
4539 assert(fDriverTimer
== -1);
4541 // Driver has not acked, and has returned a positive result.
4542 // Enforce a minimum permissible timeout value.
4543 // Make the min value large enough so timeout is less likely
4544 // to occur if a driver misinterpreted that the return value
4545 // should be in microsecond units. And make it large enough
4546 // to be noticeable if a driver neglects to ack.
4548 if (result
< kMinAckTimeoutTicks
)
4549 result
= kMinAckTimeoutTicks
;
4551 fDriverTimer
= (result
/ (ACK_TIMER_PERIOD
/ ns_per_us
)) + 1;
4553 // else, child has already acked and driver_timer reset to 0.
4555 fDriverCallParamCount
= 0;
4559 OUR_PMLog(kPMLogStartAckTimer
, 0, 0);
4564 // Hop back to original machine state path.
4565 fMachineState
= fNextMachineState
;
4568 //*********************************************************************************
4569 // [public] askChangeDown
4571 // Ask registered applications and kernel clients if we can change to a lower
4574 // Subclass can override this to send a different message type. Parameter is
4575 // the destination state number.
4577 // Return true if we don't have to wait for acknowledgements
4578 //*********************************************************************************
4580 bool IOService::askChangeDown ( unsigned long stateNum
)
4582 return tellClientsWithResponse( kIOMessageCanDevicePowerOff
);
4585 //*********************************************************************************
4586 // [private] tellChangeDown1
4588 // Notify registered applications and kernel clients that we are definitely
4591 // Return true if we don't have to wait for acknowledgements
4592 //*********************************************************************************
4594 bool IOService::tellChangeDown1 ( unsigned long stateNum
)
4596 fOutOfBandParameter
= kNotifyApps
;
4597 return tellChangeDown(stateNum
);
4600 //*********************************************************************************
4601 // [private] tellChangeDown2
4603 // Notify priority clients that we are definitely dropping power.
4605 // Return true if we don't have to wait for acknowledgements
4606 //*********************************************************************************
4608 bool IOService::tellChangeDown2 ( unsigned long stateNum
)
4610 fOutOfBandParameter
= kNotifyPriority
;
4611 return tellChangeDown(stateNum
);
4614 //*********************************************************************************
4615 // [public] tellChangeDown
4617 // Notify registered applications and kernel clients that we are definitely
4620 // Subclass can override this to send a different message type. Parameter is
4621 // the destination state number.
4623 // Return true if we don't have to wait for acknowledgements
4624 //*********************************************************************************
4626 bool IOService::tellChangeDown ( unsigned long stateNum
)
4628 return tellClientsWithResponse( kIOMessageDeviceWillPowerOff
);
4631 //*********************************************************************************
4632 // cleanClientResponses
4634 //*********************************************************************************
4636 static void logAppTimeouts ( OSObject
* object
, void * arg
)
4638 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
4640 unsigned int clientIndex
;
4642 if (OSDynamicCast(_IOServiceInterestNotifier
, object
))
4644 // Discover the 'counter' value or index assigned to this client
4645 // when it was notified, by searching for the array index of the
4646 // client in an array holding the cached interested clients.
4648 clientIndex
= context
->notifyClients
->getNextIndexOfObject(object
, 0);
4650 if ((clientIndex
!= (unsigned int) -1) &&
4651 (flag
= context
->responseFlags
->getObject(clientIndex
)) &&
4652 (flag
!= kOSBooleanTrue
))
4654 OSString
* clientID
= 0;
4655 context
->us
->messageClient(context
->msgType
, object
, &clientID
);
4656 PM_ERROR(context
->errorLog
, clientID
? clientID
->getCStringNoCopy() : "");
4658 // TODO: record message type if possible
4659 IOService::getPMRootDomain()->pmStatsRecordApplicationResponse(
4660 gIOPMStatsApplicationResponseTimedOut
,
4661 clientID
? clientID
->getCStringNoCopy() : "",
4665 clientID
->release();
4670 void IOService::cleanClientResponses ( bool logErrors
)
4672 IOPMInterestContext context
;
4674 if (logErrors
&& fResponseArray
&& fNotifyClientArray
) {
4675 context
.responseFlags
= fResponseArray
;
4676 context
.notifyClients
= fNotifyClientArray
;
4677 context
.serialNumber
= fSerialNumber
;
4678 context
.counter
= 0;
4679 context
.msgType
= kIOMessageCopyClientID
;
4681 context
.maxTimeRequested
= 0;
4682 context
.stateNumber
= fHeadNotePowerState
;
4683 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4684 context
.errorLog
= "PM notification timeout (%s)\n";
4686 switch ( fOutOfBandParameter
) {
4688 applyToInterested(gIOAppPowerStateInterest
, logAppTimeouts
, (void *) &context
);
4689 case kNotifyPriority
:
4697 // get rid of this stuff
4698 fResponseArray
->release();
4699 fResponseArray
= NULL
;
4701 if (fNotifyClientArray
)
4703 fNotifyClientArray
->release();
4704 fNotifyClientArray
= NULL
;
4710 //*********************************************************************************
4711 // [protected] tellClientsWithResponse
4713 // Notify registered applications and kernel clients that we are definitely
4716 // Return true if we don't have to wait for acknowledgements
4717 //*********************************************************************************
4719 bool IOService::tellClientsWithResponse (
4722 return tellClientsWithResponse( messageType
, 0 );
4725 bool IOService::tellClientsWithResponse (
4727 IOPMMessageFilter filter
)
4729 IOPMInterestContext context
;
4731 PM_ASSERT_IN_GATE();
4732 assert( fResponseArray
== NULL
);
4733 assert( fNotifyClientArray
== NULL
);
4735 fResponseArray
= OSArray::withCapacity( 1 );
4736 if (!fResponseArray
)
4739 fResponseArray
->setCapacityIncrement(8);
4742 context
.responseFlags
= fResponseArray
;
4743 context
.notifyClients
= 0;
4744 context
.serialNumber
= fSerialNumber
;
4745 context
.counter
= 0;
4746 context
.msgType
= messageType
;
4748 context
.maxTimeRequested
= 0;
4749 context
.stateNumber
= fHeadNotePowerState
;
4750 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4751 context
.filterFunc
= filter
;
4753 switch ( fOutOfBandParameter
) {
4755 applyToInterested( gIOAppPowerStateInterest
,
4756 pmTellAppWithResponse
, (void *) &context
);
4757 fNotifyClientArray
= context
.notifyClients
;
4759 applyToInterested( gIOGeneralInterest
,
4760 pmTellClientWithResponse
, (void *) &context
);
4763 case kNotifyPriority
:
4764 applyToInterested( gIOPriorityPowerStateInterest
,
4765 pmTellClientWithResponse
, (void *) &context
);
4769 // do we have to wait for somebody?
4770 if ( !checkForDone() )
4772 OUR_PMLog(kPMLogStartAckTimer
, context
.maxTimeRequested
, 0);
4773 start_ack_timer( context
.maxTimeRequested
/ 1000, kMillisecondScale
);
4778 // everybody responded
4781 fResponseArray
->release();
4782 fResponseArray
= NULL
;
4784 if (fNotifyClientArray
)
4786 fNotifyClientArray
->release();
4787 fNotifyClientArray
= NULL
;
4793 //*********************************************************************************
4794 // [static private] pmTellAppWithResponse
4796 // We send a message to an application, and we expect a response, so we compute a
4797 // cookie we can identify the response with.
4798 //*********************************************************************************
4800 void IOService::pmTellAppWithResponse ( OSObject
* object
, void * arg
)
4802 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
4803 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
4807 if (!OSDynamicCast(_IOServiceInterestNotifier
, object
))
4809 // object must be an _IOServiceInterestNotifier.
4813 // Lazily create app clients array.
4814 if (0 == context
->notifyClients
)
4816 context
->notifyClients
= OSArray::withCapacity( 32 );
4819 if (context
->filterFunc
&& !context
->filterFunc(object
, arg
))
4821 // ack - needed to match the counter index at logAppTimeouts().
4822 context
->responseFlags
->setObject(context
->counter
, kOSBooleanTrue
);
4823 if (context
->notifyClients
)
4824 context
->notifyClients
->setObject(context
->counter
, kOSBooleanTrue
);
4828 refcon
= ((context
->serialNumber
& 0xFFFF)<<16)
4829 + (context
->counter
& 0xFFFF);
4830 OUR_PMLog(kPMLogAppNotify
, context
->msgType
, refcon
);
4832 if (gIOKitDebug
& kIOLogDebugPower
)
4834 // Log client pid/name and associated index.
4835 OSString
* clientID
= 0;
4836 context
->us
->messageClient(kIOMessageCopyClientID
, object
, &clientID
);
4837 PM_DEBUG("[Notify %u] message 0x%x to %s\n",
4838 (uint32_t) context
->counter
,
4840 clientID
? clientID
->getCStringNoCopy() : "");
4841 if (clientID
) clientID
->release();
4844 #if LOG_APP_RESPONSE_TIMES
4846 clock_get_uptime(&now
);
4847 num
= OSNumber::withNumber(AbsoluteTime_to_scalar(&now
), sizeof(uint64_t) * 8);
4850 context
->responseFlags
->setObject(context
->counter
, num
);
4855 context
->responseFlags
->setObject(context
->counter
, kOSBooleanFalse
);
4857 if (context
->notifyClients
)
4858 context
->notifyClients
->setObject(context
->counter
, object
);
4860 context
->us
->messageClient(context
->msgType
, object
, (void *)refcon
);
4861 if ( context
->maxTimeRequested
< k30seconds
)
4863 context
->maxTimeRequested
= k30seconds
;
4870 //*********************************************************************************
4871 // [static private] pmTellClientWithResponse
4873 // We send a message to an in-kernel client, and we expect a response, so we compute a
4874 // cookie we can identify the response with.
4875 // If it doesn't understand the notification (it is not power-management savvy)
4876 // we won't wait for it to prepare for sleep. If it tells us via a return code
4877 // in the passed struct that it is currently ready, we won't wait for it to prepare.
4878 // If it tells us via the return code in the struct that it does need time, we will chill.
4879 //*********************************************************************************
4881 void IOService::pmTellClientWithResponse ( OSObject
* object
, void * arg
)
4883 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
4884 IOPowerStateChangeNotification notify
;
4889 if (context
->filterFunc
&& !context
->filterFunc(object
, arg
))
4892 refcon
= ((context
->serialNumber
& 0xFFFF)<<16) + (context
->counter
& 0xFFFF);
4893 context
->responseFlags
->setObject(context
->counter
, kOSBooleanFalse
);
4895 IOServicePM
* pwrMgt
= context
->us
->pwrMgt
;
4896 if (gIOKitDebug
& kIOLogPower
) {
4897 OUR_PMLog(kPMLogClientNotify
, refcon
, (UInt32
) context
->msgType
);
4898 if (OSDynamicCast(IOService
, object
)) {
4899 const char *who
= ((IOService
*) object
)->getName();
4900 gPlatform
->PMLog(who
,
4901 kPMLogClientNotify
, * (UInt32
*) object
, (UInt64
) object
);
4902 } else if (OSDynamicCast(_IOServiceInterestNotifier
, object
)) {
4903 _IOServiceInterestNotifier
*n
= (_IOServiceInterestNotifier
*) object
;
4904 OUR_PMLog(kPMLogClientNotify
, (UInt64
) n
->handler
, 0);
4908 notify
.powerRef
= (void *)refcon
;
4909 notify
.returnValue
= 0;
4910 notify
.stateNumber
= context
->stateNumber
;
4911 notify
.stateFlags
= context
->stateFlags
;
4912 retCode
= context
->us
->messageClient(context
->msgType
,object
,(void *)¬ify
);
4913 if ( retCode
== kIOReturnSuccess
)
4915 if ( notify
.returnValue
== 0 )
4917 // client doesn't want time to respond
4918 context
->responseFlags
->replaceObject(context
->counter
, kOSBooleanTrue
);
4919 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, (UInt64
) object
);
4921 // it does want time, and it hasn't responded yet
4922 theFlag
= context
->responseFlags
->getObject(context
->counter
);
4923 if ( kOSBooleanTrue
!= theFlag
)
4925 // so note its time requirement
4926 if ( context
->maxTimeRequested
< notify
.returnValue
)
4928 context
->maxTimeRequested
= notify
.returnValue
;
4933 OUR_PMLog(kPMLogClientAcknowledge
, refcon
, 0);
4934 // not a client of ours
4935 // so we won't be waiting for response
4936 context
->responseFlags
->replaceObject(context
->counter
, kOSBooleanTrue
);
4941 //*********************************************************************************
4942 // [public] tellNoChangeDown
4944 // Notify registered applications and kernel clients that we are not
4947 // Subclass can override this to send a different message type. Parameter is
4948 // the aborted destination state number.
4949 //*********************************************************************************
4951 void IOService::tellNoChangeDown ( unsigned long )
4953 return tellClients( kIOMessageDeviceWillNotPowerOff
);
4956 //*********************************************************************************
4957 // [public] tellChangeUp
4959 // Notify registered applications and kernel clients that we are raising power.
4961 // Subclass can override this to send a different message type. Parameter is
4962 // the aborted destination state number.
4963 //*********************************************************************************
4965 void IOService::tellChangeUp ( unsigned long )
4967 return tellClients( kIOMessageDeviceHasPoweredOn
);
4970 //*********************************************************************************
4971 // [protected] tellClients
4973 // Notify registered applications and kernel clients of something.
4974 //*********************************************************************************
4976 void IOService::tellClients ( int messageType
)
4978 tellClients( messageType
, 0 );
4981 void IOService::tellClients ( int messageType
, IOPMMessageFilter filter
)
4983 IOPMInterestContext context
;
4985 context
.msgType
= messageType
;
4987 context
.stateNumber
= fHeadNotePowerState
;
4988 context
.stateFlags
= fHeadNotePowerArrayEntry
->capabilityFlags
;
4989 context
.filterFunc
= filter
;
4991 applyToInterested( gIOPriorityPowerStateInterest
,
4992 tellKernelClientApplier
, (void *) &context
);
4994 applyToInterested( gIOAppPowerStateInterest
,
4995 tellAppClientApplier
, (void *) &context
);
4997 applyToInterested( gIOGeneralInterest
,
4998 tellKernelClientApplier
, (void *) &context
);
5001 //*********************************************************************************
5002 // [private] tellKernelClientApplier
5004 // Message a kernel client.
5005 //*********************************************************************************
5007 static void tellKernelClientApplier ( OSObject
* object
, void * arg
)
5009 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5010 IOPowerStateChangeNotification notify
;
5012 if (context
->filterFunc
&& !context
->filterFunc(object
, arg
))
5015 notify
.powerRef
= (void *) 0;
5016 notify
.returnValue
= 0;
5017 notify
.stateNumber
= context
->stateNumber
;
5018 notify
.stateFlags
= context
->stateFlags
;
5020 context
->us
->messageClient(context
->msgType
, object
, ¬ify
);
5023 //*********************************************************************************
5024 // [private] tellAppClientApplier
5026 // Message a registered application.
5027 //*********************************************************************************
5029 static void tellAppClientApplier ( OSObject
* object
, void * arg
)
5031 IOPMInterestContext
* context
= (IOPMInterestContext
*) arg
;
5033 if (context
->filterFunc
&& !context
->filterFunc(object
, arg
))
5036 context
->us
->messageClient(context
->msgType
, object
, 0);
5039 //*********************************************************************************
5040 // [private] checkForDone
5041 //*********************************************************************************
5043 bool IOService::checkForDone ( void )
5048 if ( fResponseArray
== NULL
)
5053 for ( i
= 0; ; i
++ )
5055 theFlag
= fResponseArray
->getObject(i
);
5056 if ( theFlag
== NULL
)
5060 if ( kOSBooleanTrue
!= theFlag
)
5068 //*********************************************************************************
5069 // [public] responseValid
5070 //*********************************************************************************
5072 bool IOService::responseValid ( unsigned long x
, int pid
)
5074 UInt16 serialComponent
;
5075 UInt16 ordinalComponent
;
5077 unsigned long refcon
= (unsigned long) x
;
5079 serialComponent
= (refcon
>> 16) & 0xFFFF;
5080 ordinalComponent
= (refcon
& 0xFFFF);
5082 if ( serialComponent
!= fSerialNumber
)
5087 if ( fResponseArray
== NULL
)
5092 theFlag
= fResponseArray
->getObject(ordinalComponent
);
5100 if ((num
= OSDynamicCast(OSNumber
, theFlag
)))
5102 #if LOG_APP_RESPONSE_TIMES
5107 clock_get_uptime(&now
);
5108 AbsoluteTime_to_scalar(&start
) = num
->unsigned64BitValue();
5109 SUB_ABSOLUTETIME(&now
, &start
);
5110 absolutetime_to_nanoseconds(now
, &nsec
);
5113 if (nsec
> LOG_APP_RESPONSE_TIMES
)
5115 OSString
* name
= IOCopyLogNameForPID(pid
);
5116 PM_DEBUG("PM response took %d ms (%s)\n", NS_TO_MS(nsec
),
5117 name
? name
->getCStringNoCopy() : "");
5119 if (nsec
> LOG_APP_RESPONSE_MSG_TRACER
)
5121 // TODO: populate the messageType argument
5122 getPMRootDomain()->pmStatsRecordApplicationResponse(
5123 gIOPMStatsApplicationResponseSlow
,
5124 name
? name
->getCStringNoCopy() : "", 0,
5125 NS_TO_MS(nsec
), pid
);
5132 theFlag
= kOSBooleanFalse
;
5135 if ( kOSBooleanFalse
== theFlag
)
5137 if ((gIOKitDebug
& kIOLogDebugPower
) &&
5138 (fOutOfBandParameter
== kNotifyApps
))
5140 PM_DEBUG("[Notify %u] acked\n", (uint32_t) ordinalComponent
);
5142 fResponseArray
->replaceObject(ordinalComponent
, kOSBooleanTrue
);
5148 //*********************************************************************************
5149 // [public] allowPowerChange
5151 // Our power state is about to lower, and we have notified applications
5152 // and kernel clients, and one of them has acknowledged. If this is the last to do
5153 // so, and all acknowledgements are positive, we continue with the power change.
5155 // We serialize this processing with timer expiration with a command gate on the
5156 // power management workloop, which the timer expiration is command gated to as well.
5157 //*********************************************************************************
5159 IOReturn
IOService::allowPowerChange ( unsigned long refcon
)
5161 IOPMRequest
* request
;
5166 return kIOReturnSuccess
;
5169 request
= acquirePMRequest( this, kIOPMRequestTypeAllowPowerChange
);
5171 return kIOReturnNoMemory
;
5173 request
->fArg0
= (void *) refcon
;
5174 request
->fArg1
= (void *) proc_selfpid();
5175 request
->fArg2
= (void *) 0;
5176 submitPMRequest( request
);
5178 return kIOReturnSuccess
;
5182 IOReturn
IOService::serializedAllowPowerChange2 ( unsigned long refcon
)
5184 // [deprecated] public
5185 return kIOReturnUnsupported
;
5187 #endif /* !__LP64__ */
5189 //*********************************************************************************
5190 // [public] cancelPowerChange
5192 // Our power state is about to lower, and we have notified applications
5193 // and kernel clients, and one of them has vetoed the change. If this is the last
5194 // client to respond, we abandon the power change.
5196 // We serialize this processing with timer expiration with a command gate on the
5197 // power management workloop, which the timer expiration is command gated to as well.
5198 //*********************************************************************************
5200 IOReturn
IOService::cancelPowerChange ( unsigned long refcon
)
5202 IOPMRequest
* request
;
5208 return kIOReturnSuccess
;
5211 name
= IOCopyLogNameForPID(proc_selfpid());
5212 PM_ERROR("PM notification cancel (%s)\n", name
? name
->getCStringNoCopy() : "");
5214 request
= acquirePMRequest( this, kIOPMRequestTypeCancelPowerChange
);
5219 return kIOReturnNoMemory
;
5222 request
->fArg0
= (void *) refcon
;
5223 request
->fArg1
= (void *) proc_selfpid();
5224 request
->fArg2
= (void *) name
;
5225 submitPMRequest( request
);
5227 return kIOReturnSuccess
;
5231 IOReturn
IOService::serializedCancelPowerChange2 ( unsigned long refcon
)
5233 // [deprecated] public
5234 return kIOReturnUnsupported
;
5237 //*********************************************************************************
5238 // PM_Clamp_Timer_Expired
5240 // called when clamp timer expires...set power state to 0.
5241 //*********************************************************************************
5243 void IOService::PM_Clamp_Timer_Expired ( void )
5247 //*********************************************************************************
5250 // Set to highest available power state for a minimum of duration milliseconds
5251 //*********************************************************************************
5253 void IOService::clampPowerOn ( unsigned long duration
)
5256 #endif /* !__LP64__ */
5258 //*********************************************************************************
5259 // [public] setPowerState
5261 // Does nothing here. This should be implemented in a subclass driver.
5262 //*********************************************************************************
5264 IOReturn
IOService::setPowerState (
5265 unsigned long powerStateOrdinal
, IOService
* whatDevice
)
5270 //*********************************************************************************
5271 // [public] maxCapabilityForDomainState
5273 // Finds the highest power state in the array whose input power
5274 // requirement is equal to the input parameter. Where a more intelligent
5275 // decision is possible, override this in the subclassed driver.
5276 //*********************************************************************************
5278 unsigned long IOService::maxCapabilityForDomainState ( IOPMPowerFlags domainState
)
5282 if (fNumberOfPowerStates
== 0 )
5286 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
5288 if ( (domainState
& fPowerStates
[i
].inputPowerRequirement
) ==
5289 fPowerStates
[i
].inputPowerRequirement
)
5297 //*********************************************************************************
5298 // [public] initialPowerStateForDomainState
5300 // Finds the highest power state in the array whose input power
5301 // requirement is equal to the input parameter. Where a more intelligent
5302 // decision is possible, override this in the subclassed driver.
5303 //*********************************************************************************
5305 unsigned long IOService::initialPowerStateForDomainState ( IOPMPowerFlags domainState
)
5309 if (fNumberOfPowerStates
== 0 )
5313 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
5315 if ( (domainState
& fPowerStates
[i
].inputPowerRequirement
) ==
5316 fPowerStates
[i
].inputPowerRequirement
)
5324 //*********************************************************************************
5325 // [public] powerStateForDomainState
5327 // Finds the highest power state in the array whose input power
5328 // requirement is equal to the input parameter. Where a more intelligent
5329 // decision is possible, override this in the subclassed driver.
5330 //*********************************************************************************
5332 unsigned long IOService::powerStateForDomainState ( IOPMPowerFlags domainState
)
5336 if (fNumberOfPowerStates
== 0 )
5340 for ( i
= fNumberOfPowerStates
- 1; i
>= 0; i
-- )
5342 if ( (domainState
& fPowerStates
[i
].inputPowerRequirement
) ==
5343 fPowerStates
[i
].inputPowerRequirement
)
5352 //*********************************************************************************
5353 // [deprecated] didYouWakeSystem
5355 // Does nothing here. This should be implemented in a subclass driver.
5356 //*********************************************************************************
5358 bool IOService::didYouWakeSystem ( void )
5362 #endif /* !__LP64__ */
5364 //*********************************************************************************
5365 // [public] powerStateWillChangeTo
5367 // Does nothing here. This should be implemented in a subclass driver.
5368 //*********************************************************************************
5370 IOReturn
IOService::powerStateWillChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
5372 return kIOPMAckImplied
;
5375 //*********************************************************************************
5376 // [public] powerStateDidChangeTo
5378 // Does nothing here. This should be implemented in a subclass driver.
5379 //*********************************************************************************
5381 IOReturn
IOService::powerStateDidChangeTo ( IOPMPowerFlags
, unsigned long, IOService
* )
5383 return kIOPMAckImplied
;
5386 //*********************************************************************************
5387 // [protected] powerChangeDone
5389 // Called from PM work loop thread.
5390 // Does nothing here. This should be implemented in a subclass policy-maker.
5391 //*********************************************************************************
5393 void IOService::powerChangeDone ( unsigned long )
5398 //*********************************************************************************
5399 // [deprecated] newTemperature
5401 // Does nothing here. This should be implemented in a subclass driver.
5402 //*********************************************************************************
5404 IOReturn
IOService::newTemperature ( long currentTemp
, IOService
* whichZone
)
5408 #endif /* !__LP64__ */
5410 //*********************************************************************************
5411 // [public] systemWillShutdown
5413 // System shutdown and restart notification.
5414 //*********************************************************************************
5416 void IOService::systemWillShutdown( IOOptionBits specifier
)
5418 IOPMrootDomain
* rootDomain
= IOService::getPMRootDomain();
5420 rootDomain
->acknowledgeSystemWillShutdown( this );
5423 //*********************************************************************************
5424 // [private static] acquirePMRequest
5425 //*********************************************************************************
5428 IOService::acquirePMRequest( IOService
* target
, IOOptionBits requestType
,
5429 IOPMRequest
* active
)
5431 IOPMRequest
* request
;
5435 request
= IOPMRequest::create();
5438 request
->init( target
, requestType
);
5441 IOPMRequest
* root
= active
->getRootRequest();
5442 if (root
) request
->attachRootRequest(root
);
5447 PM_ERROR("%s: No memory for PM request type 0x%x\n",
5448 target
->getName(), (uint32_t) requestType
);
5453 //*********************************************************************************
5454 // [private static] releasePMRequest
5455 //*********************************************************************************
5457 void IOService::releasePMRequest( IOPMRequest
* request
)
5466 //*********************************************************************************
5467 // [private] submitPMRequest
5468 //*********************************************************************************
5470 void IOService::submitPMRequest( IOPMRequest
* request
)
5473 assert( gIOPMReplyQueue
);
5474 assert( gIOPMRequestQueue
);
5476 PM_TRACE("[+ %02lx] %p [%p %s] %p %p %p\n",
5477 (long)request
->getType(), request
,
5478 request
->getTarget(), request
->getTarget()->getName(),
5479 request
->fArg0
, request
->fArg1
, request
->fArg2
);
5481 if (request
->isReplyType())
5482 gIOPMReplyQueue
->queuePMRequest( request
);
5484 gIOPMRequestQueue
->queuePMRequest( request
);
5487 void IOService::submitPMRequest( IOPMRequest
** requests
, IOItemCount count
)
5490 assert( count
> 0 );
5491 assert( gIOPMRequestQueue
);
5493 for (IOItemCount i
= 0; i
< count
; i
++)
5495 IOPMRequest
* req
= requests
[i
];
5496 PM_TRACE("[+ %02lx] %p [%p %s] %p %p %p\n",
5497 (long)req
->getType(), req
,
5498 req
->getTarget(), req
->getTarget()->getName(),
5499 req
->fArg0
, req
->fArg1
, req
->fArg2
);
5502 gIOPMRequestQueue
->queuePMRequestChain( requests
, count
);
5505 //*********************************************************************************
5506 // [private] servicePMRequestQueue
5507 //*********************************************************************************
5509 bool IOService::servicePMRequestQueue(
5510 IOPMRequest
* request
,
5511 IOPMRequestQueue
* queue
)
5513 // Calling PM methods without PMinit() is not allowed, fail the requests.
5517 PM_DEBUG("%s: PM not initialized\n", getName());
5521 // Create an IOPMWorkQueue on demand, when the initial PM request is
5526 // Allocate and attach an IOPMWorkQueue on demand to avoid taking
5527 // the work loop lock in PMinit(), which may deadlock with certain
5528 // drivers / families.
5530 fPMWorkQueue
= IOPMWorkQueue::create(
5532 /* Work */ OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
5533 &IOService::servicePMRequest
),
5534 /* Done */ OSMemberFunctionCast(IOPMWorkQueue::Action
, this,
5535 &IOService::retirePMRequest
)
5539 (gIOPMWorkLoop
->addEventSource(fPMWorkQueue
) != kIOReturnSuccess
))
5541 PM_ERROR("%s: add PM work queue failed\n", getName());
5542 fPMWorkQueue
->release();
5548 PM_ERROR("%s: no PM work queue (type %02lx)\n",
5549 getName(), (long)request
->getType());
5554 fPMWorkQueue
->queuePMRequest(request
);
5555 return false; // do not signal more
5558 fAdjustPowerScheduled
= false;
5559 gIOPMFreeQueue
->queuePMRequest(request
);
5560 return false; // do not signal more
5563 //*********************************************************************************
5564 // [private] servicePMFreeQueue
5566 // Called by the request completion to recycle a completed request.
5567 //*********************************************************************************
5569 bool IOService::servicePMFreeQueue(
5570 IOPMRequest
* request
,
5571 IOPMCompletionQueue
* queue
)
5573 bool more
= request
->getNextRequest();
5574 IOPMRequest
* root
= request
->getRootRequest();
5576 if (root
&& (root
!= request
))
5579 releasePMRequest( request
);
5583 //*********************************************************************************
5584 // [private] retirePMRequest
5586 // Called by IOPMWorkQueue to retire a completed request.
5587 //*********************************************************************************
5589 bool IOService::retirePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
5591 assert(request
&& queue
);
5593 PM_TRACE("[- %02x] %p [%p %s] State %d, Busy %d\n",
5594 request
->getType(), request
, this, getName(),
5595 fMachineState
, gIOPMBusyCount
);
5597 // Catch requests created by idleTimerExpired().
5599 if ((request
->getType() == kIOPMRequestTypeActivityTickle
) &&
5600 (request
->fArg1
== (void *) false))
5602 // Idle timer power drop request completed.
5603 // Restart the idle timer if deviceDesire can go lower, otherwise set
5604 // a flag so we know to restart idle timer when deviceDesire goes up.
5606 if (fDeviceDesire
> 0)
5608 fActivityTickleCount
= 0;
5609 clock_get_uptime(&fIdleTimerStartTime
);
5610 start_PM_idle_timer();
5613 fIdleTimerStopped
= true;
5616 gIOPMFreeQueue
->queuePMRequest( request
);
5620 //*********************************************************************************
5621 // [private] isPMBlocked
5623 // Check if machine state transition is blocked.
5624 //*********************************************************************************
5626 bool IOService::isPMBlocked ( IOPMRequest
* request
, int count
)
5631 if (kIOPM_Finished
== fMachineState
)
5634 if (kIOPM_DriverThreadCallDone
== fMachineState
)
5636 // 5 = kDriverCallInformPreChange
5637 // 6 = kDriverCallInformPostChange
5638 // 7 = kDriverCallSetPowerState
5639 if (fLockedFlags
.DriverCallBusy
) reason
= 5 + fDriverCallReason
;
5643 // Waiting on driver's setPowerState() timeout.
5649 // Child or interested driver acks pending.
5650 if (fHeadNotePendingAcks
)
5655 // Waiting on apps or priority power interest clients.
5661 // Waiting on settle timer expiration.
5668 fWaitReason
= reason
;
5674 PM_TRACE("[B %02x] %p [%p %s] State %d, Reason %d\n",
5675 request
->getType(), request
, this, getName(),
5676 fMachineState
, reason
);
5685 //*********************************************************************************
5686 // [private] servicePMRequest
5688 // Service a request from our work queue.
5689 //*********************************************************************************
5691 bool IOService::servicePMRequest( IOPMRequest
* request
, IOPMWorkQueue
* queue
)
5696 assert(request
&& queue
);
5698 while (isPMBlocked(request
, loop
++) == false)
5700 PM_TRACE("[W %02x] %p [%p %s] State %d\n",
5701 request
->getType(), request
, this, getName(), fMachineState
);
5703 gIOPMRequest
= request
;
5705 // Every PM machine states must be handled in one of the cases below.
5707 switch ( fMachineState
)
5709 case kIOPM_Finished
:
5710 executePMRequest( request
);
5713 case kIOPM_OurChangeTellClientsPowerDown
:
5714 // our change, was it vetoed?
5715 if (!fDoNotPowerDown
)
5717 // no, we can continue
5718 OurChangeTellClientsPowerDown();
5722 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
5723 PM_ERROR("%s: idle cancel\n", fName
);
5724 // yes, rescind the warning
5725 tellNoChangeDown(fHeadNotePowerState
);
5726 // mark the change note un-actioned
5727 fHeadNoteFlags
|= kIOPMNotDone
;
5733 case kIOPM_OurChangeTellPriorityClientsPowerDown
:
5734 // our change, should it be acted on still?
5735 if (fDoNotPowerDown
)
5737 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, fMachineState
);
5738 PM_ERROR("%s: idle revert\n", fName
);
5739 // no, tell clients we're back in the old state
5740 tellChangeUp(fCurrentPowerState
);
5741 // mark the change note un-actioned
5742 fHeadNoteFlags
|= kIOPMNotDone
;
5748 // yes, we can continue
5749 OurChangeTellPriorityClientsPowerDown();
5753 case kIOPM_OurChangeNotifyInterestedDriversWillChange
:
5754 OurChangeNotifyInterestedDriversWillChange();
5757 case kIOPM_OurChangeSetPowerState
:
5758 OurChangeSetPowerState();
5761 case kIOPM_OurChangeWaitForPowerSettle
:
5762 OurChangeWaitForPowerSettle();
5765 case kIOPM_OurChangeNotifyInterestedDriversDidChange
:
5766 OurChangeNotifyInterestedDriversDidChange();
5769 case kIOPM_OurChangeFinish
:
5773 case kIOPM_ParentDownTellPriorityClientsPowerDown
:
5774 ParentDownTellPriorityClientsPowerDown();
5777 case kIOPM_ParentDownNotifyInterestedDriversWillChange
:
5778 ParentDownNotifyInterestedDriversWillChange();
5781 case kIOPM_ParentDownNotifyDidChangeAndAcknowledgeChange
:
5782 ParentDownNotifyDidChangeAndAcknowledgeChange();
5785 case kIOPM_ParentDownSetPowerState
:
5786 ParentDownSetPowerState();
5789 case kIOPM_ParentDownWaitForPowerSettle
:
5790 ParentDownWaitForPowerSettle();
5793 case kIOPM_ParentAcknowledgePowerChange
:
5794 ParentAcknowledgePowerChange();
5797 case kIOPM_ParentUpSetPowerState
:
5798 ParentUpSetPowerState();
5801 case kIOPM_ParentUpWaitForSettleTime
:
5802 ParentUpWaitForSettleTime();
5805 case kIOPM_ParentUpNotifyInterestedDriversDidChange
:
5806 ParentUpNotifyInterestedDriversDidChange();
5809 case kIOPM_DriverThreadCallDone
:
5810 if (fDriverCallReason
== kDriverCallSetPowerState
)
5811 notifyControllingDriverDone();
5813 notifyInterestedDriversDone();
5816 case kIOPM_NotifyChildrenDone
:
5817 notifyChildrenDone();
5820 case kIOPM_SyncNotifyDidChange
:
5821 fMachineState
= kIOPM_SyncFinish
;
5822 fDriverCallReason
= kDriverCallInformPostChange
;
5826 case kIOPM_SyncFinish
:
5827 if (fHeadNoteFlags
& kIOPMParentInitiated
)
5828 ParentAcknowledgePowerChange();
5834 panic("servicePMWorkQueue: unknown machine state %x",
5840 if (fMachineState
== kIOPM_Finished
)
5842 //PM_TRACE("[%s] PM End: Request %p (type %02lx)\n",
5843 // getName(), request, request->getType());
5852 //*********************************************************************************
5853 // [private] executePMRequest
5854 //*********************************************************************************
5856 void IOService::executePMRequest( IOPMRequest
* request
)
5858 assert( kIOPM_Finished
== fMachineState
);
5860 switch (request
->getType())
5862 case kIOPMRequestTypePMStop
:
5863 handlePMstop( request
);
5866 case kIOPMRequestTypeAddPowerChild1
:
5867 addPowerChild1( request
);
5870 case kIOPMRequestTypeAddPowerChild2
:
5871 addPowerChild2( request
);
5874 case kIOPMRequestTypeAddPowerChild3
:
5875 addPowerChild3( request
);
5878 case kIOPMRequestTypeRegisterPowerDriver
:
5879 handleRegisterPowerDriver( request
);
5882 case kIOPMRequestTypeAdjustPowerState
:
5883 fAdjustPowerScheduled
= false;
5884 rebuildChildClampBits();
5888 case kIOPMRequestTypePowerDomainWillChange
:
5889 handlePowerDomainWillChangeTo( request
);
5892 case kIOPMRequestTypePowerDomainDidChange
:
5893 handlePowerDomainDidChangeTo( request
);
5896 case kIOPMRequestTypeRequestPowerState
:
5897 case kIOPMRequestTypeRequestPowerStateOverride
:
5898 handleRequestPowerState( request
);
5901 case kIOPMRequestTypePowerOverrideOnPriv
:
5902 case kIOPMRequestTypePowerOverrideOffPriv
:
5903 handlePowerOverrideChanged( request
);
5906 case kIOPMRequestTypeActivityTickle
:
5907 handleActivityTickle( request
);
5910 case kIOPMRequestTypeSynchronizePowerTree
:
5911 handleSynchronizePowerTree( request
);
5914 case kIOPMRequestTypeSetIdleTimerPeriod
:
5916 IOWorkLoop
* wl
= gIOPMWorkLoop
;
5917 fIdleTimerPeriod
= (uintptr_t) request
->fArg0
;
5919 if (wl
&& (false == fLockedFlags
.PMStop
) && (fIdleTimerPeriod
> 0))
5921 if ( NULL
== fIdleTimerEventSource
)
5923 IOTimerEventSource
* timerSrc
;
5925 timerSrc
= IOTimerEventSource::timerEventSource(
5927 OSMemberFunctionCast(IOTimerEventSource::Action
,
5928 this, &IOService::idleTimerExpired
));
5930 if (timerSrc
&& (wl
->addEventSource(timerSrc
) != kIOReturnSuccess
))
5932 timerSrc
->release();
5936 fIdleTimerEventSource
= timerSrc
;
5939 fActivityTickleCount
= 0;
5940 clock_get_uptime(&fIdleTimerStartTime
);
5941 start_PM_idle_timer();
5947 panic("executePMRequest: unknown request type %x", request
->getType());
5951 //*********************************************************************************
5952 // [private] servicePMReplyQueue
5953 //*********************************************************************************
5955 bool IOService::servicePMReplyQueue( IOPMRequest
* request
, IOPMRequestQueue
* queue
)
5959 assert( request
&& queue
);
5960 assert( request
->isReplyType() );
5962 PM_TRACE("[A %02x] %p [%p %s] State %d\n",
5963 request
->getType(), request
, this, getName(), fMachineState
);
5965 switch ( request
->getType() )
5967 case kIOPMRequestTypeAllowPowerChange
:
5968 case kIOPMRequestTypeCancelPowerChange
:
5969 // Check if we are expecting this response.
5970 if (responseValid((unsigned long) request
->fArg0
, (int)(long) request
->fArg1
))
5972 if (kIOPMRequestTypeCancelPowerChange
== request
->getType())
5974 OSString
* name
= (OSString
*) request
->fArg2
;
5975 getPMRootDomain()->pmStatsRecordApplicationResponse(
5976 gIOPMStatsApplicationResponseCancel
,
5977 name
? name
->getCStringNoCopy() : "", 0,
5978 0, (int)(uintptr_t) request
->fArg1
);
5980 fDoNotPowerDown
= true;
5986 if ( fResponseArray
)
5988 fResponseArray
->release();
5989 fResponseArray
= NULL
;
5991 if ( fNotifyClientArray
)
5993 fNotifyClientArray
->release();
5994 fNotifyClientArray
= NULL
;
5999 // OSString containing app name in Arg2 must be released.
6000 if (request
->getType() == kIOPMRequestTypeCancelPowerChange
)
6002 OSObject
* obj
= (OSObject
*) request
->fArg2
;
6003 if (obj
) obj
->release();
6007 case kIOPMRequestTypeAckPowerChange
:
6008 more
= handleAcknowledgePowerChange( request
);
6011 case kIOPMRequestTypeAckSetPowerState
:
6012 if (fDriverTimer
== -1)
6014 // driver acked while setPowerState() call is in-flight.
6015 // take this ack, return value from setPowerState() is irrelevant.
6016 OUR_PMLog(kPMLogDriverAcknowledgeSet
,
6017 (uintptr_t) this, fDriverTimer
);
6020 else if (fDriverTimer
> 0)
6022 // expected ack, stop the timer
6025 #if LOG_SETPOWER_TIMES
6026 uint64_t nsec
= computeTimeDeltaNS(&fDriverCallStartTime
);
6027 if (nsec
> LOG_SETPOWER_TIMES
)
6028 PM_DEBUG("%s::setPowerState(%p, %lu -> %lu) async took %d ms\n",
6029 fName
, this, fCurrentPowerState
, fHeadNotePowerState
, NS_TO_MS(nsec
));
6031 OUR_PMLog(kPMLogDriverAcknowledgeSet
, (uintptr_t) this, fDriverTimer
);
6038 OUR_PMLog(kPMLogAcknowledgeErr4
, (uintptr_t) this, 0);
6042 case kIOPMRequestTypeInterestChanged
:
6043 handleInterestChanged( request
);
6047 case kIOPMRequestTypeIdleCancel
:
6048 if ((fMachineState
== kIOPM_OurChangeTellClientsPowerDown
)
6049 || (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
))
6051 OUR_PMLog(kPMLogIdleCancel
, (uintptr_t) this, 0);
6052 fDoNotPowerDown
= true;
6053 if (fMachineState
== kIOPM_OurChangeTellPriorityClientsPowerDown
)
6054 cleanClientResponses(false);
6060 panic("servicePMReplyQueue: unknown reply type %x",
6061 request
->getType());
6064 releasePMRequest( request
);
6068 //*********************************************************************************
6069 // [private] assertPMThreadCall / deassertPMThreadCall
6070 //*********************************************************************************
6072 bool IOService::assertPMThreadCall( void )
6077 // PMfree() should only be called from IOService::free().
6078 // That makes it safe to touch IOServicePM state here.
6079 // Caller holds a retain and has checked target is on PM plane.
6082 if (fLockedFlags
.PMStop
)
6084 // PMstop() already issued - fail the assertion.
6089 // Increment assertion count to block PMstop(), and return true.
6090 fThreadAssertionCount
++;
6091 fThreadAssertionThread
= current_thread(); // only 1 caller
6097 void IOService::deassertPMThreadCall( void )
6100 assert(fThreadAssertionCount
> 0);
6101 if (fThreadAssertionCount
)
6102 fThreadAssertionCount
--;
6103 if (current_thread() == fThreadAssertionThread
)
6104 fThreadAssertionThread
= 0;
6105 if ((fThreadAssertionCount
== 0) && fLockedFlags
.PMStop
)
6107 // PMstop() is blocked waiting for assertion count to drop to zero.
6108 PM_LOCK_WAKEUP(&fThreadAssertionCount
);
6114 // MARK: IOPMRequest
6116 //*********************************************************************************
6117 // IOPMRequest Class
6119 // Requests from PM clients, and also used for inter-object messaging within PM.
6120 //*********************************************************************************
6122 OSDefineMetaClassAndStructors( IOPMRequest
, IOCommand
);
6124 IOPMRequest
* IOPMRequest::create( void )
6126 IOPMRequest
* me
= OSTypeAlloc(IOPMRequest
);
6127 if (me
&& !me
->init(0, kIOPMRequestTypeInvalid
))
6135 bool IOPMRequest::init( IOService
* target
, IOOptionBits type
)
6137 if (!IOCommand::init())
6142 fCompletionStatus
= kIOReturnSuccess
;
6150 void IOPMRequest::reset( void )
6152 assert( fWorkWaitCount
== 0 );
6153 assert( fFreeWaitCount
== 0 );
6155 detachNextRequest();
6156 detachRootRequest();
6158 fType
= kIOPMRequestTypeInvalid
;
6160 if (fCompletionAction
)
6162 fCompletionAction(fCompletionTarget
, fCompletionParam
, fCompletionStatus
);
6172 void IOPMRequest::attachNextRequest( IOPMRequest
* next
)
6176 // Postpone the execution of the next request after
6178 fRequestNext
= next
;
6179 fRequestNext
->fWorkWaitCount
++;
6180 #if LOG_REQUEST_ATTACH
6181 kprintf("Attached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
6182 this, (uint32_t) fType
, fRequestNext
,
6183 (uint32_t) fRequestNext
->fType
,
6184 (uint32_t) fRequestNext
->fWorkWaitCount
,
6185 fTarget
->getName());
6190 void IOPMRequest::detachNextRequest( void )
6194 assert(fRequestNext
->fWorkWaitCount
);
6195 if (fRequestNext
->fWorkWaitCount
)
6196 fRequestNext
->fWorkWaitCount
--;
6197 #if LOG_REQUEST_ATTACH
6198 kprintf("Detached next: %p [0x%x] -> %p [0x%x, %u] %s\n",
6199 this, (uint32_t) fType
, fRequestNext
,
6200 (uint32_t) fRequestNext
->fType
,
6201 (uint32_t) fRequestNext
->fWorkWaitCount
,
6202 fTarget
->getName());
6208 void IOPMRequest::attachRootRequest( IOPMRequest
* root
)
6212 // Delay the completion of the root request after
6214 fRequestRoot
= root
;
6215 fRequestRoot
->fFreeWaitCount
++;
6216 #if LOG_REQUEST_ATTACH
6217 kprintf("Attached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
6218 this, (uint32_t) fType
, fRequestRoot
,
6219 (uint32_t) fRequestRoot
->fType
,
6220 (uint32_t) fRequestRoot
->fFreeWaitCount
,
6221 fTarget
->getName());
6226 void IOPMRequest::detachRootRequest( void )
6230 assert(fRequestRoot
->fFreeWaitCount
);
6231 if (fRequestRoot
->fFreeWaitCount
)
6232 fRequestRoot
->fFreeWaitCount
--;
6233 #if LOG_REQUEST_ATTACH
6234 kprintf("Detached root: %p [0x%x] -> %p [0x%x, %u] %s\n",
6235 this, (uint32_t) fType
, fRequestRoot
,
6236 (uint32_t) fRequestRoot
->fType
,
6237 (uint32_t) fRequestRoot
->fFreeWaitCount
,
6238 fTarget
->getName());
6245 // MARK: IOPMRequestQueue
6247 //*********************************************************************************
6248 // IOPMRequestQueue Class
6250 // Global queues. As PM-aware drivers load and unload, their IOPMWorkQueue's are
6251 // created and deallocated. IOPMRequestQueue are created once and never released.
6252 //*********************************************************************************
6254 OSDefineMetaClassAndStructors( IOPMRequestQueue
, IOEventSource
);
6256 IOPMRequestQueue
* IOPMRequestQueue::create( IOService
* inOwner
, Action inAction
)
6258 IOPMRequestQueue
* me
= OSTypeAlloc(IOPMRequestQueue
);
6259 if (me
&& !me
->init(inOwner
, inAction
))
6267 bool IOPMRequestQueue::init( IOService
* inOwner
, Action inAction
)
6269 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
6272 queue_init(&fQueue
);
6273 fLock
= IOLockAlloc();
6274 return (fLock
!= 0);
6277 void IOPMRequestQueue::free( void )
6284 return IOEventSource::free();
6287 void IOPMRequestQueue::queuePMRequest( IOPMRequest
* request
)
6291 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
6292 IOLockUnlock(fLock
);
6293 if (workLoop
) signalWorkAvailable();
6297 IOPMRequestQueue::queuePMRequestChain( IOPMRequest
** requests
, IOItemCount count
)
6301 assert(requests
&& count
);
6307 queue_enter(&fQueue
, next
, IOPMRequest
*, fCommandChain
);
6309 IOLockUnlock(fLock
);
6310 if (workLoop
) signalWorkAvailable();
6313 bool IOPMRequestQueue::checkForWork( void )
6315 Action dqAction
= (Action
) action
;
6316 IOPMRequest
* request
;
6320 IOLockLock( fLock
);
6322 while (!queue_empty(&fQueue
))
6324 queue_remove_first( &fQueue
, request
, IOPMRequest
*, fCommandChain
);
6325 IOLockUnlock( fLock
);
6326 target
= request
->getTarget();
6328 more
|= (*dqAction
)( target
, request
, this );
6329 IOLockLock( fLock
);
6332 IOLockUnlock( fLock
);
6336 void IOPMRequestQueue::signalWorkAvailable( void )
6338 IOEventSource::signalWorkAvailable();
6342 // MARK: IOPMWorkQueue
6344 //*********************************************************************************
6345 // IOPMWorkQueue Class
6347 // Every object in the power plane that has handled a PM request, will have an
6348 // instance of IOPMWorkQueue allocated for it.
6349 //*********************************************************************************
6351 OSDefineMetaClassAndStructors( IOPMWorkQueue
, IOEventSource
);
6354 IOPMWorkQueue::create( IOService
* inOwner
, Action work
, Action retire
)
6356 IOPMWorkQueue
* me
= OSTypeAlloc(IOPMWorkQueue
);
6357 if (me
&& !me
->init(inOwner
, work
, retire
))
6365 bool IOPMWorkQueue::init( IOService
* inOwner
, Action work
, Action retire
)
6367 if (!work
|| !retire
||
6368 !IOEventSource::init(inOwner
, (IOEventSourceAction
)0))
6371 queue_init(&fWorkQueue
);
6374 fRetireAction
= retire
;
6379 void IOPMWorkQueue::queuePMRequest( IOPMRequest
* request
)
6382 assert( onThread() );
6385 queue_enter(&fWorkQueue
, request
, IOPMRequest
*, fCommandChain
);
6389 bool IOPMWorkQueue::checkForWork( void )
6391 IOPMRequest
* request
;
6392 IOService
* target
= (IOService
*) owner
;
6395 while (!queue_empty(&fWorkQueue
))
6397 request
= (IOPMRequest
*) queue_first(&fWorkQueue
);
6398 assert(request
->getTarget() == target
);
6399 if (request
->isWorkBlocked()) break;
6400 done
= (*fWorkAction
)( target
, request
, this );
6403 assert(gIOPMBusyCount
> 0);
6404 if (gIOPMBusyCount
) gIOPMBusyCount
--;
6405 queue_remove_first(&fWorkQueue
, request
, IOPMRequest
*, fCommandChain
);
6406 (*fRetireAction
)( target
, request
, this );
6413 // MARK: IOPMCompletionQueue
6415 //*********************************************************************************
6416 // IOPMCompletionQueue Class
6417 //*********************************************************************************
6419 OSDefineMetaClassAndStructors( IOPMCompletionQueue
, IOEventSource
);
6421 IOPMCompletionQueue
* IOPMCompletionQueue::create( IOService
* inOwner
, Action inAction
)
6423 IOPMCompletionQueue
* me
= OSTypeAlloc(IOPMCompletionQueue
);
6424 if (me
&& !me
->init(inOwner
, inAction
))
6432 bool IOPMCompletionQueue::init( IOService
* inOwner
, Action inAction
)
6434 if (!inAction
|| !IOEventSource::init(inOwner
, (IOEventSourceAction
)inAction
))
6437 queue_init(&fQueue
);
6441 void IOPMCompletionQueue::queuePMRequest( IOPMRequest
* request
)
6444 request
->detachNextRequest(); // unblocks next request
6445 queue_enter(&fQueue
, request
, IOPMRequest
*, fCommandChain
);
6446 if (workLoop
) signalWorkAvailable();
6449 bool IOPMCompletionQueue::checkForWork( void )
6451 Action dqAction
= (Action
) action
;
6452 IOPMRequest
* request
;
6455 queue_head_t tmpQueue
;
6457 queue_init(&tmpQueue
);
6459 while (!queue_empty(&fQueue
))
6461 queue_remove_first( &fQueue
, request
, IOPMRequest
*, fCommandChain
);
6462 if (request
->isFreeBlocked())
6464 queue_enter(&tmpQueue
, request
, IOPMRequest
*, fCommandChain
);
6467 target
= request
->getTarget();
6469 more
|= (*dqAction
)( target
, request
, this );
6472 queue_new_head(&tmpQueue
, &fQueue
, IOPMRequest
*, fCommandChain
);
6477 // MARK: IOServicePM
6479 OSDefineMetaClassAndStructors(IOServicePM
, OSObject
)
6481 //*********************************************************************************
6484 // Serialize IOServicePM for debugging.
6485 //*********************************************************************************
6488 setPMProperty( OSDictionary
* dict
, const char * key
, uint64_t value
)
6490 OSNumber
* num
= OSNumber::withNumber(value
, sizeof(value
) * 8);
6493 dict
->setObject(key
, num
);
6498 IOReturn
IOServicePM::gatedSerialize( OSSerialize
* s
)
6500 OSDictionary
* dict
;
6504 if (IdleTimerPeriod
)
6508 dict
= OSDictionary::withDictionary(
6509 PowerClients
, PowerClients
->getCount() + dictSize
);
6511 dict
= OSDictionary::withCapacity(dictSize
);
6515 setPMProperty(dict
, "CurrentPowerState", CurrentPowerState
);
6516 if (DesiredPowerState
!= CurrentPowerState
)
6517 setPMProperty(dict
, "DesiredPowerState", DesiredPowerState
);
6518 if (kIOPM_Finished
!= MachineState
)
6519 setPMProperty(dict
, "MachineState", MachineState
);
6520 if (DeviceOverrides
)
6521 dict
->setObject("PowerOverrideOn", kOSBooleanTrue
);
6523 if (IdleTimerPeriod
)
6529 clock_get_uptime(&now
);
6531 // The idle timer period in milliseconds.
6532 setPMProperty(dict
, "IdleTimerPeriod", IdleTimerPeriod
* 1000ULL);
6534 // The number of activity tickles recorded since device idle
6535 setPMProperty(dict
, "ActivityTickles", ActivityTickleCount
);
6537 if (AbsoluteTime_to_scalar(&DeviceActiveTimestamp
))
6539 // The number of milliseconds since the last activity tickle.
6541 SUB_ABSOLUTETIME(&delta
, &DeviceActiveTimestamp
);
6542 absolutetime_to_nanoseconds(delta
, &nsecs
);
6543 setPMProperty(dict
, "TimeSinceActivityTickle", NS_TO_MS(nsecs
));
6546 if (AbsoluteTime_to_scalar(&IdleTimerStartTime
))
6548 // The number of milliseconds since the last device idle.
6550 SUB_ABSOLUTETIME(&delta
, &IdleTimerStartTime
);
6551 absolutetime_to_nanoseconds(delta
, &nsecs
);
6552 setPMProperty(dict
, "TimeSinceDeviceIdle", NS_TO_MS(nsecs
));
6556 ok
= dict
->serialize(s
);
6560 return (ok
? kIOReturnSuccess
: kIOReturnNoMemory
);
6563 bool IOServicePM::serialize( OSSerialize
* s
) const
6565 IOReturn ret
= kIOReturnNotReady
;
6569 ret
= gIOPMWorkLoop
->runAction(
6570 OSMemberFunctionCast(IOWorkLoop::Action
, this, &IOServicePM::gatedSerialize
),
6571 (OSObject
*) this, (void *) s
);
6574 return (kIOReturnSuccess
== ret
);